Abstract away access to audio effects HAL and factory

In this CL all direct calls to functions from EffectsFactoryApi.h
and hardware/audio_effect.h are encapsulated within two new
classes: EffectsFactoryHalLocal and EffectHalLocal. AudioFlinger
uses interface classes EffectsFactoryHalInterface and
EffectHalInterface to access these functions.

Bug: 30222631
Change-Id: Id64b9c5529319077f6f968921489a13f60daa977
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 05dacac..c989563 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -28,6 +28,8 @@
     AudioHwDevice.cpp           \
     AudioStreamOut.cpp          \
     SpdifStreamOut.cpp          \
+    EffectHalLocal.cpp          \
+    EffectsFactoryHalLocal.cpp	\
     Effects.cpp                 \
     AudioMixer.cpp.arm          \
     BufferProviders.cpp         \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 121ff9d..fce69ad 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -44,11 +44,11 @@
 
 #include "AudioMixer.h"
 #include "AudioFlinger.h"
+#include "EffectsFactoryHalInterface.h"
 #include "ServiceUtilities.h"
 
 #include <media/AudioResamplerPublic.h>
 
-#include <media/EffectsFactoryApi.h>
 #include <audio_effects/effect_visualizer.h>
 #include <audio_effects/effect_ns.h>
 #include <audio_effects/effect_aec.h>
@@ -85,6 +85,7 @@
 static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
 static const char kHardwareLockedString[] = "Hardware lock is taken\n";
 static const char kClientLockedString[] = "Client lock is taken\n";
+static const char kNoEffectsFactory[] = "Effects Factory is absent\n";
 
 
 nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
@@ -205,6 +206,8 @@
     // in bad state, reset the state upon service start.
     BatteryNotifier::getInstance().noteResetAudio();
 
+    mEffectsFactoryHal = EffectsFactoryHalInterface::create();
+
 #ifdef TEE_SINK
     char value[PROPERTY_VALUE_MAX];
     (void) property_get("ro.debuggable", value, "0");
@@ -422,7 +425,12 @@
             write(fd, result.string(), result.size());
         }
 
-        EffectDumpEffects(fd);
+        if (mEffectsFactoryHal.get() != NULL) {
+            mEffectsFactoryHal->dumpEffects(fd);
+        } else {
+            String8 result(kNoEffectsFactory);
+            write(fd, result.string(), result.size());
+        }
 
         dumpClients(fd, args);
         if (clientLocked) {
@@ -2593,24 +2601,39 @@
 //  Effect management
 // ----------------------------------------------------------------------------
 
+sp<EffectsFactoryHalInterface> AudioFlinger::getEffectsFactory() {
+    return mEffectsFactoryHal;
+}
 
 status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
 {
     Mutex::Autolock _l(mLock);
-    return EffectQueryNumberEffects(numEffects);
+    if (mEffectsFactoryHal.get()) {
+        return mEffectsFactoryHal->queryNumberEffects(numEffects);
+    } else {
+        return -ENODEV;
+    }
 }
 
 status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
 {
     Mutex::Autolock _l(mLock);
-    return EffectQueryEffect(index, descriptor);
+    if (mEffectsFactoryHal.get()) {
+        return mEffectsFactoryHal->getDescriptor(index, descriptor);
+    } else {
+        return -ENODEV;
+    }
 }
 
 status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
         effect_descriptor_t *descriptor) const
 {
     Mutex::Autolock _l(mLock);
-    return EffectGetDescriptor(pUuid, descriptor);
+    if (mEffectsFactoryHal.get()) {
+        return mEffectsFactoryHal->getDescriptor(pUuid, descriptor);
+    } else {
+        return -ENODEV;
+    }
 }
 
 
@@ -2630,8 +2653,8 @@
     effect_descriptor_t desc;
 
     pid_t pid = IPCThreadState::self()->getCallingPid();
-    ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d",
-            pid, effectClient.get(), priority, sessionId, io);
+    ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d, factory %p",
+            pid, effectClient.get(), priority, sessionId, io, mEffectsFactoryHal.get());
 
     if (pDesc == NULL) {
         lStatus = BAD_VALUE;
@@ -2651,10 +2674,15 @@
         goto Exit;
     }
 
