Merge "Modifications in audio effect engine state management." into gingerbread
diff --git a/include/media/EffectApi.h b/include/media/EffectApi.h
index b4d738c..9f3d0b6 100644
--- a/include/media/EffectApi.h
+++ b/include/media/EffectApi.h
@@ -223,6 +223,11 @@
 //          samples as specified in output buffer descriptor. If the buffer descriptor
 //          is not specified the function must use either the buffer or the
 //          buffer provider function installed by the EFFECT_CMD_CONFIGURE command.
+//          The effect framework will call the process() function after the EFFECT_CMD_ENABLE
+//          command is received and until the EFFECT_CMD_DISABLE is received. When the engine
+//          receives the EFFECT_CMD_DISABLE command it should turn off the effect gracefully
+//          and when done indicate that it is OK to stop calling the process() function by
+//          returning the -ENODATA status.
 //
 //    NOTE: the process() function implementation should be "real-time safe" that is
 //      it should not perform blocking calls: malloc/free, sleep, read/write/open/close,
@@ -239,6 +244,8 @@
 //
 //    Output:
 //        returned value:    0 successful operation
+//                          -ENODATA the engine has finished the disable phase and the framework
+//                                  can stop calling process()
 //                          -EINVAL invalid interface handle or
 //                                  invalid input/output buffer description
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/media/libeffects/EffectEqualizer.cpp b/media/libeffects/EffectEqualizer.cpp
index d19c6b9..af0c411 100644
--- a/media/libeffects/EffectEqualizer.cpp
+++ b/media/libeffects/EffectEqualizer.cpp
@@ -30,6 +30,12 @@
 // effect_interface_t interface implementation for equalizer effect
 extern "C" const struct effect_interface_s gEqualizerInterface;
 
+enum equalizer_state_e {
+    EQUALIZER_STATE_UNINITIALIZED,
+    EQUALIZER_STATE_INITIALIZED,
+    EQUALIZER_STATE_ACTIVE,
+};
+
 namespace android {
 namespace {
 
@@ -100,6 +106,7 @@
     effect_config_t config;
     FormatAdapter adapter;
     AudioEqualizer * pEqualizer;
+    uint32_t state;
 };
 
 //--- local function prototypes
@@ -151,6 +158,7 @@
 
     pContext->itfe = &gEqualizerInterface;
     pContext->pEqualizer = NULL;
+    pContext->state = EQUALIZER_STATE_UNINITIALIZED;
 
     ret = Equalizer_init(pContext);
     if (ret < 0) {
@@ -160,6 +168,7 @@
     }
 
     *pInterface = (effect_interface_t)pContext;
+    pContext->state = EQUALIZER_STATE_INITIALIZED;
 
     LOGV("EffectLibCreateEffect %p, size %d", pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
 
@@ -175,6 +184,7 @@
         return -EINVAL;
     }
 
+    pContext->state = EQUALIZER_STATE_UNINITIALIZED;
     pContext->pEqualizer->free();
     delete pContext;
 
@@ -528,6 +538,13 @@
         return -EINVAL;
     }
 
+    if (pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
+        return -EINVAL;
+    }
+    if (pContext->state == EQUALIZER_STATE_INITIALIZED) {
+        return -ENODATA;
+    }
+
     pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
 
     return 0;
@@ -539,7 +556,7 @@
     android::EqualizerContext * pContext = (android::EqualizerContext *) self;
     int retsize;
 
-    if (pContext == NULL) {
+    if (pContext == NULL || pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
         return -EINVAL;
     }
 
@@ -594,10 +611,25 @@
                 p->data + p->psize);
         } break;
     case EFFECT_CMD_ENABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pContext->state != EQUALIZER_STATE_INITIALIZED) {
+            return -ENOSYS;
+        }
+        pContext->state = EQUALIZER_STATE_ACTIVE;
+        LOGV("EFFECT_CMD_ENABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
     case EFFECT_CMD_DISABLE:
         if (pReplyData == NULL || *replySize != sizeof(int)) {
             return -EINVAL;
         }
+        if (pContext->state != EQUALIZER_STATE_ACTIVE) {
+            return -ENOSYS;
+        }
+        pContext->state = EQUALIZER_STATE_INITIALIZED;
+        LOGV("EFFECT_CMD_DISABLE() OK");
         *(int *)pReplyData = 0;
         break;
     case EFFECT_CMD_SET_DEVICE:
diff --git a/media/libeffects/EffectReverb.c b/media/libeffects/EffectReverb.c
index 5c87f23..2ce7558 100644
--- a/media/libeffects/EffectReverb.c
+++ b/media/libeffects/EffectReverb.c
@@ -15,8 +15,7 @@
  */
 
 #define LOG_TAG "EffectReverb"
-//
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 #include <cutils/log.h>
 #include <stdlib.h>
 #include <string.h>
@@ -143,6 +142,8 @@
 
     module->itfe = &gReverbInterface;
 
+    module->context.mState = REVERB_STATE_UNINITIALIZED;
+
     if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
         preset = 1;
     }
