Merge "Issue 2667802: [Audio Effect Framework] AudioEffect base class and JNI." into kraken
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
new file mode 100644
index 0000000..2bdba2d
--- /dev/null
+++ b/include/media/AudioEffect.h
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2009 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 ANDROID_AUDIOEFFECT_H
+#define ANDROID_AUDIOEFFECT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <media/EffectApi.h>
+#include <media/AudioSystem.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class effect_param_cblk_t;
+
+// ----------------------------------------------------------------------------
+
+class AudioEffect : public RefBase
+{
+public:
+
+    /*
+     *  Static methods for effect libraries management.
+     */
+
+    /*
+     *   Loads the effect library which path is given as first argument.
+     *   This must be the full path of a dynamic library (.so) implementing one or
+     *   more effect engines and exposing the effect library interface described in
+     *   EffectApi.h. The function returns a handle on the library for use by
+     *   further call to unloadEffectLibrary() to unload the library.
+     *
+     *   Parameters:
+     *          libPath:    full path of the dynamic library file in the file system.
+     *          handle:     address where to return the library handle
+     *
+     *   Returned status (from utils/Errors.h) can be:
+     *          NO_ERROR    successful operation.
+     *          PERMISSION_DENIED could not get AudioFlinger interface or
+     *                      application does not have permission to configure audio
+     *          NO_INIT     effect factory not initialized or
+     *                      library could not be loaded or
+     *                      library does not implement required functions
+     *          BAD_VALUE   invalid libPath string or handle
+     *
+     *   Returned value:
+     *          *handle updated with library handle
+     */
+    static status_t loadEffectLibrary(const char *libPath, int *handle);
+
+    /*
+     *   Unloads the effect library which handle is given as argument.
+     *
+     *   Parameters:
+     *          handle: library handle
+     *
+     *   Returned status (from utils/Errors.h) can be:
+     *          NO_ERROR    successful operation.
+     *          PERMISSION_DENIED could not get AudioFlinger interface or
+     *                      application does not have permission to configure audio
+     *          NO_INIT     effect factory not initialized
+     *          BAD_VALUE   invalid handle
+     */
+    static status_t unloadEffectLibrary(int handle);
+
+    /*
+     *  Static methods for effects enumeration.
+     */
+
+    /*
+     * Returns the number of effects available. This method together
+     * with EffectQueryNext() is used to enumerate all effects:
+     * The enumeration sequence is:
+     *      QueryNumberEffects(&num_effects);
+     *      while (num_effects--)
+     *          QueryNextEffect();
+     *
+     * Parameters:
+     *      pNumEffects:    address where the number of effects should be returned.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR   successful operation.
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *      NO_INIT    effect library failed to initialize
+     *      BAD_VALUE  invalid numEffects pointer
+     *
+     * Returned value
+     *   *numEffects:     updated with number of effects available
+     */
+    static status_t queryNumberEffects(uint32_t *numEffects);
+
+    /*
+     * Returns number effect descriptor during effect
+     * enumeration.
+     *
+     * Parameters:
+     *      pDescriptor:    address where the effect descriptor should be returned.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR        successful operation.
+     *      NAME_NOT_FOUND  no more effect available
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *      NO_INIT         effect library failed to initialize
+     *      BAD_VALUE       invalid descriptor pointer
+     *      INVALID_OPERATION  effect list has changed since last execution of queryNumberEffects()
+     *
+     * Returned value
+     *   *descriptor:     updated with effect descriptor
+     */
+    static status_t queryNextEffect(effect_descriptor_t *descriptor);
+
+
+    /*
+     * Returns the descriptor for the specified effect uuid.
+     *
+     * Parameters:
+     *      uuid:       pointer to effect uuid.
+     *      descriptor: address where the effect descriptor should be returned.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR        successful operation.
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *      NO_INIT         effect library failed to initialize
+     *      BAD_VALUE       invalid uuid or descriptor pointers
+     *      NAME_NOT_FOUND  no effect with this uuid found
+     *
+     * Returned value
+     *   *descriptor updated with effect descriptor
+     */
+    static status_t getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor);
+
+
+    /*
+     * Events used by callback function (effect_callback_t).
+     */
+    enum event_type {
+        EVENT_CONTROL_STATUS_CHANGED = 0,
+        EVENT_ENABLE_STATUS_CHANGED = 1,
+        EVENT_PARAMETER_CHANGED = 2,
+        EVENT_ERROR = 3
+    };
+
+    /* Callback function notifying client application of a change in effect engine state or
+     * configuration.
+     * An effect engine can be shared by several applications but only one has the control
+     * of the engine activity and configuration at a time.
+     * The EVENT_CONTROL_STATUS_CHANGED event is received when an application loses or
+     * retrieves the control of the effect engine. Loss of control happens
+     * if another application requests the use of the engine by creating an AudioEffect for
+     * the same effect type but with a higher priority. Control is returned when the
+     * application having the control deletes its AudioEffect object.
+     * The EVENT_ENABLE_STATUS_CHANGED event is received by all applications not having the
+     * control of the effect engine when the effect is enabled or disabled.
+     * The EVENT_PARAMETER_CHANGED event is received by all applications not having the
+     * control of the effect engine when an effect parameter is changed.
+     * The EVENT_ERROR event is received when the media server process dies.
+     *
+     * Parameters:
+     *
+     * event:   type of event notified (see enum AudioEffect::event_type).
+     * user:    Pointer to context for use by the callback receiver.
+     * info:    Pointer to optional parameter according to event type:
+     *  - EVENT_CONTROL_STATUS_CHANGED:  boolean indicating if control is granted (true)
+     *  or stolen (false).
+     *  - EVENT_ENABLE_STATUS_CHANGED: boolean indicating if effect is now enabled (true)
+     *  or disabled (false).
+     *  - EVENT_PARAMETER_CHANGED: pointer to a effect_param_t structure.
+     *  - EVENT_ERROR:  status_t indicating the error (DEAD_OBJECT when media server dies).
+     */
+
+    typedef void (*effect_callback_t)(int32_t event, void* user, void *info);
+
+
+    /* Constructor.
+     * AudioEffect is the base class for creating and controlling an effect engine from
+     * the application process. Creating an AudioEffect object will create the effect engine
+     * in the AudioFlinger if no engine of the specified type exists. If one exists, this engine
+     * will be used. The application creating the AudioEffect object (or a derived class like
+     * Reverb for instance) will either receive control of the effect engine or not, depending
+     * on the priority parameter. If priority is higher than the priority used by the current
+     * effect engine owner, the control will be transfered to the new application. Otherwise
+     * control will remain to the previous application. In this case, the new application will be
+     * notified of changes in effect engine state or control ownership by the effect callback.
+     * After creating the AudioEffect, the application must call the initCheck() method and
+     * check the creation status before trying to control the effect engine (see initCheck()).
+     * If the effect is to be applied to an AudioTrack or MediaPlayer only the application
+     * must specify the audio session ID corresponding to this player.
+     */
+
+    /* Simple Constructor.
+     */
+    AudioEffect();
+
+
+    /* Constructor.
+     *
+     * Parameters:
+     *
+     * type:  type of effect created: can be null if uuid is specified. This corresponds to
+     *        the OpenSL ES interface implemented by this effect.
+     * uuid:  Uuid of effect created: can be null if type is specified. This uuid corresponds to
+     *        a particular implementation of an effect type.
+     * 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.
+     * cbf:         optional callback function (see effect_callback_t)
+     * user:        pointer to context for use by the callback receiver.
+     * sessionID:   audio session this effect is associated to. If 0, the effect will be global to
+     *      the output mix. If not 0, the effect will be applied to all players
+     *      (AudioTrack or MediaPLayer) within the same audio session.
+     * output:  HAL audio output stream to which this effect must be attached. Leave at 0 for
+     *      automatic output selection by AudioFlinger.
+     */
+
+    AudioEffect(const effect_uuid_t *type,
+                const effect_uuid_t *uuid = NULL,
+                  int32_t priority = 0,
+                  effect_callback_t cbf = 0,
+                  void* user = 0,
+                  int sessionId = 0,
+                  audio_io_handle_t output = 0
+                  );
+
+    /* Constructor.
+     *      Same as above but with type and uuid specified by character strings
+     */
+    AudioEffect(const char *typeStr,
+                    const char *uuidStr = NULL,
+                    int32_t priority = 0,
+                    effect_callback_t cbf = 0,
+                    void* user = 0,
+                    int sessionId = 0,
+                    audio_io_handle_t output = 0
+                    );
+
+    /* Terminates the AudioEffect and unregisters it from AudioFlinger.
+     * The effect engine is also destroyed if this AudioEffect was the last controlling
+     * the engine.
+     */
+                        ~AudioEffect();
+
+    /* Initialize an uninitialized AudioEffect.
+    * Returned status (from utils/Errors.h) can be:
+    *  - NO_ERROR or ALREADY_EXISTS: successful initialization
+    *  - INVALID_OPERATION: AudioEffect is already initialized
+    *  - BAD_VALUE: invalid parameter
+    *  - NO_INIT: audio flinger or audio hardware not initialized
+    * */
+            status_t    set(const effect_uuid_t *type,
+                            const effect_uuid_t *uuid = NULL,
+                            int32_t priority = 0,
+                            effect_callback_t cbf = 0,
+                            void* user = 0,
+                            int sessionId = 0,
+                            audio_io_handle_t output = 0
+                            );
+
+    /* Result of constructing the AudioEffect. This must be checked
+     * before using any AudioEffect API.
+     * initCheck() can return:
+     *  - NO_ERROR:    the effect engine is successfully created and the application has control.
+     *  - ALREADY_EXISTS: the effect engine is successfully created but the application does not
+     *              have control.
+     *  - NO_INIT:     the effect creation failed.
+     *
+     */
+            status_t    initCheck() const;
+
+
+    /* Returns the unique effect Id for the controlled effect engine. This ID is unique
+     * system wide and is used for instance in the case of auxiliary effects to attach
+     * the effect to an AudioTrack or MediaPlayer.
+     *
+     */
+            int32_t     id() const { return mId; }
+
+    /* Returns a descriptor for the effect (see effect_descriptor_t in EffectApi.h).
+     */
+            effect_descriptor_t descriptor() const;
+
+    /* Returns effect control priority of this AudioEffect object.
+     */
+            int32_t     priority() const { return mPriority; }
+
+
+    /* Enables the effect engine.
+     *
+     * Parameters:
+     *      None.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation
+     *  - INVALID_OPERATION: the application does not have control of the effect engine
+     */
+            status_t    enable();
+
+    /* Disables the effect engine.
+     *
+     * Parameters:
+     *      None.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation
+     *  - INVALID_OPERATION: the application does not have control of the effect engine
+     */
+             status_t    disable();
+
+             bool        isEnabled() const;
+
+    /* Sets a parameter value.
+     *
+     * Parameters:
+     *      param:  pointer to effect_param_t structure containing the parameter
+     *          and its value (See EffectApi.h).
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation.
+     *  - INVALID_OPERATION: the application does not have control of the effect engine.
+     *  - BAD_VALUE: invalid parameter identifier or value.
+     *  - DEAD_OBJECT: the effect engine has been deleted.
+     */
+             status_t   setParameter(effect_param_t *param);
+
+    /* Prepare a new parameter value that will be set by next call to
+     * setParameterCommit(). This method can be used to set multiple parameters
+     * in a synchronous manner or to avoid multiple binder calls for each
+     * parameter.
+     *
+     * Parameters:
+     *      param:  pointer to effect_param_t structure containing the parameter
+     *          and its value (See EffectApi.h).
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation.
+     *  - INVALID_OPERATION: the application does not have control of the effect engine.
+     *  - NO_MEMORY: no more space available in shared memory used for deferred parameter
+     *  setting.
+     */
+             status_t   setParameterDeferred(effect_param_t *param);
+
+     /* Commit all parameter values previously prepared by setParameterDeferred().
+      *
+      * Parameters:
+      *     none
+      *
+      * Returned status (from utils/Errors.h) can be:
+      *  - NO_ERROR: successful operation.
+      *  - INVALID_OPERATION: No new parameter values ready for commit.
+      *  - BAD_VALUE: invalid parameter identifier or value: there is no indication
+      *     as to which of the parameters caused this error.
+      *  - DEAD_OBJECT: the effect engine has been deleted.
+      */
+             status_t   setParameterCommit();
+
+    /* Gets a parameter value.
+     *
+     * Parameters:
+     *      param:  pointer to effect_param_t structure containing the parameter
+     *          and the returned value (See EffectApi.h).
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation.
+     *  - INVALID_OPERATION: the AudioEffect was not successfully initialized.
+     *  - BAD_VALUE: invalid parameter identifier.
+     *  - DEAD_OBJECT: the effect engine has been deleted.
+     */
+             status_t   getParameter(effect_param_t *param);
+
+     /* Sends a command and receives a response to/from effect engine.
+      *     See EffectApi.h for details on effect command() function, valid command codes
+      *     and formats.
+      */
+             status_t command(int32_t cmdCode, int32_t cmdSize, void *cmdData, int32_t *replySize, void *replyData);
+
+
+     /*
+      * Utility functions.
+      */
+
+     /* Converts the string passed as first argument to the effect_uuid_t
+      * pointed to by second argument
+      */
+     static status_t stringToGuid(const char *str, effect_uuid_t *guid);
+     /* Converts the effect_uuid_t pointed to by first argument to the
+      * string passed as second argument
+      */
+     static status_t guidToString(const effect_uuid_t *guid, char *str, size_t maxLen);
+
+private:
+
+     // Implements the IEffectClient interface
+    class EffectClient : public android::BnEffectClient,  public android::IBinder::DeathRecipient
+    {
+    public:
+
+        EffectClient(AudioEffect *effect) : mEffect(effect){}
+
+        // IEffectClient
+        virtual void controlStatusChanged(bool controlGranted) {mEffect->controlStatusChanged(controlGranted);}
+        virtual void enableStatusChanged(bool enabled) {mEffect->enableStatusChanged(enabled);}
+        virtual void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData) {
+            mEffect->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+        }
+
+        // IBinder::DeathRecipient
+        virtual void binderDied(const wp<IBinder>& who) {mEffect->binderDied();}
+
+    private:
+        AudioEffect *mEffect;
+    };
+
+
+    friend class EffectClient;
+
+    // IEffectClient
+    void controlStatusChanged(bool controlGranted);
+    void enableStatusChanged(bool enabled);
+    void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData);
+    void binderDied();
+
+
+    sp<IEffect>             mIEffect;           // IEffect binder interface
+    sp<EffectClient>        mIEffectClient;     // IEffectClient implementation
+    sp<IMemory>             mCblkMemory;        // shared memory for deferred parameter setting
+    effect_param_cblk_t*    mCblk;              // control block for deferred parameter setting
+    int32_t                 mPriority;          // priority for effect control
+    status_t                mStatus;            // effect status
+    volatile int32_t        mEnabled;           // enable state
+    effect_callback_t       mCbf;               // callback function for status, control, parameter changes notifications
+    void*                   mUserData;          // client context for callback function
+    effect_descriptor_t     mDescriptor;        // effect descriptor
+    int32_t                 mId;                // system wide unique effect engine instance identifier
+    int32_t                 mSessionId;         // audio session ID
+};
+
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOEFFECT_H
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 29cd2ee..7908f5d 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -28,7 +28,8 @@
     IMediaDeathNotifier.cpp \
     MediaProfiles.cpp \
     IEffect.cpp \