+    if (mEffectsFactoryHal.get() == NULL) {
+        lStatus = NO_INIT;
+        goto Exit;
+    }
+
     {
-        if (!EffectIsNullUuid(&pDesc->uuid)) {
+        if (!EffectsFactoryHalInterface::isNullUuid(&pDesc->uuid)) {
             // if uuid is specified, request effect descriptor
-            lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
+            lStatus = mEffectsFactoryHal->getDescriptor(&pDesc->uuid, &desc);
             if (lStatus < 0) {
                 ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
                 goto Exit;
@@ -2662,7 +2690,7 @@
         } else {
             // if uuid is not specified, look for an available implementation
             // of the required type in effect factory
-            if (EffectIsNullUuid(&pDesc->type)) {
+            if (EffectsFactoryHalInterface::isNullUuid(&pDesc->type)) {
                 ALOGW("createEffect() no effect type");
                 lStatus = BAD_VALUE;
                 goto Exit;
@@ -2672,13 +2700,13 @@
             d.flags = 0; // prevent compiler warning
             bool found = false;
 
-            lStatus = EffectQueryNumberEffects(&numEffects);
+            lStatus = mEffectsFactoryHal->queryNumberEffects(&numEffects);
             if (lStatus < 0) {
                 ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
                 goto Exit;
             }
             for (uint32_t i = 0; i < numEffects; i++) {
-                lStatus = EffectQueryEffect(i, &desc);
+                lStatus = mEffectsFactoryHal->getDescriptor(i, &desc);
                 if (lStatus < 0) {
                     ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
                     continue;
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index cde3d93..3eba461 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -72,6 +72,7 @@
 class AudioMixer;
 class AudioBuffer;
 class AudioResampler;
+class EffectsFactoryHalInterface;
 class FastMixer;
 class PassthruBufferProvider;
 class ServerProxy;
@@ -272,6 +273,7 @@
 
     sp<NBLog::Writer>   newWriter_l(size_t size, const char *name);
     void                unregisterWriter(const sp<NBLog::Writer>& writer);
+    sp<EffectsFactoryHalInterface> getEffectsFactory();
 private:
     static const size_t kLogMemorySize = 40 * 1024;
     sp<MemoryDealer>    mLogMemoryDealer;   // == 0 when NBLog is disabled
@@ -762,6 +764,7 @@
     nsecs_t mGlobalEffectEnableTime;  // when a global effect was last enabled
 
     sp<PatchPanel> mPatchPanel;
+    sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
 
     bool        mSystemReady;
 };
diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp
index 7b6dfcb..c1ff1af 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/services/audioflinger/BufferProviders.cpp
@@ -21,12 +21,13 @@
 #include <audio_utils/primitives.h>
 #include <audio_utils/format.h>
 #include <media/AudioResamplerPublic.h>
-#include <media/EffectsFactoryApi.h>
 
 #include <utils/Log.h>
 
 #include "Configuration.h"
 #include "BufferProviders.h"
+#include "EffectHalInterface.h"
+#include "EffectsFactoryHalInterface.h"
 
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
@@ -145,13 +146,22 @@
     ALOGV("DownmixerBufferProvider(%p)(%#x, %#x, %#x %u %d)",
             this, inputChannelMask, outputChannelMask, format,
             sampleRate, sessionId);
-    if (!sIsMultichannelCapable
-            || EffectCreate(&sDwnmFxDesc.uuid,
-                    sessionId,
-                    SESSION_ID_INVALID_AND_IGNORED,
-                    &mDownmixHandle) != 0) {
+    if (!sIsMultichannelCapable) {
+        ALOGE("DownmixerBufferProvider() error: not multichannel capable");
+        return;
+    }
+    mEffectsFactory = EffectsFactoryHalInterface::create();
+    if (mEffectsFactory.get() == NULL) {
+        ALOGE("DownmixerBufferProvider() error: could not obtain the effects factory");
+        return;
+    }
+    if (mEffectsFactory->createEffect(&sDwnmFxDesc.uuid,
+                                      sessionId,
+                                      SESSION_ID_INVALID_AND_IGNORED,
+                                      &mDownmixInterface) != 0) {
          ALOGE("DownmixerBufferProvider() error creating downmixer effect");
-         mDownmixHandle = NULL;
+         mDownmixInterface.clear();
+         mEffectsFactory.clear();
          return;
      }
      // channel input configuration will be overridden per-track
@@ -173,28 +183,28 @@
      uint32_t replySize = sizeof(int);
 
      // Configure downmixer
-     status_t status = (*mDownmixHandle)->command(mDownmixHandle,
+     status_t status = mDownmixInterface->command(
              EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
              &mDownmixConfig /*pCmdData*/,
              &replySize, &cmdStatus /*pReplyData*/);
      if (status != 0 || cmdStatus != 0) {
          ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while configuring downmixer",
                  status, cmdStatus);
-         EffectRelease(mDownmixHandle);
-         mDownmixHandle = NULL;
+         mDownmixInterface.clear();
+         mEffectsFactory.clear();
          return;
      }
 
      // Enable downmixer
      replySize = sizeof(int);
-     status = (*mDownmixHandle)->command(mDownmixHandle,
+     status = mDownmixInterface->command(
              EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
              &replySize, &cmdStatus /*pReplyData*/);
      if (status != 0 || cmdStatus != 0) {
          ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while enabling downmixer",
                  status, cmdStatus);
-         EffectRelease(mDownmixHandle);
-         mDownmixHandle = NULL;
+         mDownmixInterface.clear();
+         mEffectsFactory.clear();
          return;
      }
 
@@ -211,15 +221,15 @@
      param->vsize = sizeof(downmix_type_t);
      memcpy(param->data + psizePadded, &downmixType, param->vsize);
      replySize = sizeof(int);
-     status = (*mDownmixHandle)->command(mDownmixHandle,
+     status = mDownmixInterface->command(
              EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize /* cmdSize */,
              param /*pCmdData*/, &replySize, &cmdStatus /*pReplyData*/);
      free(param);
      if (status != 0 || cmdStatus != 0) {
          ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while setting downmix type",
                  status, cmdStatus);
-         EffectRelease(mDownmixHandle);
-         mDownmixHandle = NULL;
+         mDownmixInterface.clear();
+         mEffectsFactory.clear();
          return;
      }
      ALOGV("DownmixerBufferProvider() downmix type set to %d", (int) downmixType);
@@ -228,8 +238,6 @@
 DownmixerBufferProvider::~DownmixerBufferProvider()
 {
     ALOGV("~DownmixerBufferProvider (%p)", this);
-    EffectRelease(mDownmixHandle);
-    mDownmixHandle = NULL;
 }
 
 void DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
@@ -239,7 +247,7 @@
     mDownmixConfig.outputCfg.buffer.frameCount = frames;
     mDownmixConfig.outputCfg.buffer.raw = dst;
     // may be in-place if src == dst.
-    status_t res = (*mDownmixHandle)->process(mDownmixHandle,
+    status_t res = mDownmixInterface->process(
             &mDownmixConfig.inputCfg.buffer, &mDownmixConfig.outputCfg.buffer);
     ALOGE_IF(res != OK, "DownmixBufferProvider error %d", res);
 }
@@ -248,8 +256,13 @@
 /*static*/ status_t DownmixerBufferProvider::init()
 {
     // find multichannel downmix effect if we have to play multichannel content
+    sp<EffectsFactoryHalInterface> effectsFactory = EffectsFactoryHalInterface::create();
+    if (effectsFactory.get() == NULL) {
+        ALOGE("AudioMixer() error: could not obtain the effects factory");
+        return NO_INIT;
+    }
     uint32_t numEffects = 0;
-    int ret = EffectQueryNumberEffects(&numEffects);
+    int ret = effectsFactory->queryNumberEffects(&numEffects);
     if (ret != 0) {
         ALOGE("AudioMixer() error %d querying number of effects", ret);
         return NO_INIT;
@@ -257,7 +270,7 @@
     ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
 
     for (uint32_t i = 0 ; i < numEffects ; i++) {
-        if (EffectQueryEffect(i, &sDwnmFxDesc) == 0) {
+        if (effectsFactory->getDescriptor(i, &sDwnmFxDesc) == 0) {
             ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
             if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
                 ALOGI("found effect \"%s\" from %s",
diff --git a/services/audioflinger/BufferProviders.h b/services/audioflinger/BufferProviders.h
index abd43c6..cb13689 100644
--- a/services/audioflinger/BufferProviders.h
+++ b/services/audioflinger/BufferProviders.h
@@ -24,9 +24,13 @@
 #include <media/AudioBufferProvider.h>
 #include <system/audio.h>
 #include <sonic.h>
+#include <utils/StrongPointer.h>
 
 namespace android {
 
+class EffectHalInterface;
+class EffectsFactoryHalInterface;
+
 // ----------------------------------------------------------------------------
 
 class PassthruBufferProvider : public AudioBufferProvider {
@@ -97,12 +101,13 @@
     //Overrides
     virtual void copyFrames(void *dst, const void *src, size_t frames);
 
-    bool isValid() const { return mDownmixHandle != NULL; }
+    bool isValid() const { return mDownmixInterface.get() != NULL; }
     static status_t init();
     static bool isMultichannelCapable() { return sIsMultichannelCapable; }
 
 protected:
-    effect_handle_t    mDownmixHandle;
+    sp<EffectsFactoryHalInterface> mEffectsFactory;
+    sp<EffectHalInterface> mDownmixInterface;
     effect_config_t    mDownmixConfig;
 
     // effect descriptor for the downmixer used by the mixer
diff --git a/services/audioflinger/EffectHalInterface.h b/services/audioflinger/EffectHalInterface.h
new file mode 100644
index 0000000..8f93723
--- /dev/null
+++ b/services/audioflinger/EffectHalInterface.h
@@ -0,0 +1,55 @@
+/*
+ * 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 ANDROID_HARDWARE_EFFECT_HAL_INTERFACE_H
+#define ANDROID_HARDWARE_EFFECT_HAL_INTERFACE_H
+
+#include <hardware/audio_effect.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class EffectHalInterface : public virtual RefBase
+{
+  public:
+    // The destructor automatically releases the effect.
+    virtual ~EffectHalInterface() {}
+
+    // Effect process function. Takes input samples as specified
+    // in input buffer descriptor and output processed samples as specified
+    // in output buffer descriptor.
+    virtual status_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) = 0;
+
+    // Process reverse stream function. This function is used to pass
+    // a reference stream to the effect engine.
+    virtual status_t processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) = 0;
+
+    // Send a command and receive a response to/from effect engine.
+    virtual status_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
+            uint32_t *replySize, void *pReplyData) = 0;
+
+    // Returns the effect descriptor.
+    virtual status_t getDescriptor(effect_descriptor_t *pDescriptor) = 0;
+
+  protected:
+    // Subclasses can not be constructed directly by clients.
+    EffectHalInterface() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECT_HAL_INTERFACE_H
diff --git a/services/audioflinger/EffectHalLocal.cpp b/services/audioflinger/EffectHalLocal.cpp
new file mode 100644
index 0000000..11fdc30
--- /dev/null
+++ b/services/audioflinger/EffectHalLocal.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#include <media/EffectsFactoryApi.h>
+#include <utils/Log.h>
+
+#include "EffectHalLocal.h"
+
+namespace android {
+
+EffectHalLocal::EffectHalLocal(effect_handle_t handle)
+        : mHandle(handle) {
+}
+
+EffectHalLocal::~EffectHalLocal() {
+    int status = EffectRelease(mHandle);
+    if (status != 0) {
+        ALOGW("Error releasing effect %p: %s", mHandle, strerror(-status));
+    }
+}
+
+status_t EffectHalLocal::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+    return (*mHandle)->process(mHandle, inBuffer, outBuffer);
+}
+
+status_t EffectHalLocal::processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+    return (*mHandle)->process_reverse(mHandle, inBuffer, outBuffer);
+}
+
+status_t EffectHalLocal::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
+        uint32_t *replySize, void *pReplyData) {
+    return (*mHandle)->command(mHandle, cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+}
+
+status_t EffectHalLocal::getDescriptor(effect_descriptor_t *pDescriptor) {
+    return (*mHandle)->get_descriptor(mHandle, pDescriptor);
+}
+
+} // namespace android
diff --git a/services/audioflinger/EffectHalLocal.h b/services/audioflinger/EffectHalLocal.h
new file mode 100644
index 0000000..92b2153
--- /dev/null
+++ b/services/audioflinger/EffectHalLocal.h
@@ -0,0 +1,60 @@
+/*
+ * 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 ANDROID_HARDWARE_EFFECT_HAL_LOCAL_H
+#define ANDROID_HARDWARE_EFFECT_HAL_LOCAL_H
+
+#include "EffectHalInterface.h"
+
+namespace android {
+
+class EffectHalLocal : public EffectHalInterface
+{
+  public:
+    // The destructor automatically releases the effect.
+    virtual ~EffectHalLocal();
+
+    // Effect process function. Takes input samples as specified
+    // in input buffer descriptor and output processed samples as specified
+    // in output buffer descriptor.
+    virtual status_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+
+    // Process reverse stream function. This function is used to pass
+    // a reference stream to the effect engine.
+    virtual status_t processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+
+    // Send a command and receive a response to/from effect engine.
+    virtual status_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
+            uint32_t *replySize, void *pReplyData);
+
+    // Returns the effect descriptor.
+    virtual status_t getDescriptor(effect_descriptor_t *pDescriptor);
+
+    // FIXME: Remove after converting the main audio HAL
+    effect_handle_t handle() const { return mHandle; }
+
+  private:
+    effect_handle_t mHandle;
+
+    friend class EffectsFactoryHalLocal;
+
+    // Can not be constructed directly by clients.
+    explicit EffectHalLocal(effect_handle_t handle);
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECT_HAL_LOCAL_H
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index b4d6295..984bde0 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -27,6 +27,10 @@
 #include <media/EffectsFactoryApi.h>
 
 #include "AudioFlinger.h"
+#include "EffectHalInterface.h"
+// FIXME: Remove after converting the main audio HAL
+#include "EffectHalLocal.h"
+#include "EffectsFactoryHalInterface.h"
 #include "ServiceUtilities.h"
 
 // ----------------------------------------------------------------------------
@@ -64,7 +68,6 @@
       mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
       mDescriptor(*desc),
       // mConfig is set by configure() and not used before then
-      mEffectInterface(NULL),
       mStatus(NO_INIT), mState(IDLE),
       // mMaxDisableWaitCnt is set by configure() and not used before then
       // mDisableWaitCnt is set by process() and updateState() and not used before then
@@ -75,7 +78,15 @@
     int lStatus;
 
     // create effect engine from effect factory
-    mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
+    mStatus = -ENODEV;
+    sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
+    if (audioFlinger.get() != NULL) {
+        sp<EffectsFactoryHalInterface> effectsFactory = audioFlinger->getEffectsFactory();
+        if (effectsFactory.get() != NULL) {
+            mStatus = effectsFactory->createEffect(
+                    &desc->uuid, sessionId, thread->id(), &mEffectInterface);
+        }
+    }
 
     if (mStatus != NO_ERROR) {
         return;
@@ -86,21 +97,20 @@
         goto Error;
     }
 
-    ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
+    ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get());
     return;
 Error:
-    EffectRelease(mEffectInterface);
-    mEffectInterface = NULL;
+    mEffectInterface.clear();
     ALOGV("Constructor Error %d", mStatus);
 }
 
 AudioFlinger::EffectModule::~EffectModule()
 {
     ALOGV("Destructor %p", this);
-    if (mEffectInterface != NULL) {
+    if (mEffectInterface.get() != NULL) {
         remove_effect_from_hal_l();
         // release effect engine
-        EffectRelease(mEffectInterface);
+        mEffectInterface.clear();
     }
 }
 
@@ -266,7 +276,7 @@
 {
     Mutex::Autolock _l(mLock);
 
-    if (mState == DESTROYED || mEffectInterface == NULL ||
+    if (mState == DESTROYED || mEffectInterface.get() == NULL ||
             mConfig.inputCfg.buffer.raw == NULL ||
             mConfig.outputCfg.buffer.raw == NULL) {
         return;
@@ -281,9 +291,8 @@
         }
 
         // do the actual processing in the effect engine
-        int ret = (*mEffectInterface)->process(mEffectInterface,
-                                               &mConfig.inputCfg.buffer,
-                                               &mConfig.outputCfg.buffer);
+        int ret = mEffectInterface->process(&mConfig.inputCfg.buffer,
+                                            &mConfig.outputCfg.buffer);
 
         // force transition to IDLE state when engine is ready
         if (mState == STOPPED && ret == -ENODATA) {
@@ -313,10 +322,10 @@
 
 void AudioFlinger::EffectModule::reset_l()
 {
-    if (mStatus != NO_ERROR || mEffectInterface == NULL) {
+    if (mStatus != NO_ERROR || mEffectInterface.get() == NULL) {
         return;
     }
-    (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
+    mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, 0, NULL);
 }
 
 status_t AudioFlinger::EffectModule::configure()
@@ -326,7 +335,7 @@
     uint32_t size;
     audio_channel_mask_t channelMask;
 
-    if (mEffectInterface == NULL) {
+    if (mEffectInterface.get() == NULL) {
         status = NO_INIT;
         goto exit;
     }
@@ -389,12 +398,11 @@
 
     status_t cmdStatus;
     size = sizeof(int);
-    status = (*mEffectInterface)->command(mEffectInterface,
-                                                   EFFECT_CMD_SET_CONFIG,
-                                                   sizeof(effect_config_t),
-                                                   &mConfig,
-                                                   &size,
-                                                   &cmdStatus);
+    status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
+                                       sizeof(effect_config_t),
+                                       &mConfig,
+                                       &size,
+                                       &cmdStatus);
     if (status == 0) {
         status = cmdStatus;
     }
@@ -416,12 +424,11 @@
         }
 
         *((int32_t *)p->data + 1)= latency;
-        (*mEffectInterface)->command(mEffectInterface,
-                                     EFFECT_CMD_SET_PARAM,
-                                     sizeof(effect_param_t) + 8,
-                                     &buf32,
-                                     &size,
-                                     &cmdStatus);
+        mEffectInterface->command(EFFECT_CMD_SET_PARAM,
+                                  sizeof(effect_param_t) + 8,
+                                  &buf32,
+                                  &size,
+                                  &cmdStatus);
     }
 
     mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
@@ -435,17 +442,16 @@
 status_t AudioFlinger::EffectModule::init()
 {
     Mutex::Autolock _l(mLock);
-    if (mEffectInterface == NULL) {
+    if (mEffectInterface.get() == NULL) {
         return NO_INIT;
     }
     status_t cmdStatus;
     uint32_t size = sizeof(status_t);
-    status_t status = (*mEffectInterface)->command(mEffectInterface,
-                                                   EFFECT_CMD_INIT,
-                                                   0,
-                                                   NULL,
-                                                   &size,
-                                                   &cmdStatus);
+    status_t status = mEffectInterface->command(EFFECT_CMD_INIT,
+                                                0,
+                                                NULL,
+                                                &size,
+                                                &cmdStatus);
     if (status == 0) {
         status = cmdStatus;
     }
@@ -460,7 +466,8 @@
         if (thread != 0) {
             audio_stream_t *stream = thread->stream();
             if (stream != NULL) {
-                stream->add_audio_effect(stream, mEffectInterface);
+                stream->add_audio_effect(stream,
+                        reinterpret_cast<EffectHalLocal*>(mEffectInterface.get())->handle());
             }
         }
     }
@@ -486,7 +493,7 @@
 
 status_t AudioFlinger::EffectModule::start_l()
 {
-    if (mEffectInterface == NULL) {
+    if (mEffectInterface.get() == NULL) {
         return NO_INIT;
     }
     if (mStatus != NO_ERROR) {
@@ -494,12 +501,11 @@
     }
     status_t cmdStatus;
     uint32_t size = sizeof(status_t);
-    status_t status = (*mEffectInterface)->command(mEffectInterface,
-                                                   EFFECT_CMD_ENABLE,
-                                                   0,
-                                                   NULL,
-                                                   &size,
-                                                   &cmdStatus);
+    status_t status = mEffectInterface->command(EFFECT_CMD_ENABLE,
+                                                0,
+                                                NULL,
+                                                &size,
+                                                &cmdStatus);
     if (status == 0) {
         status = cmdStatus;
     }
@@ -517,7 +523,7 @@
 
 status_t AudioFlinger::EffectModule::stop_l()
 {
-    if (mEffectInterface == NULL) {
+    if (mEffectInterface.get() == NULL) {
         return NO_INIT;
     }
     if (mStatus != NO_ERROR) {
@@ -525,12 +531,11 @@
     }
     status_t cmdStatus = NO_ERROR;
     uint32_t size = sizeof(status_t);
-    status_t status = (*mEffectInterface)->command(mEffectInterface,
-                                                   EFFECT_CMD_DISABLE,
-                                                   0,
-                                                   NULL,
-                                                   &size,
-                                                   &cmdStatus);
+    status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE,
+                                                0,
+                                                NULL,
+                                                &size,
+                                                &cmdStatus);
     if (status == NO_ERROR) {
         status = cmdStatus;
     }
@@ -548,7 +553,8 @@
         if (thread != 0) {
             audio_stream_t *stream = thread->stream();
             if (stream != NULL) {
-                stream->remove_audio_effect(stream, mEffectInterface);
+                stream->remove_audio_effect(stream,
+                        reinterpret_cast<EffectHalLocal*>(mEffectInterface.get())->handle());
             }
         }
     }
@@ -569,9 +575,9 @@
                                              void *pReplyData)
 {
     Mutex::Autolock _l(mLock);
-    ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
+    ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface.get());
 
-    if (mState == DESTROYED || mEffectInterface == NULL) {
+    if (mState == DESTROYED || mEffectInterface.get() == NULL) {
         return NO_INIT;
     }
     if (mStatus != NO_ERROR) {
@@ -599,12 +605,11 @@
         android_errorWriteLog(0x534e4554, "30204301");
         return -EINVAL;
     }
-    status_t status = (*mEffectInterface)->command(mEffectInterface,
-                                                   cmdCode,
-                                                   cmdSize,
-                                                   pCmdData,
-                                                   replySize,
-                                                   pReplyData);
+    status_t status = mEffectInterface->command(cmdCode,
+                                                cmdSize,
+                                                pCmdData,
+                                                replySize,
+                                                pReplyData);
     if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
         uint32_t size = (replySize == NULL) ? 0 : *replySize;
         for (size_t i = 1; i < mHandles.size(); i++) {
@@ -726,12 +731,11 @@
         if (controller) {
             pVolume = volume;
         }
-        status = (*mEffectInterface)->command(mEffectInterface,
-                                              EFFECT_CMD_SET_VOLUME,
-                                              size,
-                                              volume,
-                                              &size,
-                                              pVolume);
+        status = mEffectInterface->command(EFFECT_CMD_SET_VOLUME,
+                                           size,
+                                           volume,
+                                           &size,
+                                           pVolume);
         if (controller && status == NO_ERROR && size == sizeof(volume)) {
             *left = volume[0];
             *right = volume[1];
@@ -756,12 +760,11 @@
         uint32_t size = sizeof(status_t);
         uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
                             EFFECT_CMD_SET_INPUT_DEVICE;
-        status = (*mEffectInterface)->command(mEffectInterface,
-                                              cmd,
-                                              sizeof(uint32_t),
-                                              &device,
-                                              &size,
-                                              &cmdStatus);
+        status = mEffectInterface->command(cmd,
+                                           sizeof(uint32_t),
+                                           &device,
+                                           &size,
+                                           &cmdStatus);
     }
     return status;
 }
@@ -776,12 +779,11 @@
     if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
         status_t cmdStatus;
         uint32_t size = sizeof(status_t);
-        status = (*mEffectInterface)->command(mEffectInterface,
-                                              EFFECT_CMD_SET_AUDIO_MODE,
-                                              sizeof(audio_mode_t),
-                                              &mode,
-                                              &size,
-                                              &cmdStatus);
+        status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_MODE,
+                                           sizeof(audio_mode_t),
+                                           &mode,
+                                           &size,
+                                           &cmdStatus);
         if (status == NO_ERROR) {
             status = cmdStatus;
         }
@@ -798,12 +800,11 @@
     status_t status = NO_ERROR;
     if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_SOURCE_MASK) == EFFECT_FLAG_AUDIO_SOURCE_IND) {
         uint32_t size = 0;
-        status = (*mEffectInterface)->command(mEffectInterface,
-                                              EFFECT_CMD_SET_AUDIO_SOURCE,
-                                              sizeof(audio_source_t),
-                                              &source,
-                                              &size,
-                                              NULL);
+        status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_SOURCE,
+                                           sizeof(audio_source_t),
+                                           &source,
+                                           &size,
+                                           NULL);
     }
     return status;
 }
@@ -850,12 +851,11 @@
 
         cmd.isOffload = offloaded;
         cmd.ioHandle = io;
-        status = (*mEffectInterface)->command(mEffectInterface,
-                                              EFFECT_CMD_OFFLOAD,
-                                              sizeof(effect_offload_param_t),
-                                              &cmd,
-                                              &size,
-                                              &cmdStatus);
+        status = mEffectInterface->command(EFFECT_CMD_OFFLOAD,
+                                           sizeof(effect_offload_param_t),
+                                           &cmd,
+                                           &size,
+                                           &cmdStatus);
         if (status == NO_ERROR) {
             status = cmdStatus;
         }
@@ -998,7 +998,7 @@
 
     result.append("\t\tSession Status State Engine:\n");
     snprintf(buffer, SIZE, "\t\t%05d   %03d    %03d   %p\n",
-            mSessionId, mStatus, mState, mEffectInterface);
+            mSessionId, mStatus, mState, mEffectInterface.get());
     result.append(buffer);
 
     result.append("\t\tDescriptor:\n");
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 626fcc1..055dac3 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -146,7 +146,7 @@
     const audio_session_t mSessionId; // audio session ID
     const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
     effect_config_t     mConfig;    // input and output audio configuration
-    effect_handle_t  mEffectInterface; // Effect module C API
+    sp<EffectHalInterface> mEffectInterface; // Effect module HAL
     status_t            mStatus;    // initialization status
     effect_state        mState;     // current activation state
     Vector<EffectHandle *> mHandles;    // list of client handles
diff --git a/services/audioflinger/EffectsFactoryHalInterface.h b/services/audioflinger/EffectsFactoryHalInterface.h
new file mode 100644
index 0000000..2805560
--- /dev/null
+++ b/services/audioflinger/EffectsFactoryHalInterface.h
@@ -0,0 +1,64 @@
+/*
+ * 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 ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
+#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
+
+#include <hardware/audio_effect.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include "EffectHalInterface.h"
+
+namespace android {
+
+class EffectsFactoryHalInterface : public virtual RefBase
+{
+  public:
+    virtual ~EffectsFactoryHalInterface() {}
+
+    // Returns the number of different effects in all loaded libraries.
+    virtual status_t queryNumberEffects(uint32_t *pNumEffects) = 0;
+
+    // Returns a descriptor of the next available effect.
+    virtual status_t getDescriptor(uint32_t index,
+            effect_descriptor_t *pDescriptor) = 0;
+
+    virtual status_t getDescriptor(const effect_uuid_t *pEffectUuid,
+            effect_descriptor_t *pDescriptor) = 0;
+
+    // Creates an effect engine of the specified type.
+    // To release the effect engine, it is necessary to release references
+    // to the returned effect object.
+    virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
+            int32_t sessionId, int32_t ioId,
+            sp<EffectHalInterface> *effect) = 0;
+
+    virtual status_t dumpEffects(int fd) = 0;
+
+    static sp<EffectsFactoryHalInterface> create();
+
+    // Helper function to compare effect uuid to EFFECT_UUID_NULL.
+    static bool isNullUuid(const effect_uuid_t *pEffectUuid);
+
+  protected:
+    // Subclasses can not be constructed directly by clients.
+    EffectsFactoryHalInterface() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
diff --git a/services/audioflinger/EffectsFactoryHalLocal.cpp b/services/audioflinger/EffectsFactoryHalLocal.cpp
new file mode 100644
index 0000000..bbdef5d
--- /dev/null
+++ b/services/audioflinger/EffectsFactoryHalLocal.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#include <media/EffectsFactoryApi.h>
+
+#include "EffectHalLocal.h"
+#include "EffectsFactoryHalLocal.h"
+
+namespace android {
+
+// static
+sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
+    return new EffectsFactoryHalLocal();
+}
+
+// static
+bool EffectsFactoryHalInterface::isNullUuid(const effect_uuid_t *pEffectUuid) {
+    return EffectIsNullUuid(pEffectUuid);
+}
+
+status_t EffectsFactoryHalLocal::queryNumberEffects(uint32_t *pNumEffects) {
+    return EffectQueryNumberEffects(pNumEffects);
+}
+
+status_t EffectsFactoryHalLocal::getDescriptor(
+        uint32_t index, effect_descriptor_t *pDescriptor) {
+    return EffectQueryEffect(index, pDescriptor);
+}
+
+status_t EffectsFactoryHalLocal::getDescriptor(
+        const effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptor) {
+    return EffectGetDescriptor(pEffectUuid, pDescriptor);
+}
+
+status_t EffectsFactoryHalLocal::createEffect(
+        const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t ioId,
+        sp<EffectHalInterface> *effect) {
+    effect_handle_t handle;
+    int result = EffectCreate(pEffectUuid, sessionId, ioId, &handle);
+    if (result == 0) {
+        *effect = new EffectHalLocal(handle);
+    }
+    return result;
+}
+
+status_t EffectsFactoryHalLocal::dumpEffects(int fd) {
+    return EffectDumpEffects(fd);
+}
+
+} // namespace android
diff --git a/services/audioflinger/EffectsFactoryHalLocal.h b/services/audioflinger/EffectsFactoryHalLocal.h
new file mode 100644
index 0000000..244176a
--- /dev/null
+++ b/services/audioflinger/EffectsFactoryHalLocal.h
@@ -0,0 +1,57 @@
+/*
+ * 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 ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_LOCAL_H
+#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_LOCAL_H
+
+#include "EffectsFactoryHalInterface.h"
+
+namespace android {
+
+class EffectsFactoryHalLocal : public EffectsFactoryHalInterface
+{
+  public:
+    virtual ~EffectsFactoryHalLocal() {}
+
+    // Returns the number of different effects in all loaded libraries.
+    virtual status_t queryNumberEffects(uint32_t *pNumEffects);
+
+    // Returns a descriptor of the next available effect.
+    virtual status_t getDescriptor(uint32_t index,
+            effect_descriptor_t *pDescriptor);
+
+    virtual status_t getDescriptor(const effect_uuid_t *pEffectUuid,
+            effect_descriptor_t *pDescriptor);
+
+    // Creates an effect engine of the specified type.
+    // To release the effect engine, it is necessary to release references
+    // to the returned effect object.
+    virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
+            int32_t sessionId, int32_t ioId,
+            sp<EffectHalInterface> *effect);
+
+    virtual status_t dumpEffects(int fd);
+
+  private:
+    friend class EffectsFactoryHalInterface;
+
+    // Can not be constructed directly by clients.
+    EffectsFactoryHalLocal() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_LOCAL_H
diff --git a/services/audioflinger/tests/Android.mk b/services/audioflinger/tests/Android.mk
index 3505e0f..bf94f71 100644
--- a/services/audioflinger/tests/Android.mk
+++ b/services/audioflinger/tests/Android.mk
@@ -34,8 +34,10 @@
 
 LOCAL_SRC_FILES:= \
 	test-mixer.cpp \
-	../AudioMixer.cpp.arm \
-	../BufferProviders.cpp
+	../AudioMixer.cpp.arm  \
+	../BufferProviders.cpp \
+	../EffectHalLocal.cpp  \
+	../EffectsFactoryHalLocal.cpp
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, audio-effects) \