@@ -158,6 +159,8 @@
 
     *pInterface = (effect_interface_t) module;
 
+    module->context.mState = REVERB_STATE_INITIALIZED;
+
     LOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));
 
     return 0;
@@ -171,6 +174,8 @@
         return -EINVAL;
     }
 
+    pRvbModule->context.mState = REVERB_STATE_UNINITIALIZED;
+
     free(pRvbModule);
     return 0;
 }
@@ -195,6 +200,13 @@
 
     pReverb = (reverb_object_t*) &pRvbModule->context;
 
+    if (pReverb->mState == REVERB_STATE_UNINITIALIZED) {
+        return -EINVAL;
+    }
+    if (pReverb->mState == REVERB_STATE_INITIALIZED) {
+        return -ENODATA;
+    }
+
     //if bypassed or the preset forces the signal to be completely dry
     if (pReverb->m_bBypass != 0) {
         if (inBuffer->raw != outBuffer->raw) {
@@ -257,13 +269,15 @@
     return 0;
 }
 
+
 static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize,
         void *pCmdData, int *replySize, void *pReplyData) {
     reverb_module_t *pRvbModule = (reverb_module_t *) self;
     reverb_object_t *pReverb;
     int retsize;
 
-    if (pRvbModule == NULL) {
+    if (pRvbModule == NULL ||
+            pRvbModule->context.mState == REVERB_STATE_UNINITIALIZED) {
         return -EINVAL;
     }
 
@@ -277,6 +291,9 @@
             return -EINVAL;
         }
         *(int *) pReplyData = Reverb_Init(pRvbModule, pReverb->m_Aux, pReverb->m_Preset);
+        if (*(int *) pReplyData == 0) {
+            pRvbModule->context.mState = REVERB_STATE_INITIALIZED;
+        }
         break;
     case EFFECT_CMD_CONFIGURE:
         if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
@@ -315,10 +332,25 @@
                 cmd->vsize, cmd->data + sizeof(int32_t));
         break;
     case EFFECT_CMD_ENABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pReverb->mState != REVERB_STATE_INITIALIZED) {
+            return -ENOSYS;
+        }
+        pReverb->mState = REVERB_STATE_ACTIVE;
+        LOGV("EFFECT_CMD_ENABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
     case EFFECT_CMD_DISABLE:
         if (pReplyData == NULL || *replySize != sizeof(int)) {
             return -EINVAL;
         }
+        if (pReverb->mState != REVERB_STATE_ACTIVE) {
+            return -ENOSYS;
+        }
+        pReverb->mState = REVERB_STATE_INITIALIZED;
+        LOGV("EFFECT_CMD_DISABLE() OK");
         *(int *)pReplyData = 0;
         break;
     case EFFECT_CMD_SET_DEVICE:
diff --git a/media/libeffects/EffectReverb.h b/media/libeffects/EffectReverb.h
index 5af316d..ee8e390 100644
--- a/media/libeffects/EffectReverb.h
+++ b/media/libeffects/EffectReverb.h
@@ -114,6 +114,12 @@
 #define AP1_GAIN_RANGE (int)(22936-6553)
 
 
+enum reverb_state_e {
+    REVERB_STATE_UNINITIALIZED,
+    REVERB_STATE_INITIALIZED,
+    REVERB_STATE_ACTIVE,
+};
+
 /* parameters for each allpass */
 typedef struct
 {
@@ -279,6 +285,7 @@
     uint16_t            m_Aux;                // if TRUE, is connected as auxiliary effect
     uint16_t            m_Preset;             // if TRUE, expose preset revert interface
 
+    uint32_t            mState;
 } reverb_object_t;
 
 
diff --git a/media/libeffects/EffectVisualizer.cpp b/media/libeffects/EffectVisualizer.cpp
index f27e296..bcda06e 100644
--- a/media/libeffects/EffectVisualizer.cpp
+++ b/media/libeffects/EffectVisualizer.cpp
@@ -231,7 +231,7 @@
         return -EINVAL;
     }
     if (pContext->mState != VISUALIZER_STATE_ACTIVE) {
-        return -ENOSYS;
+        return -ENODATA;
     }
 
     if (inBuffer == NULL || inBuffer->raw == NULL ||