-    IEffectClient.cpp
+    IEffectClient.cpp \
+    AudioEffect.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
new file mode 100644
index 0000000..8648211
--- /dev/null
+++ b/media/libmedia/AudioEffect.cpp
@@ -0,0 +1,462 @@
+/*
+**
+** Copyright 2010, 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_NDEBUG 0
+#define LOG_TAG "AudioEffect"
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <private/media/AudioEffectShared.h>
+#include <media/AudioEffect.h>
+
+#include <utils/Log.h>
+#include <cutils/atomic.h>
+#include <binder/IPCThreadState.h>
+
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+AudioEffect::AudioEffect()
+    : mStatus(NO_INIT)
+{
+}
+
+
+AudioEffect::AudioEffect(const effect_uuid_t *type,
+                const effect_uuid_t *uuid,
+                int32_t priority,
+                effect_callback_t cbf,
+                void* user,
+                int sessionId,
+                audio_io_handle_t output
+                )
+    : mStatus(NO_INIT)
+{
+    mStatus = set(type, uuid, priority, cbf, user, output, sessionId);
+}
+
+AudioEffect::AudioEffect(const char *typeStr,
+                const char *uuidStr,
+                int32_t priority,
+                effect_callback_t cbf,
+                void* user,
+                int sessionId,
+                audio_io_handle_t output
+                )
+    : mStatus(NO_INIT)
+{
+    effect_uuid_t type;
+    effect_uuid_t *pType = NULL;
+    effect_uuid_t uuid;
+    effect_uuid_t *pUuid = NULL;
+
+    LOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);
+
+    if (typeStr != NULL) {
+        if (stringToGuid(typeStr, &type) == NO_ERROR) {
+            pType = &type;
+        }
+    }
+
+    if (uuidStr != NULL) {
+        if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
+            pUuid = &uuid;
+        }
+    }
+
+    mStatus = set(pType, pUuid, priority, cbf, user, output, sessionId);
+}
+
+status_t AudioEffect::set(const effect_uuid_t *type,
+                const effect_uuid_t *uuid,
+                int32_t priority,
+                effect_callback_t cbf,
+                void* user,
+                int sessionId,
+                audio_io_handle_t output)
+{
+    sp<IEffect> iEffect;
+    sp<IMemory> cblk;
+    int enabled;
+
+    LOGV("set %p mUserData: %p", this, user);
+
+    if (mIEffect != 0) {
+        LOGW("Effect already in use");
+        return INVALID_OPERATION;
+    }
+
+    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+    if (audioFlinger == 0) {
+        LOGE("set(): Could not get audioflinger");
+        return NO_INIT;
+    }
+
+    if (type == NULL && uuid == NULL) {
+        LOGW("Must specify at least type or uuid");
+        return BAD_VALUE;
+    }
+
+    mPriority = priority;
+    mCbf = cbf;
+    mUserData = user;
+    mSessionId = sessionId;
+
+    memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
+    memcpy(&mDescriptor.type, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
+    memcpy(&mDescriptor.uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
+
+    if (type != NULL) {
+        memcpy(&mDescriptor.type, type, sizeof(effect_uuid_t));
+    }
+    if (uuid != NULL) {
+        memcpy(&mDescriptor.uuid, uuid, sizeof(effect_uuid_t));
+    }
+
+    mIEffectClient = new EffectClient(this);
+
+    iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,
+            mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled);
+
+    if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
+        LOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
+        return mStatus;
+    }
+
+    mEnabled = (volatile int32_t)enabled;
+
+    mIEffect = iEffect;
+    cblk = iEffect->getCblk();
+    if (cblk == 0) {
+        mStatus = NO_INIT;
+        LOGE("Could not get control block");
+        return mStatus;
+    }
+
+    mIEffect = iEffect;
+    mCblkMemory = cblk;
+    mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
+    int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
+    mCblk->buffer = (uint8_t *)mCblk + bufOffset;
+
+    iEffect->asBinder()->linkToDeath(mIEffectClient);
+    LOGV("set() %p OK effect: %s id: %d status %d enabled %d, ", this, mDescriptor.name, mId, mStatus, mEnabled);
+
+    return mStatus;
+}
+
+
+AudioEffect::~AudioEffect()
+{
+    LOGV("Destructor %p", this);
+
+    if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
+        disable();
+        if (mIEffect != NULL) {
+            mIEffect->disconnect();
+            mIEffect->asBinder()->unlinkToDeath(mIEffectClient);
+        }
+         IPCThreadState::self()->flushCommands();
+    }
+    mIEffect.clear();
+    mIEffectClient.clear();
+    mCblkMemory.clear();
+}
+
+
+status_t AudioEffect::initCheck() const
+{
+    return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+effect_descriptor_t AudioEffect::descriptor() const
+{
+    return mDescriptor;
+}
+
+bool AudioEffect::isEnabled() const
+{
+    return (mEnabled != 0);
+}
+
+status_t AudioEffect::enable()
+{
+    if (mStatus != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+    LOGV("enable %p", this);
+
+    if (android_atomic_or(1, &mEnabled) == 0) {
+       return mIEffect->enable();
+    }
+
+    return INVALID_OPERATION;
+}
+
+status_t AudioEffect::disable()
+{
+    if (mStatus != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+    LOGV("disable %p", this);
+
+    if (android_atomic_and(~1, &mEnabled) == 1) {
+       return mIEffect->disable();
+    }
+
+    return INVALID_OPERATION;
+}
+
+status_t AudioEffect::command(int32_t cmdCode, int32_t cmdSize, void *cmdData, int32_t *replySize, void *replyData)
+{
+    if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+        return INVALID_OPERATION;
+    }
+
+    return mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
+}
+
+
+status_t AudioEffect::setParameter(effect_param_t *param)
+{
+    if (mStatus != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+
+    if (param == NULL || param->psize == 0 || param->vsize == 0) {
+        return BAD_VALUE;
+    }
+
+    int size = sizeof(int);
+    int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+
+    LOGV("setParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
+
+    return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size, &param->status);
+}
+
+status_t AudioEffect::setParameterDeferred(effect_param_t *param)
+{
+    if (mStatus != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+
+    if (param == NULL || param->psize == 0 || param->vsize == 0) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mCblk->lock);
+
+    int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+    int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
+
+    if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
+        return NO_MEMORY;
+    }
+    int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
+    *p++ = size;
+    memcpy(p, param, sizeof(effect_param_t) + psize);
+    mCblk->clientIndex += size;
+
+    return NO_ERROR;
+}
+
+status_t AudioEffect::setParameterCommit()
+{
+    if (mStatus != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+
+    Mutex::Autolock _l(mCblk->lock);
+    if (mCblk->clientIndex == 0) {
+        return INVALID_OPERATION;
+    }
+    int size = 0;
+    return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
+}
+
+status_t AudioEffect::getParameter(effect_param_t *param)
+{
+    if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+        return INVALID_OPERATION;
+    }
+
+    if (param == NULL || param->psize == 0 || param->vsize == 0) {
+        return BAD_VALUE;
+    }
+
+    LOGV("getParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
+
+    int psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+
+    return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param, &psize, param);
+}
+
+
+// -------------------------------------------------------------------------
+
+void AudioEffect::binderDied()
+{
+    LOGW("IEffect died");
+    mStatus = NO_INIT;
+    if (mCbf) {
+        status_t status = DEAD_OBJECT;
+        mCbf(EVENT_ERROR, mUserData, &status);
+    }
+    mIEffect.clear();
+}
+
+// -------------------------------------------------------------------------
+
+void AudioEffect::controlStatusChanged(bool controlGranted)
+{
+    LOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf, mUserData);
+    if (controlGranted) {
+        if (mStatus == ALREADY_EXISTS) {
+            mStatus = NO_ERROR;
+        }
+    } else {
+        if (mStatus == NO_ERROR) {
+            mStatus = ALREADY_EXISTS;
+        }
+    }
+    if (mCbf) {
+        mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
+    }
+}
+
+void AudioEffect::enableStatusChanged(bool enabled)
+{
+    LOGV("enableStatusChanged %p enabled %d", this, enabled);
+    if (mStatus == ALREADY_EXISTS) {
+        mEnabled = enabled;
+        if (mCbf) {
+            mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
+        }
+    }
+}
+
+void AudioEffect::commandExecuted(int cmdCode, int cmdSize, void *cmdData, int replySize, void *replyData)
+{
+    if (cmdData == NULL || replyData == NULL) {
+        return;
+    }
+
+    if (mCbf && cmdCode == EFFECT_CMD_SET_PARAM) {
+        effect_param_t *cmd = (effect_param_t *)cmdData;
+        cmd->status = *(int32_t *)replyData;
+        mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
+    }
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioEffect::loadEffectLibrary(const char *libPath, int *handle)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->loadEffectLibrary(libPath, handle);
+}
+
+status_t AudioEffect::unloadEffectLibrary(int handle)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->unloadEffectLibrary(handle);
+}
+
+status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->queryNumberEffects(numEffects);
+}
+
+status_t AudioEffect::queryNextEffect(effect_descriptor_t *descriptor)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->queryNextEffect(descriptor);
+}
+
+status_t AudioEffect::getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->getEffectDescriptor(uuid, descriptor);
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
+{
+    if (str == NULL || guid == NULL) {
+        return BAD_VALUE;
+    }
+
+    int tmp[10];
+
+    if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+            tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
+        return BAD_VALUE;
+    }
+    guid->timeLow = (uint32_t)tmp[0];
+    guid->timeMid = (uint16_t)tmp[1];
+    guid->timeHiAndVersion = (uint16_t)tmp[2];
+    guid->clockSeq = (uint16_t)tmp[3];
+    guid->node[0] = (uint8_t)tmp[4];
+    guid->node[1] = (uint8_t)tmp[5];
+    guid->node[2] = (uint8_t)tmp[6];
+    guid->node[3] = (uint8_t)tmp[7];
+    guid->node[4] = (uint8_t)tmp[8];
+    guid->node[5] = (uint8_t)tmp[9];
+
+    return NO_ERROR;
+}
+
+status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
+{
+    if (guid == NULL || str == NULL) {
+        return BAD_VALUE;
+    }
+
+    snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+            guid->timeLow,
+            guid->timeMid,
+            guid->timeHiAndVersion,
+            guid->clockSeq,
+            guid->node[0],
+            guid->node[1],
+            guid->node[2],
+            guid->node[3],
+            guid->node[4],
+            guid->node[5]);
+
+    return NO_ERROR;
+}
+
+
+}; // namespace android
+