AudioFlinger: Extract Effect inner classes

Add new interfaces for accessing effects.

IAfEffectBase
IAfEffectModule
IAfEffectChain
IAfEffectHandle
IAfDeviceEffectProxy

Test: atest android.media.audio.cts.AudioEffectTest android.media.audio.cts.AudioPreProcessingTest android.media.audio.cts.BassBoostTest android.media.audio.cts.EnvReverbTest android.media.audio.cts.EqualizerTest android.media.audio.cts.LoudnessEnhancerTest android.media.audio.cts.PresetReverbTest android.media.audio.cts.VirtualizerTest android.media.audio.cts.VisualizerTest
Bug: 288339104
Bug: 288339921
Change-Id: Id27f9f7e9da53890f8e22ad45e174ff8eeb68b09
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 60717b5..ad2ba21 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2200,7 +2200,7 @@
 
 void AudioFlinger::removeNotificationClient(pid_t pid)
 {
-    std::vector< sp<AudioFlinger::EffectModule> > removedEffects;
+    std::vector<sp<IAfEffectModule>> removedEffects;
     {
         Mutex::Autolock _l(mLock);
         {
@@ -2536,7 +2536,7 @@
 
         // Check if one effect chain was awaiting for an AudioRecord to be created on this
         // session and move it to this thread.
-        sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
+        sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
         if (chain != 0) {
             Mutex::Autolock _l2(thread->mLock);
             thread->addEffectChain_l(chain);
@@ -3216,7 +3216,7 @@
                     // audioflinger lock is held so order of thread lock acquisition doesn't matter
                     Mutex::Autolock _dl(dstThread->mLock);
                     Mutex::Autolock _sl(playbackThread->mLock);
-                    Vector< sp<EffectChain> > effectChains = playbackThread->getEffectChains_l();
+                    Vector<sp<IAfEffectChain>> effectChains = playbackThread->getEffectChains_l();
                     for (size_t i = 0; i < effectChains.size(); i ++) {
                         moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
                                 dstThread);
@@ -3450,10 +3450,10 @@
             // on at least one effect. We must either move the chain to an existing thread with the
             // same session ID or put it aside in case a new record thread is opened for a
             // new capture on the same session
-            sp<EffectChain> chain;
+            sp<IAfEffectChain> chain;
             {
                 Mutex::Autolock _sl(recordThread->mLock);
-                Vector< sp<EffectChain> > effectChains = recordThread->getEffectChains_l();
+                Vector< sp<IAfEffectChain> > effectChains = recordThread->getEffectChains_l();
                 // Note: maximum one chain per record thread
                 if (effectChains.size() != 0) {
                     chain = effectChains[0];
@@ -3596,7 +3596,7 @@
 
 void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
 {
-    std::vector< sp<EffectModule> > removedEffects;
+    std::vector<sp<IAfEffectModule>> removedEffects;
     {
         Mutex::Autolock _l(mLock);
         pid_t caller = IPCThreadState::self()->getCallingPid();
@@ -3614,7 +3614,7 @@
                 if (ref->mCnt == 0) {
                     mAudioSessionRefs.removeAt(i);
                     delete ref;
-                    std::vector< sp<EffectModule> > effects = purgeStaleEffects_l();
+                    std::vector<sp<IAfEffectModule>> effects = purgeStaleEffects_l();
                     removedEffects.insert(removedEffects.end(), effects.begin(), effects.end());
                 }
                 goto Exit;
@@ -3644,18 +3644,18 @@
     return false;
 }
 
-std::vector<sp<AudioFlinger::EffectModule>> AudioFlinger::purgeStaleEffects_l() {
+std::vector<sp<IAfEffectModule>> AudioFlinger::purgeStaleEffects_l() {
 
     ALOGV("purging stale effects");
 
-    Vector< sp<EffectChain> > chains;
-    std::vector< sp<EffectModule> > removedEffects;
+    Vector< sp<IAfEffectChain> > chains;
+    std::vector< sp<IAfEffectModule> > removedEffects;
 
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
         sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
         Mutex::Autolock _l(t->mLock);
         for (size_t j = 0; j < t->mEffectChains.size(); j++) {
-            sp<EffectChain> ec = t->mEffectChains[j];
+            sp<IAfEffectChain> ec = t->mEffectChains[j];
             if (!audio_is_global_session(ec->sessionId())) {
                 chains.push(ec);
             }
@@ -3666,7 +3666,7 @@
         sp<RecordThread> t = mRecordThreads.valueAt(i);
         Mutex::Autolock _l(t->mLock);
         for (size_t j = 0; j < t->mEffectChains.size(); j++) {
-            sp<EffectChain> ec = t->mEffectChains[j];
+            sp<IAfEffectChain> ec = t->mEffectChains[j];
             chains.push(ec);
         }
     }
@@ -3675,16 +3675,16 @@
         sp<MmapThread> t = mMmapThreads.valueAt(i);
         Mutex::Autolock _l(t->mLock);
         for (size_t j = 0; j < t->mEffectChains.size(); j++) {
-            sp<EffectChain> ec = t->mEffectChains[j];
+            sp<IAfEffectChain> ec = t->mEffectChains[j];
             chains.push(ec);
         }
     }
 
     for (size_t i = 0; i < chains.size(); i++) {
          // clang-tidy suggests const ref
-        sp<EffectChain> ec = chains[i];  // NOLINT(performance-unnecessary-copy-initialization)
+        sp<IAfEffectChain> ec = chains[i];  // NOLINT(performance-unnecessary-copy-initialization)
         int sessionid = ec->sessionId();
-        sp<ThreadBase> t = ec->thread().promote();
+        sp<ThreadBase> t = sp<ThreadBase>::cast(ec->thread().promote()); // TODO(b/288339104)
         if (t == 0) {
             continue;
         }
@@ -3702,8 +3702,8 @@
         if (!found) {
             Mutex::Autolock _l(t->mLock);
             // remove all effects from the chain
-            while (ec->mEffects.size()) {
-                sp<EffectModule> effect = ec->mEffects[0];
+            while (ec->numberOfEffects()) {
+                sp<IAfEffectModule> effect = ec->getEffectModule(0);
                 effect->unPin();
                 t->removeEffect_l(effect, /*release*/ true);
                 if (effect->purgeHandles()) {
@@ -4140,7 +4140,7 @@
             aidl2legacy_EffectDescriptor_effect_descriptor_t(request.desc));
     const bool probe = request.probe;
 
-    sp<EffectHandle> handle;
+    sp<IAfEffectHandle> handle;
     effect_descriptor_t descOut;
     int enabledOut = 0;
     int idOut = -1;
@@ -4248,7 +4248,7 @@
             goto Exit;
         }
 
-        const bool hapticPlaybackRequired = EffectModule::isHapticGenerator(&descOut.type);
+        const bool hapticPlaybackRequired = IAfEffectModule::isHapticGenerator(&descOut.type);
         if (hapticPlaybackRequired
                 && (sessionId == AUDIO_SESSION_DEVICE
                         || sessionId == AUDIO_SESSION_OUTPUT_MIX
@@ -4376,7 +4376,7 @@
         } else {
             // Check if one effect chain was awaiting for an effect to be created on this
             // session and used it instead of creating a new one.
-            sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
+            sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
             if (chain != 0) {
                 Mutex::Autolock _l2(thread->mLock);
                 thread->addEffectChain_l(chain);
@@ -4428,7 +4428,7 @@
             response->alreadyExists = false;
         }
         // Check CPU and memory usage
-        sp<EffectBase> effect = handle->effect().promote();
+        sp<IAfEffectBase> effect = handle->effect().promote();
         if (effect != nullptr) {
             status_t rStatus = effect->updatePolicyState();
             if (rStatus != NO_ERROR) {
@@ -4441,7 +4441,7 @@
 
     response->id = idOut;
     response->enabled = enabledOut != 0;
-    response->effect = handle;
+    response->effect = handle->asIEffect();
     response->desc = VALUE_OR_RETURN_STATUS(
             legacy2aidl_effect_descriptor_t_EffectDescriptor(descOut));
 
@@ -4487,7 +4487,7 @@
       return;
     }
     Mutex::Autolock _sl(thread->mLock);
-    sp<EffectModule> effect = thread->getEffect_l(sessionId, effectId);
+    sp<IAfEffectModule> effect = thread->getEffect_l(sessionId, effectId);
     thread->setEffectSuspended_l(&effect->desc().type, suspended, sessionId);
 }
 
@@ -4501,7 +4501,7 @@
     ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
             sessionId, srcThread, dstThread);
 
-    sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
+    sp<IAfEffectChain> chain = srcThread->getEffectChain_l(sessionId);
     if (chain == 0) {
         ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
                 sessionId, srcThread);
@@ -4525,12 +4525,12 @@
 
     // transfer all effects one by one so that new effect chain is created on new thread with
     // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
-    sp<EffectChain> dstChain;
-    Vector< sp<EffectModule> > removed;
+    sp<IAfEffectChain> dstChain;
+    Vector<sp<IAfEffectModule>> removed;
     status_t status = NO_ERROR;
     std::string errorString;
     // process effects one by one.
-    for (sp<EffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
+    for (sp<IAfEffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
             effect = chain->getEffectFromId_l(0)) {
         srcThread->removeEffect_l(effect);
         removed.add(effect);
@@ -4578,8 +4578,8 @@
         // see b/202360137.
         dstChain->lock();
         for (const auto& effect : removed) {
-            if (effect->state() == EffectModule::ACTIVE ||
-                    effect->state() == EffectModule::STOPPING) {
+            if (effect->state() == IAfEffectModule::ACTIVE ||
+                    effect->state() == IAfEffectModule::STOPPING) {
                 ++started;
                 effect->start();
             }
@@ -4616,13 +4616,13 @@
     if (EffectId != 0 && thread != 0 && dstThread != thread.get()) {
         Mutex::Autolock _dl(dstThread->mLock);
         Mutex::Autolock _sl(thread->mLock);
-        sp<EffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
-        sp<EffectChain> dstChain;
+        sp<IAfEffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+        sp<IAfEffectChain> dstChain;
         if (srcChain == 0) {
             return INVALID_OPERATION;
         }
 
-        sp<EffectModule> effect = srcChain->getEffectFromId_l(EffectId);
+        sp<IAfEffectModule> effect = srcChain->getEffectFromId_l(EffectId);
         if (effect == 0) {
             return INVALID_OPERATION;
         }
@@ -4642,8 +4642,8 @@
 
 Exit:
         // removeEffect_l() has stopped the effect if it was active so it must be restarted
-        if (effect->state() == EffectModule::ACTIVE ||
-            effect->state() == EffectModule::STOPPING) {
+        if (effect->state() == IAfEffectModule::ACTIVE ||
+            effect->state() == IAfEffectModule::STOPPING) {
             effect->start();
         }
     }
@@ -4663,7 +4663,7 @@
     }
 
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        sp<EffectChain> ec =
+        sp<IAfEffectChain> ec =
                 mPlaybackThreads.valueAt(i)->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
         if (ec != 0 && ec->isNonOffloadableEnabled()) {
             return true;
@@ -4687,7 +4687,7 @@
 
 }
 
-status_t AudioFlinger::putOrphanEffectChain_l(const sp<AudioFlinger::EffectChain>& chain)
+status_t AudioFlinger::putOrphanEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     // clear possible suspended state before parking the chain so that it starts in default state
     // when attached to a new record thread
@@ -4705,9 +4705,9 @@
     return NO_ERROR;
 }
 
-sp<AudioFlinger::EffectChain> AudioFlinger::getOrphanEffectChain_l(audio_session_t session)
+sp<IAfEffectChain> AudioFlinger::getOrphanEffectChain_l(audio_session_t session)
 {
-    sp<EffectChain> chain;
+    sp<IAfEffectChain> chain;
     ssize_t index = mOrphanEffectChains.indexOfKey(session);
     ALOGV("getOrphanEffectChain_l session %d index %zd", session, index);
     if (index >= 0) {
@@ -4717,14 +4717,14 @@
     return chain;
 }
 
-bool AudioFlinger::updateOrphanEffectChains(const sp<AudioFlinger::EffectModule>& effect)
+bool AudioFlinger::updateOrphanEffectChains(const sp<IAfEffectModule>& effect)
 {
     Mutex::Autolock _l(mLock);
     audio_session_t session = effect->sessionId();
     ssize_t index = mOrphanEffectChains.indexOfKey(session);
     ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
     if (index >= 0) {
-        sp<EffectChain> chain = mOrphanEffectChains.valueAt(index);
+        sp<IAfEffectChain> chain = mOrphanEffectChains.valueAt(index);
         if (chain->removeEffect_l(effect, true) == 0) {
             ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index);
             mOrphanEffectChains.removeItemsAt(index);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 8b1d70b..e2d340b 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -117,6 +117,9 @@
 #include "android/media/BnAudioRecord.h"
 #include "android/media/BnEffect.h"
 
+// include AudioFlinger component interfaces
+#include "IAfEffect.h"
+
 namespace android {
 
 class AudioMixer;
@@ -478,16 +481,24 @@
 
     // Internal dump utilities.
     static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
+public:
+    // TODO(b/288339104) extract to afutils
     static bool dumpTryLock(Mutex& mutex);
+private:
     void dumpPermissionDenial(int fd, const Vector<String16>& args);
     void dumpClients(int fd, const Vector<String16>& args);
     void dumpInternals(int fd, const Vector<String16>& args);
 
     SimpleLog mThreadLog{16}; // 16 Thread history limit
 
+public:
+    // TODO(b/288339104)
     class ThreadBase;
+private:
     void dumpToThreadLog_l(const sp<ThreadBase> &thread);
 
+public:
+    // TODO(b/288339104) Move to separate file
     // --- Client ---
     class Client : public RefBase {
       public:
@@ -504,6 +515,7 @@
         const pid_t         mPid;
         AllocatorFactory::ClientAllocator mClientAllocator;
     };
+private:
 
     // --- Notification Client ---
     class NotificationClient : public IBinder::DeathRecipient {
@@ -575,15 +587,12 @@
     class BitPerfectThread;
     class Track;
     class RecordTrack;
-    class EffectBase;
-    class EffectModule;
-    class EffectHandle;
-    class EffectChain;
-    class DeviceEffectProxy;
     class DeviceEffectManager;
+    // TODO(b/288339104) these should be separate files
+public:
     class PatchPanel;
     class DeviceEffectManagerCallback;
-
+private:
     struct AudioStreamIn;
     struct TeePatch;
     using TeePatches = std::vector<TeePatch>;
@@ -617,8 +626,6 @@
 
 #include "PatchCommandThread.h"
 
-#include "Effects.h"
-
 #include "DeviceEffectManager.h"
 
 #include "MelReporter.h"
@@ -819,17 +826,19 @@
                 // return ALREADY_EXISTS if a chain with the same session already exists in
                 // mOrphanEffectChains. Note that this should never happen as there is only one
                 // chain for a given session and it is attached to only one thread at a time.
-                status_t        putOrphanEffectChain_l(const sp<EffectChain>& chain);
+                status_t putOrphanEffectChain_l(const sp<IAfEffectChain>& chain);
                 // Get an effect chain for the specified session in mOrphanEffectChains and remove
                 // it if found. Returns 0 if not found (this is the most common case).
-                sp<EffectChain> getOrphanEffectChain_l(audio_session_t session);
+                sp<IAfEffectChain> getOrphanEffectChain_l(audio_session_t session);
                 // Called when the last effect handle on an effect instance is removed. If this
                 // effect belongs to an effect chain in mOrphanEffectChains, the chain is updated
                 // and removed from mOrphanEffectChains if it does not contain any effect.
                 // Return true if the effect was found in mOrphanEffectChains, false otherwise.
-                bool            updateOrphanEffectChains(const sp<EffectModule>& effect);
-
-                std::vector< sp<EffectModule> > purgeStaleEffects_l();
+public:
+// TODO(b/288339104) suggest better grouping
+                bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect);
+private:
+                std::vector< sp<IAfEffectModule> > purgeStaleEffects_l();
 
                 void broadcastParametersToRecordThreads_l(const String8& keyValuePairs);
                 void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
@@ -879,7 +888,10 @@
                 // protects mClients and mNotificationClients.
                 // must be locked after mLock and ThreadBase::mLock if both must be locked
                 // avoids acquiring AudioFlinger::mLock from inside thread loop.
+public:
+    // TODO(b/288339104) access by getter,
     mutable     Mutex                               mClientLock;
+private:
                 // protected by mClientLock
                 DefaultKeyedVector< pid_t, wp<Client> >     mClients;   // see ~Client()
 
@@ -958,7 +970,7 @@
                 std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents;
 
                 // Effect chains without a valid thread
-                DefaultKeyedVector< audio_session_t , sp<EffectChain> > mOrphanEffectChains;
+                DefaultKeyedVector<audio_session_t, sp<IAfEffectChain>> mOrphanEffectChains;
 
                 // list of sessions for which a valid HW A/V sync ID was retrieved from the HAL
                 DefaultKeyedVector< audio_session_t , audio_hw_sync_t >mHwAvSyncIds;
@@ -1004,7 +1016,10 @@
 
     // protected by mLock
     PatchPanel mPatchPanel;
+public:
+    // TODO(b/288339104) access by getter.
     sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
+private:
 
     const sp<PatchCommandThread> mPatchCommandThread;
     sp<DeviceEffectManager> mDeviceEffectManager;
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 4fb6138..f034e05 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -41,7 +41,7 @@
             patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
     Mutex::Autolock _l(mLock);
     for (auto& effect : mDeviceEffects) {
-        status_t status = effect.second->onCreatePatch(handle, patch);
+        status_t status = effect.second->onCreatePatch(handle, &patch); // TODO(b/288339104) void*
         ALOGV("%s Effect onCreatePatch status %d", __func__, status);
         ALOGW_IF(status == BAD_VALUE, "%s onCreatePatch error %d", __func__, status);
     }
@@ -56,7 +56,7 @@
 }
 
 // DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
+sp<IAfEffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
         effect_descriptor_t *descriptor,
         const AudioDeviceTypeAddr& device,
         const sp<AudioFlinger::Client>& client,
@@ -66,8 +66,8 @@
         status_t *status,
         bool probe,
         bool notifyFramesProcessed) {
-    sp<DeviceEffectProxy> effect;
-    sp<EffectHandle> handle;
+    sp<IAfDeviceEffectProxy> effect;
+    sp<IAfEffectHandle> handle;
     status_t lStatus;
 
     lStatus = checkEffectCompatibility(descriptor);
@@ -82,18 +82,18 @@
         if (iter != mDeviceEffects.end()) {
             effect = iter->second;
         } else {
-            effect = new DeviceEffectProxy(device, mMyCallback,
+            effect = IAfDeviceEffectProxy::create(device, mMyCallback,
                     descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
                     notifyFramesProcessed);
         }
         // create effect handle and connect it to effect module
-        handle = new EffectHandle(effect, client, effectClient, 0 /*priority*/,
-                                  notifyFramesProcessed);
+        handle = IAfEffectHandle::create(
+                effect, client, effectClient, 0 /*priority*/, notifyFramesProcessed);
         lStatus = handle->initCheck();
         if (lStatus == NO_ERROR) {
             lStatus = effect->addHandle(handle.get());
             if (lStatus == NO_ERROR) {
-                lStatus = effect->init(patches);
+                lStatus = effect->init(&patches); // TODO(b/288339104) void*
                 if (lStatus == NAME_NOT_FOUND) {
                     lStatus = NO_ERROR;
                 }
@@ -165,7 +165,7 @@
         outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
                 ::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
         write(fd, outStr.string(), outStr.size());
-        iter.second->dump(fd, 4);
+        iter.second->dump2(fd, 4);
     }
 
     if (locked) {
@@ -174,7 +174,7 @@
 }
 
 
-size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<DeviceEffectProxy>& effect)
+size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
 {
     Mutex::Autolock _l(mLock);
     mDeviceEffects.erase(effect->device());
@@ -182,13 +182,13 @@
 }
 
 bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
-        EffectHandle *handle, bool unpinIfLast) {
-    sp<EffectBase> effectBase = handle->effect().promote();
+        IAfEffectHandle *handle, bool unpinIfLast) {
+    sp<IAfEffectBase> effectBase = handle->effect().promote();
     if (effectBase == nullptr) {
         return false;
     }
 
-    sp<DeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
+    sp<IAfDeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
     if (effect == nullptr) {
         return false;
     }
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index b87f830..3a33a71 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -30,7 +30,7 @@
         mAudioFlinger.mPatchCommandThread->addListener(this);
     }
 
-    sp<EffectHandle> createEffect_l(effect_descriptor_t *descriptor,
+    sp<IAfEffectHandle> createEffect_l(effect_descriptor_t *descriptor,
                 const AudioDeviceTypeAddr& device,
                 const sp<AudioFlinger::Client>& client,
                 const sp<media::IEffectClient>& effectClient,
@@ -40,7 +40,7 @@
                 bool probe,
                 bool notifyFramesProcessed);
 
-    size_t removeEffect(const sp<DeviceEffectProxy>& effect);
+    size_t removeEffect(const sp<IAfDeviceEffectProxy>& effect);
     status_t createEffectHal(const effect_uuid_t *pEffectUuid,
            int32_t sessionId, int32_t deviceId,
            sp<EffectHalInterface> *effect);
@@ -69,9 +69,10 @@
     Mutex mLock;
     AudioFlinger &mAudioFlinger;
     const sp<DeviceEffectManagerCallback> mMyCallback;
-    std::map<AudioDeviceTypeAddr, sp<DeviceEffectProxy>> mDeviceEffects;
+    std::map<AudioDeviceTypeAddr, sp<IAfDeviceEffectProxy>> mDeviceEffects;
 };
 
+public: // TODO(b/288339104) extract inner class.
 class DeviceEffectManagerCallback : public EffectCallbackInterface {
 public:
     explicit DeviceEffectManagerCallback(DeviceEffectManager& manager)
@@ -84,7 +85,9 @@
             }
     status_t allocateHalBuffer(size_t size __unused,
             sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; }
-    bool updateOrphanEffectChains(const sp<EffectBase>& effect __unused) override { return false; }
+    bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect __unused) override {
+        return false;
+    }
 
     audio_io_handle_t io() const override  { return AUDIO_IO_HANDLE_NONE; }
     bool isOutput() const override { return false; }
@@ -112,19 +115,19 @@
         return NO_ERROR;
     }
 
-    bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+    bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override;
     void setVolumeForOutput(float left __unused, float right __unused) const override {}
 
     // check if effects should be suspended or restored when a given effect is enable or disabled
-    void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect __unused,
+    void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect __unused,
                           bool enabled __unused, bool threadLocked __unused) override {}
     void resetVolume() override {}
     product_strategy_t strategy() const override  { return static_cast<product_strategy_t>(0); }
     int32_t activeTrackCnt() const override { return 0; }
-    void onEffectEnable(const sp<EffectBase>& effect __unused) override {}
-    void onEffectDisable(const sp<EffectBase>& effect __unused) override {}
+    void onEffectEnable(const sp<IAfEffectBase>& effect __unused) override {}
+    void onEffectDisable(const sp<IAfEffectBase>& effect __unused) override {}
 
-    wp<EffectChain> chain() const override { return nullptr; }
+    wp<IAfEffectChain> chain() const override { return nullptr; }
 
     bool isAudioPolicyReady() const override {
         return mManager.audioFlinger().isAudioPolicyReady();
@@ -143,3 +146,4 @@
 private:
     DeviceEffectManager& mManager;
 };
+private:
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 822ea93..35edf3a 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -45,6 +45,7 @@
 
 #include "AudioFlinger.h"
 #include "EffectConfiguration.h"
+#include "Effects.h"
 
 // ----------------------------------------------------------------------------
 
@@ -93,9 +94,9 @@
 // ----------------------------------------------------------------------------
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectBase"
+#define LOG_TAG "EffectBase"
 
-AudioFlinger::EffectBase::EffectBase(const sp<AudioFlinger::EffectCallbackInterface>& callback,
+EffectBase::EffectBase(const sp<EffectCallbackInterface>& callback,
                                         effect_descriptor_t *desc,
                                         int id,
                                         audio_session_t sessionId,
@@ -107,7 +108,7 @@
 }
 
 // must be called with EffectModule::mLock held
-status_t AudioFlinger::EffectBase::setEnabled_l(bool enabled)
+status_t EffectBase::setEnabled_l(bool enabled)
 {
 
     ALOGV("setEnabled %p enabled %d", this, enabled);
@@ -139,7 +140,7 @@
             return NO_ERROR; // simply ignore as we are being destroyed
         }
         for (size_t i = 1; i < mHandles.size(); i++) {
-            EffectHandle *h = mHandles[i];
+            IAfEffectHandle *h = mHandles[i];
             if (h != NULL && !h->disconnected()) {
                 h->setEnabled(enabled);
             }
@@ -148,7 +149,7 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::EffectBase::setEnabled(bool enabled, bool fromHandle)
+status_t EffectBase::setEnabled(bool enabled, bool fromHandle)
 {
     status_t status;
     {
@@ -169,7 +170,7 @@
     return status;
 }
 
-bool AudioFlinger::EffectBase::isEnabled() const
+bool EffectBase::isEnabled() const
 {
     switch (mState) {
     case RESTART:
@@ -185,29 +186,29 @@
     }
 }
 
-void AudioFlinger::EffectBase::setSuspended(bool suspended)
+void EffectBase::setSuspended(bool suspended)
 {
     Mutex::Autolock _l(mLock);
     mSuspended = suspended;
 }
 
-bool AudioFlinger::EffectBase::suspended() const
+bool EffectBase::suspended() const
 {
     Mutex::Autolock _l(mLock);
     return mSuspended;
 }
 
-status_t AudioFlinger::EffectBase::addHandle(EffectHandle *handle)
+status_t EffectBase::addHandle(IAfEffectHandle *handle)
 {
     status_t status;
 
     Mutex::Autolock _l(mLock);
     int priority = handle->priority();
     size_t size = mHandles.size();
-    EffectHandle *controlHandle = NULL;
+    IAfEffectHandle *controlHandle = nullptr;
     size_t i;
     for (i = 0; i < size; i++) {
-        EffectHandle *h = mHandles[i];
+        IAfEffectHandle *h = mHandles[i];
         if (h == NULL || h->disconnected()) {
             continue;
         }
@@ -236,7 +237,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectBase::updatePolicyState()
+status_t EffectBase::updatePolicyState()
 {
     status_t status = NO_ERROR;
     bool doRegister = false;
@@ -266,7 +267,7 @@
         }
         // enable effect when registered according to enable state requested by controlling handle
         if (mHandles.size() > 0) {
-            EffectHandle *handle = controlHandle_l();
+            IAfEffectHandle *handle = controlHandle_l();
             if (handle != nullptr && mPolicyEnabled != handle->enabled()) {
                 doEnable = true;
                 mPolicyEnabled = handle->enabled();
@@ -305,13 +306,13 @@
 }
 
 
-ssize_t AudioFlinger::EffectBase::removeHandle(EffectHandle *handle)
+ssize_t EffectBase::removeHandle(IAfEffectHandle *handle)
 {
     Mutex::Autolock _l(mLock);
     return removeHandle_l(handle);
 }
 
-ssize_t AudioFlinger::EffectBase::removeHandle_l(EffectHandle *handle)
+ssize_t EffectBase::removeHandle_l(IAfEffectHandle *handle)
 {
     size_t size = mHandles.size();
     size_t i;
@@ -329,7 +330,7 @@
     mHandles.removeAt(i);
     // if removed from first place, move effect control from this handle to next in line
     if (i == 0) {
-        EffectHandle *h = controlHandle_l();
+        IAfEffectHandle *h = controlHandle_l();
         if (h != NULL) {
             h->setControl(true /*hasControl*/, true /*signal*/ , handle->enabled() /*enabled*/);
         }
@@ -346,11 +347,11 @@
 }
 
 // must be called with EffectModule::mLock held
-AudioFlinger::EffectHandle *AudioFlinger::EffectBase::controlHandle_l()
+IAfEffectHandle *EffectBase::controlHandle_l()
 {
     // the first valid handle in the list has control over the module
     for (size_t i = 0; i < mHandles.size(); i++) {
-        EffectHandle *h = mHandles[i];
+        IAfEffectHandle *h = mHandles[i];
         if (h != NULL && !h->disconnected()) {
             return h;
         }
@@ -360,7 +361,7 @@
 }
 
 // unsafe method called when the effect parent thread has been destroyed
-ssize_t AudioFlinger::EffectBase::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
+ssize_t EffectBase::disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast)
 {
     const auto callback = getCallback();
     ALOGV("disconnect() %p handle %p", this, handle);
@@ -378,11 +379,11 @@
     return numHandles;
 }
 
-bool AudioFlinger::EffectBase::purgeHandles()
+bool EffectBase::purgeHandles()
 {
     bool enabled = false;
     Mutex::Autolock _l(mLock);
-    EffectHandle *handle = controlHandle_l();
+    IAfEffectHandle *handle = controlHandle_l();
     if (handle != NULL) {
         enabled = handle->enabled();
     }
@@ -390,7 +391,7 @@
     return enabled;
 }
 
-void AudioFlinger::EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
+void EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
     getCallback()->checkSuspendOnEffectEnabled(this, enabled, threadLocked);
 }
 
@@ -499,7 +500,7 @@
     return s;
 }
 
-void AudioFlinger::EffectBase::dump(int fd, const Vector<String16>& args __unused)
+void EffectBase::dump(int fd, const Vector<String16>& args __unused) const
 NO_THREAD_SAFETY_ANALYSIS // conditional try lock
 {
     String8 result;
@@ -537,7 +538,7 @@
     result.append("\t\t\t  Pid Priority Ctrl Locked client server\n");
     char buffer[256];
     for (size_t i = 0; i < mHandles.size(); ++i) {
-        EffectHandle *handle = mHandles[i];
+        IAfEffectHandle *handle = mHandles[i];
         if (handle != NULL && !handle->disconnected()) {
             handle->dumpToBuffer(buffer, sizeof(buffer));
             result.append(buffer);
@@ -555,9 +556,9 @@
 // ----------------------------------------------------------------------------
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectModule"
+#define LOG_TAG "EffectModule"
 
-AudioFlinger::EffectModule::EffectModule(const sp<AudioFlinger::EffectCallbackInterface>& callback,
+EffectModule::EffectModule(const sp<EffectCallbackInterface>& callback,
                                          effect_descriptor_t *desc,
                                          int id,
                                          audio_session_t sessionId,
@@ -599,7 +600,7 @@
     ALOGV("Constructor Error %d", mStatus);
 }
 
-AudioFlinger::EffectModule::~EffectModule()
+EffectModule::~EffectModule()
 {
     ALOGV("Destructor %p", this);
     if (mEffectInterface != 0) {
@@ -612,7 +613,7 @@
 
 }
 
-bool AudioFlinger::EffectModule::updateState() {
+bool EffectModule::updateState() {
     Mutex::Autolock _l(mLock);
 
     bool started = false;
@@ -667,7 +668,7 @@
     return started;
 }
 
-void AudioFlinger::EffectModule::process()
+void EffectModule::process()
 {
     Mutex::Autolock _l(mLock);
 
@@ -821,7 +822,7 @@
     }
 }
 
-void AudioFlinger::EffectModule::reset_l()
+void EffectModule::reset_l()
 {
     if (mStatus != NO_ERROR || mEffectInterface == 0) {
         return;
@@ -829,7 +830,7 @@
     mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, 0, NULL);
 }
 
-status_t AudioFlinger::EffectModule::configure()
+status_t EffectModule::configure()
 {
     ALOGVV("configure() started");
     status_t status;
@@ -1015,7 +1016,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::init()
+status_t EffectModule::init()
 {
     Mutex::Autolock _l(mLock);
     if (mEffectInterface == 0) {
@@ -1034,7 +1035,7 @@
     return status;
 }
 
-void AudioFlinger::EffectModule::addEffectToHal_l()
+void EffectModule::addEffectToHal_l()
 {
     if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
          (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
@@ -1048,7 +1049,7 @@
 }
 
 // start() must be called with PlaybackThread::mLock or EffectChain::mLock held
-status_t AudioFlinger::EffectModule::start()
+status_t EffectModule::start()
 {
     status_t status;
     {
@@ -1061,7 +1062,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::start_l()
+status_t EffectModule::start_l()
 {
     if (mEffectInterface == 0) {
         return NO_INIT;
@@ -1085,13 +1086,13 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::stop()
+status_t EffectModule::stop()
 {
     Mutex::Autolock _l(mLock);
     return stop_l();
 }
 
-status_t AudioFlinger::EffectModule::stop_l()
+status_t EffectModule::stop_l()
 {
     if (mEffectInterface == 0) {
         return NO_INIT;
@@ -1125,7 +1126,7 @@
 }
 
 // must be called with EffectChain::mLock held
-void AudioFlinger::EffectModule::release_l()
+void EffectModule::release_l()
 {
     if (mEffectInterface != 0) {
         removeEffectFromHal_l();
@@ -1135,7 +1136,7 @@
     }
 }
 
-status_t AudioFlinger::EffectModule::removeEffectFromHal_l()
+status_t EffectModule::removeEffectFromHal_l()
 {
     if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
              (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
@@ -1155,7 +1156,7 @@
     return remainder == 0 ? 0 : divisor - remainder;
 }
 
-status_t AudioFlinger::EffectModule::command(int32_t cmdCode,
+status_t EffectModule::command(int32_t cmdCode,
                      const std::vector<uint8_t>& cmdData,
                      int32_t maxReplySize,
                      std::vector<uint8_t>* reply)
@@ -1228,7 +1229,7 @@
     reply->resize(status == NO_ERROR ? replySize : 0);
     if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
         for (size_t i = 1; i < mHandles.size(); i++) {
-            EffectHandle *h = mHandles[i];
+            IAfEffectHandle *h = mHandles[i];
             if (h != NULL && !h->disconnected()) {
                 h->commandExecuted(cmdCode, cmdData, *reply);
             }
@@ -1237,7 +1238,7 @@
     return status;
 }
 
-bool AudioFlinger::EffectModule::isProcessEnabled() const
+bool EffectModule::isProcessEnabled() const
 {
     if (mStatus != NO_ERROR) {
         return false;
@@ -1257,17 +1258,17 @@
     }
 }
 
-bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
+bool EffectModule::isOffloadedOrDirect() const
 {
     return getCallback()->isOffloadOrDirect();
 }
 
-bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
+bool EffectModule::isVolumeControlEnabled() const
 {
     return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled()));
 }
 
-void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+void EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
     ALOGVV("setInBuffer %p",(&buffer));
 
     // mConfig.inputCfg.buffer.frameCount may be zero if configure() is not called yet.
@@ -1313,7 +1314,7 @@
     }
 }
 
-void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+void EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
     ALOGVV("setOutBuffer %p",(&buffer));
 
     // mConfig.outputCfg.buffer.frameCount may be zero if configure() is not called yet.
@@ -1355,7 +1356,7 @@
     }
 }
 
-status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
+status_t EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
 {
     AutoLockReentrant _l(mLock, mSetVolumeReentrantTid);
     if (mStatus != NO_ERROR) {
@@ -1373,7 +1374,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setVolumeInternal(
+status_t EffectModule::setVolumeInternal(
         uint32_t *left, uint32_t *right, bool controller) {
     uint32_t volume[2] = {*left, *right};
     uint32_t *pVolume = controller ? volume : nullptr;
@@ -1390,7 +1391,7 @@
     return status;
 }
 
-void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
+void EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
 {
     // for offload or direct thread, if the effect chain has non-offloadable
     // effect and any effect module within the chain has volume control, then
@@ -1403,7 +1404,7 @@
     }
 }
 
-status_t AudioFlinger::EffectModule::sendSetAudioDevicesCommand(
+status_t EffectModule::sendSetAudioDevicesCommand(
         const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode)
 {
     audio_devices_t deviceType = deviceTypesToBitMask(getAudioDeviceTypes(devices));
@@ -1429,17 +1430,17 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
+status_t EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
 {
     return sendSetAudioDevicesCommand(devices, EFFECT_CMD_SET_DEVICE);
 }
 
-status_t AudioFlinger::EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
+status_t EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
 {
     return sendSetAudioDevicesCommand({device}, EFFECT_CMD_SET_INPUT_DEVICE);
 }
 
-status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
+status_t EffectModule::setMode(audio_mode_t mode)
 {
     Mutex::Autolock _l(mLock);
     if (mStatus != NO_ERROR) {
@@ -1461,7 +1462,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setAudioSource(audio_source_t source)
+status_t EffectModule::setAudioSource(audio_source_t source)
 {
     Mutex::Autolock _l(mLock);
     if (mStatus != NO_ERROR) {
@@ -1479,7 +1480,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
+status_t EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
 {
     Mutex::Autolock _l(mLock);
     if (mStatus != NO_ERROR) {
@@ -1512,22 +1513,22 @@
     return status;
 }
 
-bool AudioFlinger::EffectModule::isOffloaded() const
+bool EffectModule::isOffloaded() const
 {
     Mutex::Autolock _l(mLock);
     return mOffloaded;
 }
 
 /*static*/
-bool AudioFlinger::EffectModule::isHapticGenerator(const effect_uuid_t *type) {
+bool IAfEffectModule::isHapticGenerator(const effect_uuid_t *type) {
     return memcmp(type, FX_IID_HAPTICGENERATOR, sizeof(effect_uuid_t)) == 0;
 }
 
-bool AudioFlinger::EffectModule::isHapticGenerator() const {
-    return isHapticGenerator(&mDescriptor.type);
+bool EffectModule::isHapticGenerator() const {
+    return IAfEffectModule::isHapticGenerator(&mDescriptor.type);
 }
 
-status_t AudioFlinger::EffectModule::setHapticIntensity(int id, os::HapticScale intensity)
+status_t EffectModule::setHapticIntensity(int id, os::HapticScale intensity)
 {
     if (mStatus != NO_ERROR) {
         return mStatus;
@@ -1553,7 +1554,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo)
+status_t EffectModule::setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo)
 {
     if (mStatus != NO_ERROR) {
         return mStatus;
@@ -1583,7 +1584,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::getConfigs(
+status_t EffectModule::getConfigs(
         audio_config_base_t* inputCfg, audio_config_base_t* outputCfg, bool* isOutput) const {
     Mutex::Autolock _l(mLock);
     if (mConfig.inputCfg.mask == 0 || mConfig.outputCfg.mask == 0) {
@@ -1614,7 +1615,7 @@
     return ss.str();
 }
 
-void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
+void EffectModule::dump(int fd, const Vector<String16>& args) const
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     EffectBase::dump(fd, args);
@@ -1672,9 +1673,21 @@
 // ----------------------------------------------------------------------------
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectHandle"
+#define LOG_TAG "EffectHandle"
 
-AudioFlinger::EffectHandle::EffectHandle(const sp<EffectBase>& effect,
+/* static */
+sp<IAfEffectHandle> IAfEffectHandle::create(
+        const sp<IAfEffectBase>& effect,
+        const sp<RefBase /*AudioFlinger::Client */>& client, // TODO(b/288339104) update type
+        const sp<media::IEffectClient>& effectClient,
+        int32_t priority, bool notifyFramesProcessed)
+{
+    return sp<EffectHandle>::make(
+            effect, sp<AudioFlinger::Client>::cast(client),
+            effectClient, priority, notifyFramesProcessed);
+}
+
+EffectHandle::EffectHandle(const sp<IAfEffectBase>& effect,
                                          const sp<AudioFlinger::Client>& client,
                                          const sp<media::IEffectClient>& effectClient,
                                          int32_t priority, bool notifyFramesProcessed)
@@ -1709,7 +1722,7 @@
     mBuffer = (uint8_t *)mCblk + bufOffset;
 }
 
-AudioFlinger::EffectHandle::~EffectHandle()
+EffectHandle::~EffectHandle()
 {
     ALOGV("Destructor %p", this);
     disconnect(false);
@@ -1742,7 +1755,7 @@
     return methodStatistics;
 }
 
-status_t AudioFlinger::EffectHandle::onTransact(
+status_t EffectHandle::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
     const std::string methodName = getIEffectStatistics().getMethodForCode(code);
     mediautils::TimeCheck check(
@@ -1757,7 +1770,7 @@
     return BnEffect::onTransact(code, data, reply, flags);
 }
 
-status_t AudioFlinger::EffectHandle::initCheck()
+status_t EffectHandle::initCheck() const
 {
     return mClient == 0 || mCblkMemory != 0 ? OK : NO_MEMORY;
 }
@@ -1773,11 +1786,11 @@
         std::move(_tmp.value());                        \
     })
 
-Status AudioFlinger::EffectHandle::enable(int32_t* _aidl_return)
+Status EffectHandle::enable(int32_t* _aidl_return)
 {
     AutoMutex _l(mLock);
     ALOGV("enable %p", this);
-    sp<EffectBase> effect = mEffect.promote();
+    sp<IAfEffectBase> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
         RETURN(DEAD_OBJECT);
     }
@@ -1811,11 +1824,11 @@
     RETURN(status);
 }
 
-Status AudioFlinger::EffectHandle::disable(int32_t* _aidl_return)
+Status EffectHandle::disable(int32_t* _aidl_return)
 {
     ALOGV("disable %p", this);
     AutoMutex _l(mLock);
-    sp<EffectBase> effect = mEffect.promote();
+    sp<IAfEffectBase> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
         RETURN(DEAD_OBJECT);
     }
@@ -1838,14 +1851,14 @@
     RETURN(status);
 }
 
-Status AudioFlinger::EffectHandle::disconnect()
+Status EffectHandle::disconnect()
 {
     ALOGV("%s %p", __FUNCTION__, this);
     disconnect(true);
     return Status::ok();
 }
 
-void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
+void EffectHandle::disconnect(bool unpinIfLast)
 {
     AutoMutex _l(mLock);
     ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this);
@@ -1857,7 +1870,7 @@
     }
     mDisconnected = true;
     {
-        sp<EffectBase> effect = mEffect.promote();
+        sp<IAfEffectBase> effect = mEffect.promote();
         if (effect != 0) {
             if (effect->disconnectHandle(this, unpinIfLast) > 0) {
                 ALOGW("%s Effect handle %p disconnected after thread destruction",
@@ -1879,19 +1892,19 @@
     }
 }
 
-Status AudioFlinger::EffectHandle::getCblk(media::SharedFileRegion* _aidl_return) {
+Status EffectHandle::getCblk(media::SharedFileRegion* _aidl_return) {
     LOG_ALWAYS_FATAL_IF(!convertIMemoryToSharedFileRegion(mCblkMemory, _aidl_return));
     return Status::ok();
 }
 
-Status AudioFlinger::EffectHandle::getConfig(
+Status EffectHandle::getConfig(
         media::EffectConfig* _config, int32_t* _aidl_return) {
     AutoMutex _l(mLock);
-    sp<EffectBase> effect = mEffect.promote();
+    sp<IAfEffectBase> effect = mEffect.promote();
     if (effect == nullptr || mDisconnected) {
         RETURN(DEAD_OBJECT);
     }
-    sp<EffectModule> effectModule = effect->asEffectModule();
+    sp<IAfEffectModule> effectModule = effect->asEffectModule();
     if (effectModule == nullptr) {
         RETURN(INVALID_OPERATION);
     }
@@ -1910,7 +1923,7 @@
     RETURN(status);
 }
 
-Status AudioFlinger::EffectHandle::command(int32_t cmdCode,
+Status EffectHandle::command(int32_t cmdCode,
                        const std::vector<uint8_t>& cmdData,
                        int32_t maxResponseSize,
                        std::vector<uint8_t>* response,
@@ -1954,7 +1967,7 @@
     }
 
     AutoMutex _l(mLock);
-    sp<EffectBase> effect = mEffect.promote();
+    sp<IAfEffectBase> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
         RETURN(DEAD_OBJECT);
     }
@@ -2043,7 +2056,7 @@
     RETURN(status);
 }
 
-void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
+void EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
 {
     ALOGV("setControl %p control %d", this, hasControl);
 
@@ -2055,7 +2068,7 @@
     }
 }
 
-void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
+void EffectHandle::commandExecuted(uint32_t cmdCode,
                          const std::vector<uint8_t>& cmdData,
                          const std::vector<uint8_t>& replyData)
 {
@@ -2066,21 +2079,21 @@
 
 
 
-void AudioFlinger::EffectHandle::setEnabled(bool enabled)
+void EffectHandle::setEnabled(bool enabled)
 {
     if (mEffectClient != 0) {
         mEffectClient->enableStatusChanged(enabled);
     }
 }
 
-void AudioFlinger::EffectHandle::framesProcessed(int32_t frames) const
+void EffectHandle::framesProcessed(int32_t frames) const
 {
     if (mEffectClient != 0 && mNotifyFramesProcessed) {
         mEffectClient->framesProcessed(frames);
     }
 }
 
-void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
+void EffectHandle::dumpToBuffer(char* buffer, size_t size) const
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
@@ -2100,16 +2113,25 @@
 }
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectChain"
+#define LOG_TAG "EffectChain"
 
-AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread,
+/* static */
+sp<IAfEffectChain> IAfEffectChain::create(
+        const wp<Thread /*ThreadBase*/>& wThread,  // TODO(b/288339104) update type
+        audio_session_t sessionId)
+{
+    // TODO(b/288339104) no weak pointer cast.
+    return sp<EffectChain>::make(sp<AudioFlinger::ThreadBase>::cast(wThread.promote()), sessionId);
+}
+
+EffectChain::EffectChain(const wp<AudioFlinger::ThreadBase>& thread,
                                        audio_session_t sessionId)
     : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
       mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
       mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
       mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
 {
-    sp<ThreadBase> p = thread.promote();
+    sp<AudioFlinger::ThreadBase> p = thread.promote();
     if (p == nullptr) {
         return;
     }
@@ -2118,13 +2140,13 @@
                                     p->frameCount();
 }
 
-AudioFlinger::EffectChain::~EffectChain()
+EffectChain::~EffectChain()
 {
 }
 
-// getEffectFromDesc_l() must be called with ThreadBase::mLock held
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(
-        effect_descriptor_t *descriptor)
+// getEffectFromDesc_l() must be called with AudioFlinger::ThreadBase::mLock held
+sp<IAfEffectModule> EffectChain::getEffectFromDesc_l(
+        effect_descriptor_t *descriptor) const
 {
     size_t size = mEffects.size();
 
@@ -2136,8 +2158,8 @@
     return 0;
 }
 
-// getEffectFromId_l() must be called with ThreadBase::mLock held
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
+// getEffectFromId_l() must be called with AudioFlinger::ThreadBase::mLock held
+sp<IAfEffectModule> EffectChain::getEffectFromId_l(int id) const
 {
     size_t size = mEffects.size();
 
@@ -2150,9 +2172,9 @@
     return 0;
 }
 
-// getEffectFromType_l() must be called with ThreadBase::mLock held
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
-        const effect_uuid_t *type)
+// getEffectFromType_l() must be called with AudioFlinger::ThreadBase::mLock held
+sp<IAfEffectModule> EffectChain::getEffectFromType_l(
+        const effect_uuid_t *type) const
 {
     size_t size = mEffects.size();
 
@@ -2164,7 +2186,7 @@
     return 0;
 }
 
-std::vector<int> AudioFlinger::EffectChain::getEffectIds()
+std::vector<int> EffectChain::getEffectIds() const
 {
     std::vector<int> ids;
     Mutex::Autolock _l(mLock);
@@ -2174,14 +2196,14 @@
     return ids;
 }
 
-void AudioFlinger::EffectChain::clearInputBuffer()
+void EffectChain::clearInputBuffer()
 {
     Mutex::Autolock _l(mLock);
     clearInputBuffer_l();
 }
 
 // Must be called with EffectChain::mLock locked
-void AudioFlinger::EffectChain::clearInputBuffer_l()
+void EffectChain::clearInputBuffer_l()
 {
     if (mInBuffer == NULL) {
         return;
@@ -2194,7 +2216,7 @@
 }
 
 // Must be called with EffectChain::mLock locked
-void AudioFlinger::EffectChain::process_l()
+void EffectChain::process_l()
 {
     // never process effects when:
     // - on an OFFLOAD thread
@@ -2245,8 +2267,8 @@
     }
 }
 
-// createEffect_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect,
+// createEffect_l() must be called with AudioFlinger::ThreadBase::mLock held
+status_t EffectChain::createEffect_l(sp<IAfEffectModule>& effect,
                                                    effect_descriptor_t *desc,
                                                    int id,
                                                    audio_session_t sessionId,
@@ -2264,14 +2286,14 @@
     return lStatus;
 }
 
-// addEffect_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
+// addEffect_l() must be called with AudioFlinger::ThreadBase::mLock held
+status_t EffectChain::addEffect_l(const sp<IAfEffectModule>& effect)
 {
     Mutex::Autolock _l(mLock);
     return addEffect_ll(effect);
 }
-// addEffect_l() must be called with ThreadBase::mLock and EffectChain::mLock held
-status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
+// addEffect_l() must be called with AudioFlinger::ThreadBase::mLock and EffectChain::mLock held
+status_t EffectChain::addEffect_ll(const sp<IAfEffectModule>& effect)
 {
     effect->setCallback(mEffectCallback);
 
@@ -2351,7 +2373,7 @@
     return NO_ERROR;
 }
 
-ssize_t AudioFlinger::EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
+ssize_t EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
     // Insert effects are inserted at the end of mEffects vector as they are processed
     //  after track and auxiliary effects.
     // Insert effect order as a function of indicated preference:
@@ -2424,8 +2446,8 @@
     return idx_insert;
 }
 
-// removeEffect_l() must be called with ThreadBase::mLock held
-size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect,
+// removeEffect_l() must be called with AudioFlinger::ThreadBase::mLock held
+size_t EffectChain::removeEffect_l(const sp<IAfEffectModule>& effect,
                                                  bool release)
 {
     Mutex::Autolock _l(mLock);
@@ -2472,8 +2494,8 @@
     return mEffects.size();
 }
 
-// setDevices_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
+// setDevices_l() must be called with AudioFlinger::ThreadBase::mLock held
+void EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2481,8 +2503,8 @@
     }
 }
 
-// setInputDevice_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
+// setInputDevice_l() must be called with AudioFlinger::ThreadBase::mLock held
+void EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2490,8 +2512,8 @@
     }
 }
 
-// setMode_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
+// setMode_l() must be called with AudioFlinger::ThreadBase::mLock held
+void EffectChain::setMode_l(audio_mode_t mode)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2499,8 +2521,8 @@
     }
 }
 
-// setAudioSource_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
+// setAudioSource_l() must be called with AudioFlinger::ThreadBase::mLock held
+void EffectChain::setAudioSource_l(audio_source_t source)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2508,15 +2530,15 @@
     }
 }
 
-bool AudioFlinger::EffectChain::hasVolumeControlEnabled_l() const {
+bool EffectChain::hasVolumeControlEnabled_l() const {
     for (const auto &effect : mEffects) {
         if (effect->isVolumeControlEnabled()) return true;
     }
     return false;
 }
 
-// setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
-bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
+// setVolume_l() must be called with AudioFlinger::ThreadBase::mLock or EffectChain::mLock held
+bool EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
 {
     uint32_t newLeft = *left;
     uint32_t newRight = *right;
@@ -2582,8 +2604,8 @@
     return hasControl;
 }
 
-// resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
-void AudioFlinger::EffectChain::resetVolume_l()
+// resetVolume_l() must be called with AudioFlinger::ThreadBase::mLock or EffectChain::mLock held
+void EffectChain::resetVolume_l()
 {
     if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
         uint32_t left = mLeftVolume;
@@ -2592,8 +2614,9 @@
     }
 }
 
-// containsHapticGeneratingEffect_l must be called with ThreadBase::mLock or EffectChain::mLock held
-bool AudioFlinger::EffectChain::containsHapticGeneratingEffect_l()
+// containsHapticGeneratingEffect_l must be called with
+// AudioFlinger::ThreadBase::mLock or EffectChain::mLock held
+bool EffectChain::containsHapticGeneratingEffect_l()
 {
     for (size_t i = 0; i < mEffects.size(); ++i) {
         if (mEffects[i]->isHapticGenerator()) {
@@ -2603,7 +2626,7 @@
     return false;
 }
 
-void AudioFlinger::EffectChain::setHapticIntensity_l(int id, os::HapticScale intensity)
+void EffectChain::setHapticIntensity_l(int id, os::HapticScale intensity)
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mEffects.size(); ++i) {
@@ -2611,7 +2634,7 @@
     }
 }
 
-void AudioFlinger::EffectChain::syncHalEffectsState()
+void EffectChain::syncHalEffectsState()
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mEffects.size(); i++) {
@@ -2622,7 +2645,7 @@
     }
 }
 
-void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
+void EffectChain::dump(int fd, const Vector<String16>& args) const
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     String8 result;
@@ -2647,7 +2670,7 @@
         write(fd, result.string(), result.size());
 
         for (size_t i = 0; i < numEffects; ++i) {
-            sp<EffectModule> effect = mEffects[i];
+            sp<IAfEffectModule> effect = mEffects[i];
             if (effect != 0) {
                 effect->dump(fd, args);
             }
@@ -2661,8 +2684,8 @@
     }
 }
 
-// must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setEffectSuspended_l(
+// must be called with AudioFlinger::ThreadBase::mLock held
+void EffectChain::setEffectSuspended_l(
         const effect_uuid_t *type, bool suspend)
 {
     sp<SuspendedEffectDesc> desc;
@@ -2680,7 +2703,7 @@
         }
 
         if (desc->mRefCount++ == 0) {
-            sp<EffectModule> effect = getEffectIfEnabled(type);
+            sp<IAfEffectModule> effect = getEffectIfEnabled(type);
             if (effect != 0) {
                 desc->mEffect = effect;
                 effect->setSuspended(true);
@@ -2700,11 +2723,11 @@
         if (--desc->mRefCount == 0) {
             ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
             if (desc->mEffect != 0) {
-                sp<EffectModule> effect = desc->mEffect.promote();
+                sp<IAfEffectModule> effect = desc->mEffect.promote();
                 if (effect != 0) {
                     effect->setSuspended(false);
                     effect->lock();
-                    EffectHandle *handle = effect->controlHandle_l();
+                    IAfEffectHandle *handle = effect->controlHandle_l();
                     if (handle != NULL && !handle->disconnected()) {
                         effect->setEnabled_l(handle->enabled());
                     }
@@ -2717,8 +2740,8 @@
     }
 }
 
-// must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
+// must be called with AudioFlinger::ThreadBase::mLock held
+void EffectChain::setEffectSuspendedAll_l(bool suspend)
 {
     sp<SuspendedEffectDesc> desc;
 
@@ -2732,7 +2755,7 @@
             ALOGV("setEffectSuspendedAll_l() add entry for 0");
         }
         if (desc->mRefCount++ == 0) {
-            Vector< sp<EffectModule> > effects;
+            Vector< sp<IAfEffectModule> > effects;
             getSuspendEligibleEffects(effects);
             for (size_t i = 0; i < effects.size(); i++) {
                 setEffectSuspended_l(&effects[i]->desc().type, true);
@@ -2774,7 +2797,7 @@
 #endif //OPENSL_ES_H_
 
 /* static */
-bool AudioFlinger::EffectChain::isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type)
+bool EffectChain::isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type)
 {
     // Only NS and AEC are suspended when BtNRec is off
     if ((memcmp(type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) ||
@@ -2784,7 +2807,7 @@
     return false;
 }
 
-bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
+bool EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
 {
     // auxiliary effects and visualizer are never suspended on output mix
     if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
@@ -2797,8 +2820,8 @@
     return true;
 }
 
-void AudioFlinger::EffectChain::getSuspendEligibleEffects(
-        Vector< sp<AudioFlinger::EffectModule> > &effects)
+void EffectChain::getSuspendEligibleEffects(
+        Vector< sp<IAfEffectModule> > &effects)
 {
     effects.clear();
     for (size_t i = 0; i < mEffects.size(); i++) {
@@ -2808,14 +2831,13 @@
     }
 }
 
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
-                                                            const effect_uuid_t *type)
+sp<IAfEffectModule> EffectChain::getEffectIfEnabled(const effect_uuid_t *type)
 {
-    sp<EffectModule> effect = getEffectFromType_l(type);
+    sp<IAfEffectModule> effect = getEffectFromType_l(type);
     return effect != 0 && effect->isEnabled() ? effect : 0;
 }
 
-void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+void EffectChain::checkSuspendOnEffectEnabled(const sp<IAfEffectModule>& effect,
                                                             bool enabled)
 {
     ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
@@ -2857,13 +2879,13 @@
     }
 }
 
-bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
+bool EffectChain::isNonOffloadableEnabled() const
 {
     Mutex::Autolock _l(mLock);
     return isNonOffloadableEnabled_l();
 }
 
-bool AudioFlinger::EffectChain::isNonOffloadableEnabled_l()
+bool EffectChain::isNonOffloadableEnabled_l() const
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2874,13 +2896,13 @@
     return false;
 }
 
-void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread)
+void EffectChain::setThread(const sp<AudioFlinger::ThreadBase>& thread)
 {
     Mutex::Autolock _l(mLock);
     mEffectCallback->setThread(thread);
 }
 
-void AudioFlinger::EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
+void EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
 {
     if ((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
         *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
@@ -2893,7 +2915,7 @@
     }
 }
 
-void AudioFlinger::EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
+void EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
 {
     if ((*flags & AUDIO_INPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
         *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_RAW);
@@ -2903,7 +2925,7 @@
     }
 }
 
-bool AudioFlinger::EffectChain::isRawCompatible() const
+bool EffectChain::isRawCompatible() const
 {
     Mutex::Autolock _l(mLock);
     for (const auto &effect : mEffects) {
@@ -2915,7 +2937,7 @@
     return true;
 }
 
-bool AudioFlinger::EffectChain::isFastCompatible() const
+bool EffectChain::isFastCompatible() const
 {
     Mutex::Autolock _l(mLock);
     for (const auto &effect : mEffects) {
@@ -2928,7 +2950,7 @@
     return true;
 }
 
-bool AudioFlinger::EffectChain::isBitPerfectCompatible() const {
+bool EffectChain::isBitPerfectCompatible() const {
     Mutex::Autolock _l(mLock);
     for (const auto &effect : mEffects) {
         if (effect->isProcessImplemented()
@@ -2941,7 +2963,7 @@
 }
 
 // isCompatibleWithThread_l() must be called with thread->mLock held
-bool AudioFlinger::EffectChain::isCompatibleWithThread_l(const sp<ThreadBase>& thread) const
+bool EffectChain::isCompatibleWithThread_l(const sp<AudioFlinger::ThreadBase>& thread) const
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mEffects.size(); i++) {
@@ -2953,7 +2975,7 @@
 }
 
 // EffectCallbackInterface implementation
-status_t AudioFlinger::EffectChain::EffectCallback::createEffectHal(
+status_t EffectChain::EffectCallback::createEffectHal(
         const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
         sp<EffectHalInterface> *effect) {
     status_t status = NO_INIT;
@@ -2965,21 +2987,21 @@
     return status;
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::updateOrphanEffectChains(
-        const sp<AudioFlinger::EffectBase>& effect) {
+bool EffectChain::EffectCallback::updateOrphanEffectChains(
+        const sp<IAfEffectBase>& effect) {
     // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
     return mAudioFlinger.updateOrphanEffectChains(effect->asEffectModule());
 }
 
-status_t AudioFlinger::EffectChain::EffectCallback::allocateHalBuffer(
+status_t EffectChain::EffectCallback::allocateHalBuffer(
         size_t size, sp<EffectBufferHalInterface>* buffer) {
     return mAudioFlinger.mEffectsFactoryHal->allocateBuffer(size, buffer);
 }
 
-status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
+status_t EffectChain::EffectCallback::addEffectToHal(
         const sp<EffectHalInterface>& effect) {
     status_t result = NO_INIT;
-    sp<ThreadBase> t = thread().promote();
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return result;
     }
@@ -2992,10 +3014,10 @@
     return result;
 }
 
-status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
+status_t EffectChain::EffectCallback::removeEffectFromHal(
         const sp<EffectHalInterface>& effect) {
     status_t result = NO_INIT;
-    sp<ThreadBase> t = thread().promote();
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return result;
     }
@@ -3008,64 +3030,65 @@
     return result;
 }
 
-audio_io_handle_t AudioFlinger::EffectChain::EffectCallback::io() const {
-    sp<ThreadBase> t = thread().promote();
+audio_io_handle_t EffectChain::EffectCallback::io() const {
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_IO_HANDLE_NONE;
     }
     return t->id();
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isOutput() const {
-    sp<ThreadBase> t = thread().promote();
+bool EffectChain::EffectCallback::isOutput() const {
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return true;
     }
     return t->isOutput();
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isOffload() const {
-    return mThreadType == ThreadBase::OFFLOAD;
+bool EffectChain::EffectCallback::isOffload() const {
+    return mThreadType == AudioFlinger::ThreadBase::OFFLOAD;
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrDirect() const {
-    return mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT;
+bool EffectChain::EffectCallback::isOffloadOrDirect() const {
+    return mThreadType == AudioFlinger::ThreadBase::OFFLOAD
+            || mThreadType == AudioFlinger::ThreadBase::DIRECT;
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrMmap() const {
+bool EffectChain::EffectCallback::isOffloadOrMmap() const {
     switch (mThreadType) {
-    case ThreadBase::OFFLOAD:
-    case ThreadBase::MMAP_PLAYBACK:
-    case ThreadBase::MMAP_CAPTURE:
+    case AudioFlinger::ThreadBase::OFFLOAD:
+    case AudioFlinger::ThreadBase::MMAP_PLAYBACK:
+    case AudioFlinger::ThreadBase::MMAP_CAPTURE:
         return true;
     default:
         return false;
     }
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isSpatializer() const {
-    return mThreadType == ThreadBase::SPATIALIZER;
+bool EffectChain::EffectCallback::isSpatializer() const {
+    return mThreadType == AudioFlinger::ThreadBase::SPATIALIZER;
 }
 
-uint32_t AudioFlinger::EffectChain::EffectCallback::sampleRate() const {
-    sp<ThreadBase> t = thread().promote();
+uint32_t EffectChain::EffectCallback::sampleRate() const {
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
     return t->sampleRate();
 }
 
-audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::inChannelMask(int id) const {
-    sp<ThreadBase> t = thread().promote();
+audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const {
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
-    sp<EffectChain> c = chain().promote();
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
 
-    if (mThreadType == ThreadBase::SPATIALIZER) {
+    if (mThreadType == AudioFlinger::ThreadBase::SPATIALIZER) {
         if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
             if (c->isFirstEffect(id)) {
                 return t->mixerChannelMask();
@@ -3073,7 +3096,8 @@
                 return t->channelMask();
             }
         } else if (!audio_is_global_session(c->sessionId())) {
-            if ((t->hasAudioSession_l(c->sessionId()) & ThreadBase::SPATIALIZED_SESSION) != 0) {
+            if ((t->hasAudioSession_l(c->sessionId())
+                    & AudioFlinger::ThreadBase::SPATIALIZED_SESSION) != 0) {
                 return t->mixerChannelMask();
             } else {
                 return t->channelMask();
@@ -3086,23 +3110,24 @@
     }
 }
 
-uint32_t AudioFlinger::EffectChain::EffectCallback::inChannelCount(int id) const {
+uint32_t EffectChain::EffectCallback::inChannelCount(int id) const {
     return audio_channel_count_from_out_mask(inChannelMask(id));
 }
 
-audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::outChannelMask() const {
-    sp<ThreadBase> t = thread().promote();
+audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const {
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
-    sp<EffectChain> c = chain().promote();
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
 
-    if (mThreadType == ThreadBase::SPATIALIZER) {
+    if (mThreadType == AudioFlinger::ThreadBase::SPATIALIZER) {
         if (!audio_is_global_session(c->sessionId())) {
-            if ((t->hasAudioSession_l(c->sessionId()) & ThreadBase::SPATIALIZED_SESSION) != 0) {
+            if ((t->hasAudioSession_l(c->sessionId())
+                    & AudioFlinger::ThreadBase::SPATIALIZED_SESSION) != 0) {
                 return t->mixerChannelMask();
             } else {
                 return t->channelMask();
@@ -3115,30 +3140,30 @@
     }
 }
 
-uint32_t AudioFlinger::EffectChain::EffectCallback::outChannelCount() const {
+uint32_t EffectChain::EffectCallback::outChannelCount() const {
     return audio_channel_count_from_out_mask(outChannelMask());
 }
 
-audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::hapticChannelMask() const {
-    sp<ThreadBase> t = thread().promote();
+audio_channel_mask_t EffectChain::EffectCallback::hapticChannelMask() const {
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
     return t->hapticChannelMask();
 }
 
-size_t AudioFlinger::EffectChain::EffectCallback::frameCount() const {
-    sp<ThreadBase> t = thread().promote();
+size_t EffectChain::EffectCallback::frameCount() const {
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
     return t->frameCount();
 }
 
-uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const
+uint32_t EffectChain::EffectCallback::latency() const
 NO_THREAD_SAFETY_ANALYSIS  // latency_l() access
 {
-    sp<ThreadBase> t = thread().promote();
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
@@ -3146,25 +3171,25 @@
     return t->latency_l();
 }
 
-void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
+void EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
 NO_THREAD_SAFETY_ANALYSIS  // setVolumeForOutput_l() access
 {
-    sp<ThreadBase> t = thread().promote();
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
     t->setVolumeForOutput_l(left, right);
 }
 
-void AudioFlinger::EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
-        const sp<EffectBase>& effect, bool enabled, bool threadLocked) {
-    sp<ThreadBase> t = thread().promote();
+void EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
+        const sp<IAfEffectBase>& effect, bool enabled, bool threadLocked) {
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
     t->checkSuspendOnEffectEnabled(enabled, effect->sessionId(), threadLocked);
 
-    sp<EffectChain> c = chain().promote();
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return;
     }
@@ -3172,8 +3197,8 @@
     c->checkSuspendOnEffectEnabled(effect->asEffectModule(), enabled);
 }
 
-void AudioFlinger::EffectChain::EffectCallback::onEffectEnable(const sp<EffectBase>& effect) {
-    sp<ThreadBase> t = thread().promote();
+void EffectChain::EffectCallback::onEffectEnable(const sp<IAfEffectBase>& effect) {
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
@@ -3181,19 +3206,19 @@
     t->onEffectEnable(effect->asEffectModule());
 }
 
-void AudioFlinger::EffectChain::EffectCallback::onEffectDisable(const sp<EffectBase>& effect) {
+void EffectChain::EffectCallback::onEffectDisable(const sp<IAfEffectBase>& effect) {
     checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
 
-    sp<ThreadBase> t = thread().promote();
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
     t->onEffectDisable();
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::disconnectEffectHandle(EffectHandle *handle,
+bool EffectChain::EffectCallback::disconnectEffectHandle(IAfEffectHandle *handle,
                                                       bool unpinIfLast) {
-    sp<ThreadBase> t = thread().promote();
+    sp<AudioFlinger::ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return false;
     }
@@ -3201,8 +3226,8 @@
     return true;
 }
 
-void AudioFlinger::EffectChain::EffectCallback::resetVolume() {
-    sp<EffectChain> c = chain().promote();
+void EffectChain::EffectCallback::resetVolume() {
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return;
     }
@@ -3210,16 +3235,16 @@
 
 }
 
-product_strategy_t AudioFlinger::EffectChain::EffectCallback::strategy() const {
-    sp<EffectChain> c = chain().promote();
+product_strategy_t EffectChain::EffectCallback::strategy() const {
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return PRODUCT_STRATEGY_NONE;
     }
     return c->strategy();
 }
 
-int32_t AudioFlinger::EffectChain::EffectCallback::activeTrackCnt() const {
-    sp<EffectChain> c = chain().promote();
+int32_t EffectChain::EffectCallback::activeTrackCnt() const {
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return 0;
     }
@@ -3228,9 +3253,20 @@
 
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::DeviceEffectProxy"
+#define LOG_TAG "DeviceEffectProxy"
 
-status_t AudioFlinger::DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
+/* static */
+sp<IAfDeviceEffectProxy> IAfDeviceEffectProxy::create(
+        const AudioDeviceTypeAddr& device,
+        const sp</* DeviceEffectManagerCallback */ RefBase>& callback,  // TODO(b/288339104) type
+        effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
+{
+    return sp<DeviceEffectProxy>::make(device,
+            sp<AudioFlinger::DeviceEffectManagerCallback>::cast(callback),
+            desc, id, notifyFramesProcessed);
+}
+
+status_t DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
 {
     status_t status = EffectBase::setEnabled(enabled, fromHandle);
     Mutex::Autolock _l(mProxyLock);
@@ -3238,9 +3274,9 @@
         for (auto& handle : mEffectHandles) {
             Status bs;
             if (enabled) {
-                bs = handle.second->enable(&status);
+                bs = handle.second->asIEffect()->enable(&status);
             } else {
-                bs = handle.second->disable(&status);
+                bs = handle.second->asIEffect()->disable(&status);
             }
             if (!bs.isOk()) {
               status = statusTFromBinderStatus(bs);
@@ -3251,8 +3287,8 @@
     return status;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::init(
-        const std::map <audio_patch_handle_t, PatchPanel::Patch>& patches) {
+status_t DeviceEffectProxy::init(
+        const std::map <audio_patch_handle_t, AudioFlinger::PatchPanel::Patch>& patches) {
 //For all audio patches
 //If src or sink device match
 //If the effect is HW accelerated
@@ -3274,10 +3310,10 @@
     return status;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::onCreatePatch(
+status_t DeviceEffectProxy::onCreatePatch(
         audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch) {
     status_t status = NAME_NOT_FOUND;
-    sp<EffectHandle> handle;
+    sp<IAfEffectHandle> handle;
     // only consider source[0] as this is the only "true" source of a patch
     status = checkPort(patch, &patch.mAudioPatch.sources[0], &handle);
     ALOGV("%s source checkPort status %d", __func__, status);
@@ -3295,8 +3331,8 @@
     return status;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::checkPort(const PatchPanel::Patch& patch,
-        const struct audio_port_config *port, sp <EffectHandle> *handle) {
+status_t DeviceEffectProxy::checkPort(const AudioFlinger::PatchPanel::Patch& patch,
+        const struct audio_port_config *port, sp<IAfEffectHandle> *handle) {
 
     ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
             __func__, port->type, port->ext.device.type,
@@ -3341,7 +3377,7 @@
             mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
         }
     } else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
-        sp <ThreadBase> thread;
+        sp <AudioFlinger::ThreadBase> thread;
         if (audio_port_config_has_input_direction(port)) {
             if (patch.isSoftware()) {
                 thread = patch.mRecord.thread();
@@ -3368,9 +3404,9 @@
     if (status == NO_ERROR || status == ALREADY_EXISTS) {
         Status bs;
         if (isEnabled()) {
-            bs = (*handle)->enable(&status);
+            bs = (*handle)->asIEffect()->enable(&status);
         } else {
-            bs = (*handle)->disable(&status);
+            bs = (*handle)->asIEffect()->disable(&status);
         }
         if (!bs.isOk()) {
             status = statusTFromBinderStatus(bs);
@@ -3379,8 +3415,8 @@
     return status;
 }
 
-void AudioFlinger::DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
-    sp<EffectHandle> effect;
+void DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
+    sp<IAfEffectHandle> effect;
     {
         Mutex::Autolock _l(mProxyLock);
         if (mEffectHandles.find(patchHandle) != mEffectHandles.end()) {
@@ -3391,7 +3427,7 @@
 }
 
 
-size_t AudioFlinger::DeviceEffectProxy::removeEffect(const sp<EffectModule>& effect)
+size_t DeviceEffectProxy::removeEffect(const sp<IAfEffectModule>& effect)
 {
     Mutex::Autolock _l(mProxyLock);
     if (effect == mHalEffect) {
@@ -3402,7 +3438,7 @@
     return mHalEffect == nullptr ? 0 : 1;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::addEffectToHal(
+status_t DeviceEffectProxy::addEffectToHal(
         const sp<EffectHalInterface>& effect) {
     if (mHalEffect == nullptr) {
         return NO_INIT;
@@ -3410,7 +3446,7 @@
     return mManagerCallback->addEffectToHal(&mDevicePort, effect);
 }
 
-status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal(
+status_t DeviceEffectProxy::removeEffectFromHal(
         const sp<EffectHalInterface>& effect) {
     if (mHalEffect == nullptr) {
         return NO_INIT;
@@ -3418,14 +3454,14 @@
     return mManagerCallback->removeEffectFromHal(&mDevicePort, effect);
 }
 
-bool AudioFlinger::DeviceEffectProxy::isOutput() const {
+bool DeviceEffectProxy::isOutput() const {
     if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE) {
         return mDevicePort.role == AUDIO_PORT_ROLE_SINK;
     }
     return true;
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::sampleRate() const {
+uint32_t DeviceEffectProxy::sampleRate() const {
     if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
             (mDevicePort.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) != 0) {
         return mDevicePort.sample_rate;
@@ -3433,7 +3469,7 @@
     return DEFAULT_OUTPUT_SAMPLE_RATE;
 }
 
-audio_channel_mask_t AudioFlinger::DeviceEffectProxy::channelMask() const {
+audio_channel_mask_t DeviceEffectProxy::channelMask() const {
     if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
             (mDevicePort.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) != 0) {
         return mDevicePort.channel_mask;
@@ -3441,20 +3477,20 @@
     return AUDIO_CHANNEL_OUT_STEREO;
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::channelCount() const {
+uint32_t DeviceEffectProxy::channelCount() const {
     if (isOutput()) {
         return audio_channel_count_from_out_mask(channelMask());
     }
     return audio_channel_count_from_in_mask(channelMask());
 }
 
-void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces)
+void DeviceEffectProxy::dump2(int fd, int spaces) const
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     const Vector<String16> args;
     EffectBase::dump(fd, args);
 
-    const bool locked = dumpTryLock(mProxyLock);
+    const bool locked = AudioFlinger::dumpTryLock(mProxyLock);
     if (!locked) {
         String8 result("DeviceEffectProxy may be deadlocked\n");
         write(fd, result.string(), result.size());
@@ -3477,7 +3513,7 @@
         outStr.appendFormat("%*sEffect for patch handle %d:\n", spaces + 2, "", iter.first);
         write(fd, outStr.string(), outStr.size());
         outStr.clear();
-        sp<EffectBase> effect = iter.second->effect().promote();
+        sp<IAfEffectBase> effect = iter.second->effect().promote();
         if (effect != nullptr) {
             effect->dump(fd, args);
         }
@@ -3489,21 +3525,21 @@
 }
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::DeviceEffectProxy::ProxyCallback"
+#define LOG_TAG "DeviceEffectProxy::ProxyCallback"
 
-int AudioFlinger::DeviceEffectProxy::ProxyCallback::newEffectId() {
+int DeviceEffectProxy::ProxyCallback::newEffectId() {
     return mManagerCallback->newEffectId();
 }
 
 
-bool AudioFlinger::DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
-        EffectHandle *handle, bool unpinIfLast) {
-    sp<EffectBase> effectBase = handle->effect().promote();
+bool DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
+        IAfEffectHandle *handle, bool unpinIfLast) {
+    sp<IAfEffectBase> effectBase = handle->effect().promote();
     if (effectBase == nullptr) {
         return false;
     }
 
-    sp<EffectModule> effect = effectBase->asEffectModule();
+    sp<IAfEffectModule> effect = effectBase->asEffectModule();
     if (effect == nullptr) {
         return false;
     }
@@ -3522,13 +3558,13 @@
     return true;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::createEffectHal(
+status_t DeviceEffectProxy::ProxyCallback::createEffectHal(
         const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
         sp<EffectHalInterface> *effect) {
     return mManagerCallback->createEffectHal(pEffectUuid, sessionId, deviceId, effect);
 }
 
-status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::addEffectToHal(
+status_t DeviceEffectProxy::ProxyCallback::addEffectToHal(
         const sp<EffectHalInterface>& effect) {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
@@ -3537,7 +3573,7 @@
     return proxy->addEffectToHal(effect);
 }
 
-status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
+status_t DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
         const sp<EffectHalInterface>& effect) {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
@@ -3546,7 +3582,7 @@
     return proxy->removeEffectFromHal(effect);
 }
 
-bool AudioFlinger::DeviceEffectProxy::ProxyCallback::isOutput() const {
+bool DeviceEffectProxy::ProxyCallback::isOutput() const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return true;
@@ -3554,7 +3590,7 @@
     return proxy->isOutput();
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::sampleRate() const {
+uint32_t DeviceEffectProxy::ProxyCallback::sampleRate() const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return DEFAULT_OUTPUT_SAMPLE_RATE;
@@ -3562,7 +3598,7 @@
     return proxy->sampleRate();
 }
 
-audio_channel_mask_t AudioFlinger::DeviceEffectProxy::ProxyCallback::inChannelMask(
+audio_channel_mask_t DeviceEffectProxy::ProxyCallback::inChannelMask(
         int id __unused) const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
@@ -3571,7 +3607,7 @@
     return proxy->channelMask();
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::inChannelCount(int id __unused) const {
+uint32_t DeviceEffectProxy::ProxyCallback::inChannelCount(int id __unused) const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return 2;
@@ -3579,7 +3615,7 @@
     return proxy->channelCount();
 }
 
-audio_channel_mask_t AudioFlinger::DeviceEffectProxy::ProxyCallback::outChannelMask() const {
+audio_channel_mask_t DeviceEffectProxy::ProxyCallback::outChannelMask() const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return AUDIO_CHANNEL_OUT_STEREO;
@@ -3587,7 +3623,7 @@
     return proxy->channelMask();
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::outChannelCount() const {
+uint32_t DeviceEffectProxy::ProxyCallback::outChannelCount() const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return 2;
@@ -3595,18 +3631,18 @@
     return proxy->channelCount();
 }
 
-void AudioFlinger::DeviceEffectProxy::ProxyCallback::onEffectEnable(
-        const sp<EffectBase>& effectBase) {
-    sp<EffectModule> effect = effectBase->asEffectModule();
+void DeviceEffectProxy::ProxyCallback::onEffectEnable(
+        const sp<IAfEffectBase>& effectBase) {
+    sp<IAfEffectModule> effect = effectBase->asEffectModule();
     if (effect == nullptr) {
         return;
     }
     effect->start();
 }
 
-void AudioFlinger::DeviceEffectProxy::ProxyCallback::onEffectDisable(
-        const sp<EffectBase>& effectBase) {
-    sp<EffectModule> effect = effectBase->asEffectModule();
+void DeviceEffectProxy::ProxyCallback::onEffectDisable(
+        const sp<IAfEffectBase>& effectBase) {
+    sp<IAfEffectModule> effect = effectBase->asEffectModule();
     if (effect == nullptr) {
         return;
     }
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 57acc67..2d8775b 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -15,62 +15,10 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+namespace android {
 
 //--- Audio Effect Management
 
-// Interface implemented by the EffectModule parent or owner (e.g an EffectChain) to abstract
-// interactions between the EffectModule and the reset of the audio framework.
-class EffectCallbackInterface : public RefBase {
-public:
-            ~EffectCallbackInterface() override = default;
-
-    // Trivial methods usually implemented with help from ThreadBase
-    virtual audio_io_handle_t io() const = 0;
-    virtual bool isOutput() const = 0;
-    virtual bool isOffload() const = 0;
-    virtual bool isOffloadOrDirect() const = 0;
-    virtual bool isOffloadOrMmap() const = 0;
-    virtual bool isSpatializer() const = 0;
-    virtual uint32_t sampleRate() const = 0;
-    virtual audio_channel_mask_t inChannelMask(int id) const = 0;
-    virtual uint32_t inChannelCount(int id) const = 0;
-    virtual audio_channel_mask_t outChannelMask() const = 0;
-    virtual uint32_t outChannelCount() const = 0;
-    virtual audio_channel_mask_t hapticChannelMask() const = 0;
-    virtual size_t frameCount() const = 0;
-
-    // Non trivial methods usually implemented with help from ThreadBase:
-    //   pay attention to mutex locking order
-    virtual uint32_t latency() const { return 0; }
-    virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
-    virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
-    virtual void setVolumeForOutput(float left, float right) const = 0;
-    virtual bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) = 0;
-    virtual void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
-                                             bool enabled,
-                                             bool threadLocked) = 0;
-    virtual void onEffectEnable(const sp<EffectBase>& effect) = 0;
-    virtual void onEffectDisable(const sp<EffectBase>& effect) = 0;
-
-    // Methods usually implemented with help from AudioFlinger: pay attention to mutex locking order
-    virtual status_t createEffectHal(const effect_uuid_t *pEffectUuid,
-                    int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) = 0;
-    virtual status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
-    virtual bool updateOrphanEffectChains(const sp<EffectBase>& effect) = 0;
-
-    // Methods usually implemented with help from EffectChain: pay attention to mutex locking order
-    virtual product_strategy_t strategy() const = 0;
-    virtual int32_t activeTrackCnt() const = 0;
-    virtual void resetVolume() = 0;
-
-    virtual wp<EffectChain> chain() const = 0;
-
-    virtual bool isAudioPolicyReady() const = 0;
-};
-
 // EffectBase(EffectModule) and EffectChain classes both have their own mutex to protect
 // state changes or resource modifications. Always respect the following order
 // if multiple mutexes must be acquired to avoid cross deadlock:
@@ -90,7 +38,7 @@
 // The EffectBase class contains common properties, state and behavior for and EffectModule or
 // other derived classes managing an audio effect instance within the effect framework.
 // It also contains the class mutex (see comment on locking order above).
-class EffectBase : public RefBase {
+class EffectBase : public virtual IAfEffectBase {
 public:
     EffectBase(const sp<EffectCallbackInterface>& callback,
                effect_descriptor_t *desc,
@@ -98,76 +46,69 @@
                audio_session_t sessionId,
                bool pinned);
 
-    ~EffectBase() override = default;
-
-    enum effect_state {
-        IDLE,
-        RESTART,
-        STARTING,
-        ACTIVE,
-        STOPPING,
-        STOPPED,
-        DESTROYED
-    };
-
-    int id() const { return mId; }
-    effect_state state() const {
+    int id() const final { return mId; }
+    effect_state state() const final {
         return mState;
     }
-    audio_session_t sessionId() const {
+    audio_session_t sessionId() const final {
         return mSessionId;
     }
-    const effect_descriptor_t& desc() const { return mDescriptor; }
-    bool             isOffloadable() const
+    const effect_descriptor_t& desc() const final { return mDescriptor; }
+    bool isOffloadable() const final
                         { return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; }
-    bool             isImplementationSoftware() const
+    bool isImplementationSoftware() const final
                         { return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; }
-    bool             isProcessImplemented() const
+    bool isProcessImplemented() const final
                         { return (mDescriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0; }
-    bool             isVolumeControl() const
+    bool isVolumeControl() const
                         { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK)
                             == EFFECT_FLAG_VOLUME_CTRL; }
-    bool             isVolumeMonitor() const
+    bool isVolumeMonitor() const final
                         { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK)
                             == EFFECT_FLAG_VOLUME_MONITOR; }
 
-    virtual status_t setEnabled(bool enabled, bool fromHandle);
-    status_t    setEnabled_l(bool enabled);
-    bool isEnabled() const;
+    status_t setEnabled(bool enabled, bool fromHandle) override;
+    status_t setEnabled_l(bool enabled) final;
+    bool isEnabled() const final;
+    void setSuspended(bool suspended) final;
+    bool suspended() const final;
 
-    void             setSuspended(bool suspended);
-    bool             suspended() const;
-
-    virtual status_t command(int32_t __unused,
+    status_t command(int32_t __unused,
                              const std::vector<uint8_t>& __unused,
                              int32_t __unused,
-                             std::vector<uint8_t>* __unused) { return NO_ERROR; };
+                             std::vector<uint8_t>* __unused) override {
+        return NO_ERROR;
+    }
 
     // mCallback is atomic so this can be lock-free.
-    void setCallback(const sp<EffectCallbackInterface>& callback) { mCallback = callback; }
-    sp<EffectCallbackInterface> getCallback() const { return mCallback.load(); }
+    void setCallback(const sp<EffectCallbackInterface>& callback) final {
+        mCallback = callback;
+    }
+    sp<EffectCallbackInterface> getCallback() const final {
+        return mCallback.load();
+    }
 
-    status_t addHandle(EffectHandle *handle);
-    ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast);
-    ssize_t removeHandle(EffectHandle *handle);
-    ssize_t removeHandle_l(EffectHandle *handle);
-    EffectHandle* controlHandle_l();
-    bool purgeHandles();
+    status_t addHandle(IAfEffectHandle *handle) final;
+    ssize_t disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast) final;
+    ssize_t removeHandle(IAfEffectHandle *handle) final;
+    ssize_t removeHandle_l(IAfEffectHandle *handle) final;
+    IAfEffectHandle* controlHandle_l() final;
+    bool purgeHandles() final;
 
-    void             checkSuspendOnEffectEnabled(bool enabled, bool threadLocked);
+    void             checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) final;
 
-    bool             isPinned() const { return mPinned; }
-    void             unPin() { mPinned = false; }
+    bool             isPinned() const final { return mPinned; }
+    void             unPin() final { mPinned = false; }
 
-    void             lock() ACQUIRE(mLock) { mLock.lock(); }
-    void             unlock() RELEASE(mLock) { mLock.unlock(); }
+    void             lock() ACQUIRE(mLock) final { mLock.lock(); }
+    void             unlock() RELEASE(mLock) final { mLock.unlock(); }
 
-    status_t         updatePolicyState();
+    status_t         updatePolicyState() final;
 
-    virtual          sp<EffectModule> asEffectModule() { return nullptr; }
-    virtual          sp<DeviceEffectProxy> asDeviceEffectProxy() { return nullptr; }
+    sp<IAfEffectModule> asEffectModule() override { return nullptr; }
+    sp<IAfDeviceEffectProxy> asDeviceEffectProxy() override { return nullptr; }
 
-    void             dump(int fd, const Vector<String16>& args);
+    void             dump(int fd, const Vector<String16>& args) const override;
 
 protected:
     bool             isInternal_l() const {
@@ -179,13 +120,11 @@
                          return true;
                      }
 
-private:
-    friend class AudioFlinger;      // for mHandles
     bool             mPinned = false;
 
     DISALLOW_COPY_AND_ASSIGN(EffectBase);
 
-mutable Mutex                 mLock;      // mutex for process, commands and handles list protection
+    mutable Mutex mLock;      // mutex for process, commands and handles list protection
     mediautils::atomic_sp<EffectCallbackInterface> mCallback; // parent effect chain
     const int                 mId;        // this instance unique ID
     const audio_session_t     mSessionId; // audio session ID
@@ -194,7 +133,7 @@
     // effect is suspended: temporarily disabled by framework
     bool                      mSuspended = false;
 
-    Vector<EffectHandle *>    mHandles;   // list of client handles
+    Vector<IAfEffectHandle *> mHandles;  // list of client handles
                 // First handle in mHandles has highest priority and controls the effect module
 
     // Audio policy effect state management
@@ -217,7 +156,7 @@
 // ramping when effects are activated/deactivated.
 // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by
 // the attached track(s) to accumulate their auxiliary channel.
-class EffectModule : public EffectBase {
+class EffectModule : public IAfEffectModule, public EffectBase {
 public:
     EffectModule(const sp<EffectCallbackInterface>& callabck,
                     effect_descriptor_t *desc,
@@ -225,72 +164,65 @@
                     audio_session_t sessionId,
                     bool pinned,
                     audio_port_handle_t deviceId);
-    virtual ~EffectModule();
+    ~EffectModule() override;
 
-    void process();
-    bool updateState();
+    void process() final;
+    bool updateState() final;
     status_t command(int32_t cmdCode,
                      const std::vector<uint8_t>& cmdData,
                      int32_t maxReplySize,
-                     std::vector<uint8_t>* reply) override;
+                     std::vector<uint8_t>* reply) final;
 
-    void reset_l();
-    status_t configure();
-    status_t init();
-
-    uint32_t status() {
+    void reset_l() final;
+    status_t configure() final;
+    status_t init() final;
+    uint32_t status() const final {
         return mStatus;
     }
-
-    bool isProcessEnabled() const;
-    bool isOffloadedOrDirect() const;
-    bool isVolumeControlEnabled() const;
-
-    void        setInBuffer(const sp<EffectBufferHalInterface>& buffer);
-    int16_t     *inBuffer() const {
+    bool isProcessEnabled() const final;
+    bool isOffloadedOrDirect() const final;
+    bool isVolumeControlEnabled() const final;
+    void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final;
+    int16_t *inBuffer() const final {
         return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL;
     }
-    void        setOutBuffer(const sp<EffectBufferHalInterface>& buffer);
-    int16_t     *outBuffer() const {
+    void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) final;
+    int16_t *outBuffer() const final {
         return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
     }
-
     // Updates the access mode if it is out of date.  May issue a new effect configure.
-    void        updateAccessMode() {
+    void updateAccessMode() final {
                     if (requiredEffectBufferAccessMode() != mConfig.outputCfg.accessMode) {
                         configure();
                     }
                 }
+    status_t setDevices(const AudioDeviceTypeAddrVector &devices) final;
+    status_t setInputDevice(const AudioDeviceTypeAddr &device) final;
+    status_t setVolume(uint32_t *left, uint32_t *right, bool controller) final;
+    status_t setMode(audio_mode_t mode) final;
+    status_t setAudioSource(audio_source_t source) final;
+    status_t start() final;
+    status_t stop() final;
 
-    status_t         setDevices(const AudioDeviceTypeAddrVector &devices);
-    status_t         setInputDevice(const AudioDeviceTypeAddr &device);
-    status_t         setVolume(uint32_t *left, uint32_t *right, bool controller);
-    status_t         setMode(audio_mode_t mode);
-    status_t         setAudioSource(audio_source_t source);
-    status_t         start();
-    status_t         stop();
+    status_t setOffloaded(bool offloaded, audio_io_handle_t io) final;
+    bool isOffloaded() const final;
+    void addEffectToHal_l() final;
+    void release_l() final;
 
-    status_t         setOffloaded(bool offloaded, audio_io_handle_t io);
-    bool             isOffloaded() const;
-    void             addEffectToHal_l();
-    void             release_l();
+    sp<IAfEffectModule> asEffectModule() final { return this; }
 
-    sp<EffectModule> asEffectModule() override { return this; }
+    bool isHapticGenerator() const final;
 
-    static bool      isHapticGenerator(const effect_uuid_t* type);
-    bool             isHapticGenerator() const;
+    status_t setHapticIntensity(int id, os::HapticScale intensity) final;
+    status_t setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo) final;
 
-    status_t         setHapticIntensity(int id, os::HapticScale intensity);
-    status_t         setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo);
-
-    status_t         getConfigs(audio_config_base_t* inputCfg,
+    status_t getConfigs(audio_config_base_t* inputCfg,
                                 audio_config_base_t* outputCfg,
-                                bool* isOutput) const;
+                                bool* isOutput) const final;
 
-    void             dump(int fd, const Vector<String16>& args);
+    void dump(int fd, const Vector<String16>& args) const final;
 
 private:
-    friend class AudioFlinger;      // for mHandles
 
     // Maximum time allocated to effect engines to complete the turn off sequence
     static const uint32_t MAX_DISABLE_TIME_MS = 10000;
@@ -354,32 +286,37 @@
 // There is one EffectHandle object for each application controlling (or using)
 // an effect module.
 // The EffectHandle is obtained by calling AudioFlinger::createEffect().
-class EffectHandle: public android::media::BnEffect {
+class EffectHandle: public IAfEffectHandle, public android::media::BnEffect {
 public:
 
-    EffectHandle(const sp<EffectBase>& effect,
+    EffectHandle(const sp<IAfEffectBase>& effect,
             const sp<AudioFlinger::Client>& client,
             const sp<media::IEffectClient>& effectClient,
             int32_t priority, bool notifyFramesProcessed);
-    virtual ~EffectHandle();
+    ~EffectHandle() override;
     status_t onTransact(
-            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
-    virtual status_t initCheck();
+            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) final;
+    status_t initCheck() const final;
 
     // IEffect
-    android::binder::Status enable(int32_t* _aidl_return) override;
-    android::binder::Status disable(int32_t* _aidl_return) override;
+    android::binder::Status enable(int32_t* _aidl_return) final;
+    android::binder::Status disable(int32_t* _aidl_return) final;
     android::binder::Status command(int32_t cmdCode,
                                     const std::vector<uint8_t>& cmdData,
                                     int32_t maxResponseSize,
                                     std::vector<uint8_t>* response,
-                                    int32_t* _aidl_return) override;
-    android::binder::Status disconnect() override;
-    android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) override;
+                                    int32_t* _aidl_return) final;
+    android::binder::Status disconnect() final;
+    android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) final;
     android::binder::Status getConfig(media::EffectConfig* _config,
-                                      int32_t* _aidl_return) override;
+                                      int32_t* _aidl_return) final;
 
-    sp<Client> client() const { return mClient; }
+    // TODO(b/288339104) type
+    sp<RefBase /* AudioFlinger::Client */> client() const final { return mClient; }
+
+    sp<android::media::IEffect> asIEffect() final {
+        return sp<android::media::IEffect>::fromExisting(this);
+    }
 
 private:
     void disconnect(bool unpinIfLast);
@@ -388,38 +325,39 @@
     // - hasControl: true if control is given, false if removed
     // - signal: true client app should be signaled of change, false otherwise
     // - enabled: state of the effect when control is passed
-    void setControl(bool hasControl, bool signal, bool enabled);
+    void setControl(bool hasControl, bool signal, bool enabled) final;
     void commandExecuted(uint32_t cmdCode,
                          const std::vector<uint8_t>& cmdData,
-                         const std::vector<uint8_t>& replyData);
-    void setEnabled(bool enabled);
-    bool enabled() const { return mEnabled; }
+                         const std::vector<uint8_t>& replyData) final;
+    bool enabled() const final { return mEnabled; }
+    void setEnabled(bool enabled) final;
+    void framesProcessed(int32_t frames) const final;
 
-    void framesProcessed(int32_t frames) const;
-
+public:
     // Getters
-    wp<EffectBase> effect() const { return mEffect; }
-    int id() const {
-        sp<EffectBase> effect = mEffect.promote();
+    wp<IAfEffectBase> effect() const final { return mEffect; }
+    int id() const final {
+        sp<IAfEffectBase> effect = mEffect.promote();
         if (effect == 0) {
             return 0;
         }
         return effect->id();
     }
-    int priority() const { return mPriority; }
-    bool hasControl() const { return mHasControl; }
-    bool disconnected() const { return mDisconnected; }
+private:
+    int priority() const final { return mPriority; }
+    bool hasControl() const final { return mHasControl; }
+    bool disconnected() const final { return mDisconnected; }
 
-    void dumpToBuffer(char* buffer, size_t size);
+    void dumpToBuffer(char* buffer, size_t size) const final;
+
 
 private:
-    friend class AudioFlinger;          // for mEffect, mHasControl, mEnabled
     DISALLOW_COPY_AND_ASSIGN(EffectHandle);
 
     Mutex mLock;                             // protects IEffect method calls
-    const wp<EffectBase> mEffect;            // pointer to controlled EffectModule
+    const wp<IAfEffectBase> mEffect;               // pointer to controlled EffectModule
     const sp<media::IEffectClient> mEffectClient;  // callback interface for client notifications
-    /*const*/ sp<Client> mClient;            // client for shared memory allocation, see
+    /*const*/ sp<AudioFlinger::Client> mClient;    // client for shared memory allocation, see
                                              //   disconnect()
     sp<IMemory> mCblkMemory;                 // shared memory for control block
     effect_param_cblk_t* mCblk;              // control block for deferred parameter setting via
@@ -443,123 +381,139 @@
 // order corresponding in the effect process order. When attached to a track (session ID !=
 // AUDIO_SESSION_OUTPUT_MIX),
 // it also provide it's own input buffer used by the track as accumulation buffer.
-class EffectChain : public RefBase {
+class EffectChain : public IAfEffectChain {
 public:
-    EffectChain(const wp<ThreadBase>& wThread, audio_session_t sessionId);
-    virtual ~EffectChain();
+    EffectChain(const wp<AudioFlinger::ThreadBase>& wThread, audio_session_t sessionId);
+    ~EffectChain() override;
 
-    // special key used for an entry in mSuspendedEffects keyed vector
-    // corresponding to a suspend all request.
-    static const int        kKeyForSuspendAll = 0;
+    void process_l() final;
 
-    // minimum duration during which we force calling effect process when last track on
-    // a session is stopped or removed to allow effect tail to be rendered
-    static const int        kProcessTailDurationMs = 1000;
-
-    void process_l();
-
-    void lock() ACQUIRE(mLock) {
+    void lock() ACQUIRE(mLock) final {
         mLock.lock();
     }
-    void unlock() RELEASE(mLock) {
+    void unlock() RELEASE(mLock) final {
         mLock.unlock();
     }
-
-    status_t createEffect_l(sp<EffectModule>& effect,
+    status_t createEffect_l(sp<IAfEffectModule>& effect,
                             effect_descriptor_t *desc,
                             int id,
                             audio_session_t sessionId,
-                            bool pinned);
-    status_t addEffect_l(const sp<EffectModule>& handle);
-    status_t addEffect_ll(const sp<EffectModule>& handle);
-    size_t removeEffect_l(const sp<EffectModule>& handle, bool release = false);
+                            bool pinned) final;
+    status_t addEffect_l(const sp<IAfEffectModule>& handle) final;
+    status_t addEffect_ll(const sp<IAfEffectModule>& handle) final;
+    size_t removeEffect_l(const sp<IAfEffectModule>& handle, bool release = false) final;
 
-    audio_session_t sessionId() const { return mSessionId; }
-    void setSessionId(audio_session_t sessionId) { mSessionId = sessionId; }
+    audio_session_t sessionId() const final { return mSessionId; }
+    void setSessionId(audio_session_t sessionId) final { mSessionId = sessionId; }
 
-    sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
-    sp<EffectModule> getEffectFromId_l(int id);
-    sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type);
-    std::vector<int> getEffectIds();
+    sp<IAfEffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor) const final;
+    sp<IAfEffectModule> getEffectFromId_l(int id) const final;
+    sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t *type) const final;
+    std::vector<int> getEffectIds() const final;
     // FIXME use float to improve the dynamic range
-    bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false);
-    void resetVolume_l();
-    void setDevices_l(const AudioDeviceTypeAddrVector &devices);
-    void setInputDevice_l(const AudioDeviceTypeAddr &device);
-    void setMode_l(audio_mode_t mode);
-    void setAudioSource_l(audio_source_t source);
 
-    void setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+    bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false) final;
+    void resetVolume_l() final;
+    void setDevices_l(const AudioDeviceTypeAddrVector &devices) final;
+    void setInputDevice_l(const AudioDeviceTypeAddr &device) final;
+    void setMode_l(audio_mode_t mode) final;
+    void setAudioSource_l(audio_source_t source) final;
+
+    void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final {
         mInBuffer = buffer;
     }
-    float *inBuffer() const {
+    float *inBuffer() const final {
         return mInBuffer != 0 ? reinterpret_cast<float*>(mInBuffer->ptr()) : NULL;
     }
-    void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+    void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) final {
         mOutBuffer = buffer;
     }
-    float *outBuffer() const {
+    float *outBuffer() const final {
         return mOutBuffer != 0 ? reinterpret_cast<float*>(mOutBuffer->ptr()) : NULL;
     }
+    void incTrackCnt() final { android_atomic_inc(&mTrackCnt); }
+    void decTrackCnt() final { android_atomic_dec(&mTrackCnt); }
+    int32_t trackCnt() const final { return android_atomic_acquire_load(&mTrackCnt); }
 
-    void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
-    void decTrackCnt() { android_atomic_dec(&mTrackCnt); }
-    int32_t trackCnt() const { return android_atomic_acquire_load(&mTrackCnt); }
-
-    void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt);
+    void incActiveTrackCnt() final { android_atomic_inc(&mActiveTrackCnt);
                                mTailBufferCount = mMaxTailBuffers; }
-    void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); }
-    int32_t activeTrackCnt() const { return android_atomic_acquire_load(&mActiveTrackCnt); }
+    void decActiveTrackCnt() final { android_atomic_dec(&mActiveTrackCnt); }
+    int32_t activeTrackCnt() const final {
+        return android_atomic_acquire_load(&mActiveTrackCnt);
+    }
 
-    product_strategy_t strategy() const { return mStrategy; }
-    void setStrategy(product_strategy_t strategy)
+    product_strategy_t strategy() const final { return mStrategy; }
+    void setStrategy(product_strategy_t strategy) final
             { mStrategy = strategy; }
 
     // suspend or restore effects of the specified type. The number of suspend requests is counted
     // and restore occurs once all suspend requests are cancelled.
     void setEffectSuspended_l(const effect_uuid_t *type,
-                              bool suspend);
+                              bool suspend) final;
     // suspend all eligible effects
-    void setEffectSuspendedAll_l(bool suspend);
+    void setEffectSuspendedAll_l(bool suspend) final;
     // check if effects should be suspended or restored when a given effect is enable or disabled
-    void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, bool enabled);
+    void checkSuspendOnEffectEnabled(
+            const sp<IAfEffectModule>& effect, bool enabled) final;
 
-    void clearInputBuffer();
+    void clearInputBuffer() final;
 
     // At least one non offloadable effect in the chain is enabled
-    bool isNonOffloadableEnabled();
-    bool isNonOffloadableEnabled_l();
+    bool isNonOffloadableEnabled() const final;
+    bool isNonOffloadableEnabled_l() const final;
 
-    void syncHalEffectsState();
+    void syncHalEffectsState() final;
 
     // flags is an ORed set of audio_output_flags_t which is updated on return.
-    void checkOutputFlagCompatibility(audio_output_flags_t *flags) const;
+    void checkOutputFlagCompatibility(audio_output_flags_t *flags) const final;
 
     // flags is an ORed set of audio_input_flags_t which is updated on return.
-    void checkInputFlagCompatibility(audio_input_flags_t *flags) const;
+    void checkInputFlagCompatibility(audio_input_flags_t *flags) const final;
 
     // Is this EffectChain compatible with the RAW audio flag.
-    bool isRawCompatible() const;
+    bool isRawCompatible() const final;
 
     // Is this EffectChain compatible with the FAST audio flag.
-    bool isFastCompatible() const;
+    bool isFastCompatible() const final;
 
     // Is this EffectChain compatible with the bit-perfect audio flag.
-    bool isBitPerfectCompatible() const;
+    bool isBitPerfectCompatible() const final;
 
     // isCompatibleWithThread_l() must be called with thread->mLock held
-    bool isCompatibleWithThread_l(const sp<ThreadBase>& thread) const;
+    // TODO(b/288339104) type
+    bool isCompatibleWithThread_l(const sp<Thread>& thread) const final {
+        return isCompatibleWithThread_l(sp<AudioFlinger::ThreadBase>::cast(thread));
+    }
 
-    bool containsHapticGeneratingEffect_l();
+    bool isCompatibleWithThread_l(const sp<AudioFlinger::ThreadBase>& thread) const;
 
-    void setHapticIntensity_l(int id, os::HapticScale intensity);
+    bool containsHapticGeneratingEffect_l() final;
 
-    sp<EffectCallbackInterface> effectCallback() const { return mEffectCallback; }
-    wp<ThreadBase> thread() const { return mEffectCallback->thread(); }
+    void setHapticIntensity_l(int id, os::HapticScale intensity) final;
 
-    bool isFirstEffect(int id) const { return !mEffects.isEmpty() && id == mEffects[0]->id(); }
+    sp<EffectCallbackInterface> effectCallback() const final { return mEffectCallback; }
 
-    void dump(int fd, const Vector<String16>& args);
+    // TODO(b/288339104) type
+    wp<Thread> thread() const final { return mEffectCallback->thread(); }
+
+    bool isFirstEffect(int id) const final {
+        return !mEffects.isEmpty() && id == mEffects[0]->id();
+    }
+
+    void dump(int fd, const Vector<String16>& args) const final;
+
+    size_t numberOfEffects() const final { return mEffects.size(); }
+
+    sp<IAfEffectModule> getEffectModule(size_t index) const final {
+        return mEffects[index];
+    }
+
+    // TODO(b/288339104) type
+    void setThread(const sp<Thread>& thread) final {
+        setThread(sp<AudioFlinger::ThreadBase>::cast(thread));
+    }
+
+    void setThread(const sp<AudioFlinger::ThreadBase>& thread);
 
 private:
 
@@ -574,22 +528,22 @@
         // Note: ctors taking a weak pointer to their owner must not promote it
         // during construction (but may keep a reference for later promotion).
         EffectCallback(const wp<EffectChain>& owner,
-                       const wp<ThreadBase>& thread)
+                       const wp<AudioFlinger::ThreadBase>& thread)
             : mChain(owner)
             , mThread(thread)
-            , mAudioFlinger(*gAudioFlinger) {
-            sp<ThreadBase> base = thread.promote();
+            , mAudioFlinger(*AudioFlinger::gAudioFlinger) {
+            sp<AudioFlinger::ThreadBase> base = thread.promote();
             if (base != nullptr) {
                 mThreadType = base->type();
             } else {
-                mThreadType = ThreadBase::MIXER;  // assure a consistent value.
+                mThreadType = AudioFlinger::ThreadBase::MIXER;  // assure a consistent value.
             }
         }
 
         status_t createEffectHal(const effect_uuid_t *pEffectUuid,
                int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
         status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
-        bool updateOrphanEffectChains(const sp<EffectBase>& effect) override;
+        bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect) override;
 
         audio_io_handle_t io() const override;
         bool isOutput() const override;
@@ -609,39 +563,38 @@
 
         status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
         status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
-        bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+        bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override;
         void setVolumeForOutput(float left, float right) const override;
 
         // check if effects should be suspended/restored when a given effect is enable/disabled
-        void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
+        void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect,
                               bool enabled, bool threadLocked) override;
         void resetVolume() override;
         product_strategy_t strategy() const override;
         int32_t activeTrackCnt() const override;
-        void onEffectEnable(const sp<EffectBase>& effect) override;
-        void onEffectDisable(const sp<EffectBase>& effect) override;
+        void onEffectEnable(const sp<IAfEffectBase>& effect) override;
+        void onEffectDisable(const sp<IAfEffectBase>& effect) override;
 
-        wp<EffectChain> chain() const override { return mChain; }
+        wp<IAfEffectChain> chain() const final { return mChain; }
 
-        bool isAudioPolicyReady() const override {
+        bool isAudioPolicyReady() const final {
             return mAudioFlinger.isAudioPolicyReady();
         }
 
-        wp<ThreadBase> thread() const { return mThread.load(); }
+        wp<AudioFlinger::ThreadBase> thread() const { return mThread.load(); }
 
-        void setThread(const sp<ThreadBase>& thread) {
+        void setThread(const sp<AudioFlinger::ThreadBase>& thread) {
             mThread = thread;
             mThreadType = thread->type();
         }
 
     private:
-        const wp<EffectChain> mChain;
-        mediautils::atomic_wp<ThreadBase> mThread;
+        const wp<IAfEffectChain> mChain;
+        mediautils::atomic_wp<AudioFlinger::ThreadBase> mThread;
         AudioFlinger &mAudioFlinger;  // implementation detail: outer instance always exists.
-        ThreadBase::type_t mThreadType;
+        AudioFlinger::ThreadBase::type_t mThreadType;
     };
 
-    friend class AudioFlinger;  // for mThread, mEffects
     DISALLOW_COPY_AND_ASSIGN(EffectChain);
 
     class SuspendedEffectDesc : public RefBase {
@@ -650,15 +603,15 @@
 
         int mRefCount;   // > 0 when suspended
         effect_uuid_t mType;
-        wp<EffectModule> mEffect;
+        wp<IAfEffectModule> mEffect;
     };
 
     // get a list of effect modules to suspend when an effect of the type
     // passed is enabled.
-    void                       getSuspendEligibleEffects(Vector< sp<EffectModule> > &effects);
+    void  getSuspendEligibleEffects(Vector<sp<IAfEffectModule>> &effects);
 
     // get an effect module if it is currently enable
-    sp<EffectModule> getEffectIfEnabled(const effect_uuid_t *type);
+    sp<IAfEffectModule> getEffectIfEnabled(const effect_uuid_t *type);
     // true if the effect whose descriptor is passed can be suspended
     // OEMs can modify the rules implemented in this method to exclude specific effect
     // types or implementations from the suspend/restore mechanism.
@@ -668,8 +621,6 @@
 
     void clearInputBuffer_l();
 
-    void setThread(const sp<ThreadBase>& thread);
-
     // true if any effect module within the chain has volume control
     bool hasVolumeControlEnabled_l() const;
 
@@ -678,7 +629,7 @@
     ssize_t getInsertIndex(const effect_descriptor_t& desc);
 
     mutable  Mutex mLock;        // mutex protecting effect list
-             Vector< sp<EffectModule> > mEffects; // list of effect modules
+             Vector<sp<IAfEffectModule>> mEffects; // list of effect modules
              audio_session_t mSessionId; // audio session ID
              sp<EffectBufferHalInterface> mInBuffer;  // chain input buffer
              sp<EffectBufferHalInterface> mOutBuffer; // chain output buffer
@@ -704,35 +655,50 @@
              const sp<EffectCallback> mEffectCallback;
 };
 
-class DeviceEffectProxy : public EffectBase {
+class DeviceEffectProxy : public IAfDeviceEffectProxy, public EffectBase {
 public:
-        DeviceEffectProxy (const AudioDeviceTypeAddr& device,
-                const sp<DeviceEffectManagerCallback>& callback,
+    DeviceEffectProxy(const AudioDeviceTypeAddr& device,
+                const sp<AudioFlinger::DeviceEffectManagerCallback>& callback,
                 effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
             : EffectBase(callback, desc, id, AUDIO_SESSION_DEVICE, false),
                 mDevice(device), mManagerCallback(callback),
                 mMyCallback(new ProxyCallback(wp<DeviceEffectProxy>(this), callback)),
                 mNotifyFramesProcessed(notifyFramesProcessed) {}
 
-    status_t setEnabled(bool enabled, bool fromHandle) override;
-    sp<DeviceEffectProxy> asDeviceEffectProxy() override { return this; }
+    status_t setEnabled(bool enabled, bool fromHandle) final;
+    sp<IAfDeviceEffectProxy> asDeviceEffectProxy() final { return this; }
 
-    status_t init(const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches);
-    status_t onCreatePatch(audio_patch_handle_t patchHandle, const PatchPanel::Patch& patch);
-    void onReleasePatch(audio_patch_handle_t patchHandle);
+    // TODO(b/288339104) type
+    status_t init(const /* std::map<audio_patch_handle_t,
+            PatchPanel::Patch>& */ void * patches) final {
+        return init(*reinterpret_cast<const std::map<
+                audio_patch_handle_t, AudioFlinger::PatchPanel::Patch> *>(patches));
+    }
+    // TODO(b/288339104) type
+    status_t onCreatePatch(audio_patch_handle_t patchHandle,
+            /* const PatchPanel::Patch& */ const void * patch) final {
+        return onCreatePatch(patchHandle,
+                *reinterpret_cast<const AudioFlinger::PatchPanel::Patch *>(patch));
+    }
 
-    size_t removeEffect(const sp<EffectModule>& effect);
+    status_t init(const std::map<audio_patch_handle_t, AudioFlinger::PatchPanel::Patch>& patches);
+    status_t onCreatePatch(
+            audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch);
 
-    status_t addEffectToHal(const sp<EffectHalInterface>& effect);
-    status_t removeEffectFromHal(const sp<EffectHalInterface>& effect);
+    void onReleasePatch(audio_patch_handle_t patchHandle) final;
 
-    const AudioDeviceTypeAddr& device() { return mDevice; };
-    bool isOutput() const;
-    uint32_t sampleRate() const;
-    audio_channel_mask_t channelMask() const;
-    uint32_t channelCount() const;
+    size_t removeEffect(const sp<IAfEffectModule>& effect) final;
 
-    void dump(int fd, int spaces);
+    status_t addEffectToHal(const sp<EffectHalInterface>& effect) final;
+    status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) final;
+
+    const AudioDeviceTypeAddr& device() const final { return mDevice; };
+    bool isOutput() const final;
+    uint32_t sampleRate() const final;
+    audio_channel_mask_t channelMask() const final;
+    uint32_t channelCount() const final;
+
+    void dump2(int fd, int spaces) const final;
 
 private:
 
@@ -741,14 +707,14 @@
         // Note: ctors taking a weak pointer to their owner must not promote it
         // during construction (but may keep a reference for later promotion).
         ProxyCallback(const wp<DeviceEffectProxy>& owner,
-                const sp<DeviceEffectManagerCallback>& callback)
+                const sp<AudioFlinger::DeviceEffectManagerCallback>& callback)
             : mProxy(owner), mManagerCallback(callback) {}
 
         status_t createEffectHal(const effect_uuid_t *pEffectUuid,
                int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
         status_t allocateHalBuffer(size_t size __unused,
                 sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; }
-        bool updateOrphanEffectChains(const sp<EffectBase>& effect __unused) override {
+        bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect __unused) override {
                     return false;
         }
 
@@ -771,18 +737,18 @@
         status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
         status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
 
-        bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+        bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override;
         void setVolumeForOutput(float left __unused, float right __unused) const override {}
 
-        void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect __unused,
+        void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect __unused,
                               bool enabled __unused, bool threadLocked __unused) override {}
         void resetVolume() override {}
         product_strategy_t strategy() const override  { return static_cast<product_strategy_t>(0); }
         int32_t activeTrackCnt() const override { return 0; }
-        void onEffectEnable(const sp<EffectBase>& effect __unused) override;
-        void onEffectDisable(const sp<EffectBase>& effect __unused) override;
+        void onEffectEnable(const sp<IAfEffectBase>& effect __unused) override;
+        void onEffectDisable(const sp<IAfEffectBase>& effect __unused) override;
 
-        wp<EffectChain> chain() const override { return nullptr; }
+        wp<IAfEffectChain> chain() const override { return nullptr; }
 
         bool isAudioPolicyReady() const override {
             return mManagerCallback->isAudioPolicyReady();
@@ -792,19 +758,21 @@
 
     private:
         const wp<DeviceEffectProxy> mProxy;
-        const sp<DeviceEffectManagerCallback> mManagerCallback;
+        const sp<AudioFlinger::DeviceEffectManagerCallback> mManagerCallback;
     };
 
-    status_t checkPort(const PatchPanel::Patch& patch, const struct audio_port_config *port,
-            sp<EffectHandle> *handle);
+    status_t checkPort(const AudioFlinger::PatchPanel::Patch& patch,
+            const struct audio_port_config *port, sp<IAfEffectHandle> *handle);
 
     const AudioDeviceTypeAddr mDevice;
-    const sp<DeviceEffectManagerCallback> mManagerCallback;
+    const sp<AudioFlinger::DeviceEffectManagerCallback> mManagerCallback;
     const sp<ProxyCallback> mMyCallback;
 
-    Mutex mProxyLock;
-    std::map<audio_patch_handle_t, sp<EffectHandle>> mEffectHandles; // protected by mProxyLock
-    sp<EffectModule> mHalEffect; // protected by mProxyLock
+    mutable Mutex mProxyLock;
+    std::map<audio_patch_handle_t, sp<IAfEffectHandle>> mEffectHandles; // protected by mProxyLock
+    sp<IAfEffectModule> mHalEffect; // protected by mProxyLock
     struct audio_port_config mDevicePort = { .id = AUDIO_PORT_HANDLE_NONE };
     const bool mNotifyFramesProcessed;
 };
+
+} // namespace android
diff --git a/services/audioflinger/IAfEffect.h b/services/audioflinger/IAfEffect.h
new file mode 100644
index 0000000..7c3be0f
--- /dev/null
+++ b/services/audioflinger/IAfEffect.h
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+namespace android {
+
+class IAfDeviceEffectProxy;
+class IAfEffectBase;
+class IAfEffectChain;
+class IAfEffectHandle;
+class IAfEffectModule;
+
+// Interface implemented by the EffectModule parent or owner (e.g an EffectChain) to abstract
+// interactions between the EffectModule and the reset of the audio framework.
+class EffectCallbackInterface : public RefBase {
+public:
+    // Trivial methods usually implemented with help from ThreadBase
+    virtual audio_io_handle_t io() const = 0;
+    virtual bool isOutput() const = 0;
+    virtual bool isOffload() const = 0;
+    virtual bool isOffloadOrDirect() const = 0;
+    virtual bool isOffloadOrMmap() const = 0;
+    virtual bool isSpatializer() const = 0;
+    virtual uint32_t sampleRate() const = 0;
+    virtual audio_channel_mask_t inChannelMask(int id) const = 0;
+    virtual uint32_t inChannelCount(int id) const = 0;
+    virtual audio_channel_mask_t outChannelMask() const = 0;
+    virtual uint32_t outChannelCount() const = 0;
+    virtual audio_channel_mask_t hapticChannelMask() const = 0;
+    virtual size_t frameCount() const = 0;
+
+    // Non trivial methods usually implemented with help from ThreadBase:
+    // pay attention to mutex locking order
+    virtual uint32_t latency() const { return 0; }
+    virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
+    virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
+    virtual void setVolumeForOutput(float left, float right) const = 0;
+    virtual bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) = 0;
+    virtual void checkSuspendOnEffectEnabled(
+            const sp<IAfEffectBase>& effect, bool enabled, bool threadLocked) = 0;
+    virtual void onEffectEnable(const sp<IAfEffectBase>& effect) = 0;
+    virtual void onEffectDisable(const sp<IAfEffectBase>& effect) = 0;
+
+    // Methods usually implemented with help from AudioFlinger: pay attention to mutex locking order
+    virtual status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+            int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) = 0;
+    virtual status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
+    virtual bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect) = 0;
+
+    // Methods usually implemented with help from EffectChain: pay attention to mutex locking order
+    virtual product_strategy_t strategy() const = 0;
+    virtual int32_t activeTrackCnt() const = 0;
+    virtual void resetVolume() = 0;
+    virtual wp<IAfEffectChain> chain() const = 0;
+    virtual bool isAudioPolicyReady() const = 0;
+};
+
+class IAfEffectBase : public virtual RefBase {
+    friend class EffectChain;
+    friend class EffectHandle;
+
+public:
+    enum effect_state {
+        IDLE,
+        RESTART,
+        STARTING,
+        ACTIVE,
+        STOPPING,
+        STOPPED,
+        DESTROYED
+    };
+    virtual int id() const = 0;
+    virtual effect_state state() const = 0;
+    virtual audio_session_t sessionId() const = 0;
+    virtual const effect_descriptor_t& desc() const = 0;
+    virtual bool isOffloadable() const = 0;
+    virtual bool isImplementationSoftware() const = 0;
+    virtual bool isProcessImplemented() const = 0;
+    virtual bool isVolumeControl() const = 0;
+    virtual bool isVolumeMonitor() const = 0;
+    virtual bool isEnabled() const = 0;
+    virtual bool isPinned() const = 0;
+    virtual void unPin() = 0;
+    virtual status_t updatePolicyState() = 0;
+    virtual bool purgeHandles() = 0;
+    virtual void checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) = 0;
+
+    // mCallback is atomic so this can be lock-free.
+    virtual void setCallback(const sp<EffectCallbackInterface>& callback) = 0;
+    virtual sp<EffectCallbackInterface> getCallback() const = 0;
+
+    virtual status_t addHandle(IAfEffectHandle *handle) = 0;
+    virtual ssize_t removeHandle(IAfEffectHandle *handle) = 0;
+
+    virtual sp<IAfEffectModule> asEffectModule() = 0;
+    virtual sp<IAfDeviceEffectProxy> asDeviceEffectProxy() = 0;
+
+    virtual void dump(int fd, const Vector<String16>& args) const = 0;
+
+private:
+    virtual status_t setEnabled(bool enabled, bool fromHandle) = 0;
+    virtual status_t setEnabled_l(bool enabled) = 0;
+    virtual void setSuspended(bool suspended) = 0;
+    virtual bool suspended() const = 0;
+
+    virtual status_t command(int32_t cmdCode,
+            const std::vector<uint8_t>& cmdData,
+            int32_t maxReplySize,
+            std::vector<uint8_t>* reply) = 0;
+
+    virtual ssize_t disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast) = 0;
+    virtual ssize_t removeHandle_l(IAfEffectHandle *handle) = 0;
+    virtual IAfEffectHandle* controlHandle_l() = 0;
+
+    virtual void lock() = 0;
+    virtual void unlock() = 0;
+};
+
+class IAfEffectModule : public virtual IAfEffectBase {
+    friend class DeviceEffectProxy;
+    friend class EffectChain;
+
+public:
+    static sp<IAfEffectModule> create(
+            const sp<EffectCallbackInterface>& callabck,
+            effect_descriptor_t *desc,
+            int id,
+            audio_session_t sessionId,
+            bool pinned,
+            audio_port_handle_t deviceId);
+
+    virtual int16_t *inBuffer() const = 0;
+    virtual status_t setDevices(const AudioDeviceTypeAddrVector &devices) = 0;
+    virtual status_t setInputDevice(const AudioDeviceTypeAddr &device) = 0;
+    virtual status_t setVolume(uint32_t *left, uint32_t *right, bool controller) = 0;
+    virtual status_t setOffloaded(bool offloaded, audio_io_handle_t io) = 0;
+    virtual bool isOffloaded() const = 0;
+
+    virtual status_t setAudioSource(audio_source_t source) = 0;
+    virtual status_t setMode(audio_mode_t mode) = 0;
+
+    virtual status_t start() = 0;
+    virtual status_t getConfigs(audio_config_base_t* inputCfg,
+            audio_config_base_t* outputCfg,
+            bool* isOutput) const = 0;
+
+    static bool isHapticGenerator(const effect_uuid_t* type);
+    virtual bool isHapticGenerator() const = 0;
+    virtual status_t setHapticIntensity(int id, os::HapticScale intensity) = 0;
+    virtual status_t setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo) = 0;
+
+private:
+    virtual void process() = 0;
+    virtual bool updateState() = 0;
+    virtual void reset_l() = 0;
+    virtual status_t configure() = 0;
+    virtual status_t init() = 0;
+    virtual uint32_t status() const = 0;
+    virtual bool isProcessEnabled() const = 0;
+    virtual bool isOffloadedOrDirect() const = 0;
+    virtual bool isVolumeControlEnabled() const = 0;
+
+    virtual void setInBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+    virtual void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+    virtual int16_t *outBuffer() const = 0;
+
+    // Updates the access mode if it is out of date.  May issue a new effect configure.
+    virtual void updateAccessMode() = 0;
+
+    virtual status_t stop() = 0;
+    virtual void addEffectToHal_l() = 0;
+    virtual void release_l() = 0;
+};
+
+class IAfEffectChain : public RefBase {
+    // Most of these methods are accessed from AudioFlinger::Thread
+public:
+    static sp<IAfEffectChain> create(
+            const wp<Thread /*ThreadBase*/>& wThread,  // TODO(b/288339104) type
+            audio_session_t sessionId);
+
+    // special key used for an entry in mSuspendedEffects keyed vector
+    // corresponding to a suspend all request.
+    static constexpr int kKeyForSuspendAll = 0;
+
+    // minimum duration during which we force calling effect process when last track on
+    // a session is stopped or removed to allow effect tail to be rendered
+    static constexpr int kProcessTailDurationMs = 1000;
+
+    virtual void process_l() = 0;
+
+    virtual void lock() = 0;
+    virtual void unlock() = 0;
+
+    virtual status_t createEffect_l(sp<IAfEffectModule>& effect,
+                            effect_descriptor_t *desc,
+                            int id,
+                            audio_session_t sessionId,
+                            bool pinned) = 0;
+
+    virtual status_t addEffect_l(const sp<IAfEffectModule>& handle) = 0;
+    virtual status_t addEffect_ll(const sp<IAfEffectModule>& handle) = 0;
+    virtual size_t removeEffect_l(const sp<IAfEffectModule>& handle, bool release = false) = 0;
+
+    virtual audio_session_t sessionId() const = 0;
+    virtual void setSessionId(audio_session_t sessionId) = 0;
+
+    virtual sp<IAfEffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor) const = 0;
+    virtual sp<IAfEffectModule> getEffectFromId_l(int id) const = 0;
+    virtual sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t *type) const = 0;
+    virtual std::vector<int> getEffectIds() const = 0;
+    virtual bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false) = 0;
+    virtual void resetVolume_l() = 0;
+    virtual void setDevices_l(const AudioDeviceTypeAddrVector &devices) = 0;
+    virtual void setInputDevice_l(const AudioDeviceTypeAddr &device) = 0;
+    virtual void setMode_l(audio_mode_t mode) = 0;
+    virtual void setAudioSource_l(audio_source_t source) = 0;
+
+    virtual void setInBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+    virtual float *inBuffer() const = 0;
+    virtual void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+    virtual float *outBuffer() const = 0;
+
+    virtual void incTrackCnt() = 0;
+    virtual void decTrackCnt() = 0;
+    virtual int32_t trackCnt() const = 0;
+
+    virtual void incActiveTrackCnt() = 0;
+    virtual void decActiveTrackCnt() = 0;
+    virtual int32_t activeTrackCnt() const = 0;
+
+    virtual product_strategy_t strategy() const = 0;
+    virtual void setStrategy(product_strategy_t strategy) = 0;
+
+    // suspend or restore effects of the specified type. The number of suspend requests is counted
+    // and restore occurs once all suspend requests are cancelled.
+    virtual void setEffectSuspended_l(
+            const effect_uuid_t *type, bool suspend) = 0;
+    // suspend all eligible effects
+    virtual void setEffectSuspendedAll_l(bool suspend) = 0;
+    // check if effects should be suspended or restored when a given effect is enable or disabled
+    virtual void checkSuspendOnEffectEnabled(const sp<IAfEffectModule>& effect, bool enabled) = 0;
+
+    virtual void clearInputBuffer() = 0;
+
+    // At least one non offloadable effect in the chain is enabled
+    virtual bool isNonOffloadableEnabled() const = 0;
+    virtual bool isNonOffloadableEnabled_l() const = 0;
+
+    virtual void syncHalEffectsState() = 0;
+
+    // flags is an ORed set of audio_output_flags_t which is updated on return.
+    virtual void checkOutputFlagCompatibility(audio_output_flags_t *flags) const = 0;
+
+    // flags is an ORed set of audio_input_flags_t which is updated on return.
+    virtual void checkInputFlagCompatibility(audio_input_flags_t *flags) const = 0;
+
+    // Is this EffectChain compatible with the RAW audio flag.
+    virtual bool isRawCompatible() const = 0;
+
+    // Is this EffectChain compatible with the FAST audio flag.
+    virtual bool isFastCompatible() const = 0;
+
+    // Is this EffectChain compatible with the bit-perfect audio flag.
+    virtual bool isBitPerfectCompatible() const = 0;
+
+    // isCompatibleWithThread_l() must be called with thread->mLock held
+    //  TODO(b/288339104) type
+    virtual bool isCompatibleWithThread_l(const sp<Thread>& thread) const = 0;
+
+    virtual bool containsHapticGeneratingEffect_l() = 0;
+
+    virtual void setHapticIntensity_l(int id, os::HapticScale intensity) = 0;
+
+    virtual sp<EffectCallbackInterface> effectCallback() const = 0;
+
+    virtual wp<Thread> thread() const = 0;  // TODO(b/288339104) type
+    virtual void setThread(const sp<Thread>& thread) = 0;  // TODO(b/288339104) type
+
+    virtual bool isFirstEffect(int id) const = 0;
+
+    virtual size_t numberOfEffects() const = 0;
+    virtual sp<IAfEffectModule> getEffectModule(size_t index) const = 0;
+
+    virtual void dump(int fd, const Vector<String16>& args) const = 0;
+};
+
+class IAfEffectHandle : public virtual RefBase {
+    friend class EffectBase;
+    friend class EffectChain;
+    friend class EffectModule;
+
+public:
+    static sp<IAfEffectHandle> create(
+            const sp<IAfEffectBase>& effect,
+            const sp<RefBase /*AudioFlinger::Client */>& client,  // TODO(b/288339104) type
+            const sp<media::IEffectClient>& effectClient,
+            int32_t priority, bool notifyFramesProcessed);
+
+    virtual status_t initCheck() const = 0;
+    virtual bool enabled() const = 0;
+    virtual int id() const = 0;
+    virtual wp<IAfEffectBase> effect() const = 0;
+    virtual sp<android::media::IEffect> asIEffect() = 0;
+    // TODO(b/288339104) type
+    virtual sp<RefBase /* AudioFlinger::Client */> client() const = 0;
+
+private:
+    virtual void setControl(bool hasControl, bool signal, bool enabled) = 0;
+    virtual bool hasControl() const = 0;
+    virtual void setEnabled(bool enabled) = 0;
+    virtual bool disconnected() const = 0;
+    virtual int priority() const = 0;
+
+    virtual void commandExecuted(uint32_t cmdCode,
+            const std::vector<uint8_t>& cmdData,
+            const std::vector<uint8_t>& replyData) = 0;
+    virtual void framesProcessed(int32_t frames) const = 0;
+
+    virtual void dumpToBuffer(char* buffer, size_t size) const = 0;
+};
+
+class IAfDeviceEffectProxy : public virtual IAfEffectBase {
+public:
+    // TODO(b/288339104) type
+    static sp<IAfDeviceEffectProxy> create(const AudioDeviceTypeAddr& device,
+                const sp</* DeviceEffectManagerCallback */ RefBase>& callback,
+                effect_descriptor_t *desc, int id, bool notifyFramesProcessed);
+
+    virtual status_t init(
+            const /* std::map<audio_patch_handle_t,
+            PatchPanel::Patch>& */ void * patches) = 0; // TODO(b/288339104) type
+    virtual const AudioDeviceTypeAddr& device() const = 0;
+
+    virtual status_t onCreatePatch(
+            audio_patch_handle_t patchHandle,
+            /* const PatchPanel::Patch& */ const void * patch) = 0;
+    virtual void onReleasePatch(audio_patch_handle_t patchHandle) = 0;
+
+    virtual void dump2(int fd, int spaces) const = 0; // TODO(b/288339104) naming?
+
+private:
+    // used by DeviceEffectProxy
+    virtual bool isOutput() const = 0;
+    virtual uint32_t sampleRate() const = 0;
+    virtual audio_channel_mask_t channelMask() const = 0;
+    virtual uint32_t channelCount() const = 0;
+
+    virtual size_t removeEffect(const sp<IAfEffectModule>& effect) = 0;
+    virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
+    virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
+};
+
+} // namespace android
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 5555766..2c5e47c 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -19,7 +19,7 @@
     #error This header file should only be included from AudioFlinger.h
 #endif
 
-
+public: // TODO(b/288339104) extract out of AudioFlinger class
 // PatchPanel is concealed within AudioFlinger, their lifetimes are the same.
 class PatchPanel {
 public:
@@ -265,3 +265,5 @@
     };
     std::map<audio_module_handle_t, ModuleConnections> mInsertedModules;
 };
+
+private:
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 95883d9..0add182 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1061,7 +1061,7 @@
     write(fd, buffer, strlen(buffer));
 
     for (size_t i = 0; i < numEffectChains; ++i) {
-        sp<EffectChain> chain = mEffectChains[i];
+        sp<IAfEffectChain> chain = mEffectChains[i];
         if (chain != 0) {
             chain->dump(fd, args);
         }
@@ -1211,7 +1211,7 @@
 void AudioFlinger::ThreadBase::setEffectSuspended_l(
         const effect_uuid_t *type, bool suspend, audio_session_t sessionId)
 {
-    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
     if (chain != 0) {
         if (type != NULL) {
             chain->setEffectSuspended_l(type, suspend);
@@ -1223,7 +1223,7 @@
     updateSuspendedSessions_l(type, suspend, sessionId);
 }
 
-void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
+void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
     if (index < 0) {
@@ -1236,7 +1236,7 @@
     for (size_t i = 0; i < sessionEffects.size(); i++) {
         const sp<SuspendedSessionDesc>& desc = sessionEffects.valueAt(i);
         for (int j = 0; j < desc->mRefCount; j++) {
-            if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
+            if (sessionEffects.keyAt(i) == IAfEffectChain::kKeyForSuspendAll) {
                 chain->setEffectSuspendedAll_l(true);
             } else {
                 ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
@@ -1269,7 +1269,7 @@
     }
 
 
-    int key = EffectChain::kKeyForSuspendAll;
+    int key = IAfEffectChain::kKeyForSuspendAll;
     if (type != NULL) {
         key = type->timeLow;
     }
@@ -1370,7 +1370,7 @@
         }
     }
 
-    if (EffectModule::isHapticGenerator(&desc->type)) {
+    if (IAfEffectModule::isHapticGenerator(&desc->type)) {
         ALOGE("%s(): HapticGenerator is not supported in RecordThread", __func__);
         return BAD_VALUE;
     }
@@ -1393,7 +1393,7 @@
         return NO_ERROR;
     }
 
-    if (EffectModule::isHapticGenerator(&desc->type) && mHapticChannelCount == 0) {
+    if (IAfEffectModule::isHapticGenerator(&desc->type) && mHapticChannelCount == 0) {
         ALOGW("%s: thread doesn't support haptic playback while the effect is HapticGenerator",
                 __func__);
         return BAD_VALUE;
@@ -1533,7 +1533,7 @@
 }
 
 // ThreadBase::createEffect_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
+sp<IAfEffectHandle> AudioFlinger::ThreadBase::createEffect_l(
         const sp<AudioFlinger::Client>& client,
         const sp<IEffectClient>& effectClient,
         int32_t priority,
@@ -1545,10 +1545,10 @@
         bool probe,
         bool notifyFramesProcessed)
 {
-    sp<EffectModule> effect;
-    sp<EffectHandle> handle;
+    sp<IAfEffectModule> effect;
+    sp<IAfEffectHandle> handle;
     status_t lStatus;
-    sp<EffectChain> chain;
+    sp<IAfEffectChain> chain;
     bool chainCreated = false;
     bool effectCreated = false;
     audio_unique_id_t effectId = AUDIO_UNIQUE_ID_USE_UNSPECIFIED;
@@ -1574,7 +1574,7 @@
         if (chain == 0) {
             // create a new chain for this session
             ALOGV("createEffect_l() new effect chain for session %d", sessionId);
-            chain = new EffectChain(this, sessionId);
+            chain = IAfEffectChain::create(this, sessionId);
             addEffectChain_l(chain);
             chain->setStrategy(getStrategyForSession_l(sessionId));
             chainCreated = true;
@@ -1610,7 +1610,8 @@
             }
         }
         // create effect handle and connect it to effect module
-        handle = new EffectHandle(effect, client, effectClient, priority, notifyFramesProcessed);
+        handle = IAfEffectHandle::create(
+                effect, client, effectClient, priority, notifyFramesProcessed);
         lStatus = handle->initCheck();
         if (lStatus == OK) {
             lStatus = effect->addHandle(handle.get());
@@ -1637,14 +1638,14 @@
     return handle;
 }
 
-void AudioFlinger::ThreadBase::disconnectEffectHandle(EffectHandle *handle,
+void AudioFlinger::ThreadBase::disconnectEffectHandle(IAfEffectHandle *handle,
                                                       bool unpinIfLast)
 {
     bool remove = false;
-    sp<EffectModule> effect;
+    sp<IAfEffectModule> effect;
     {
         Mutex::Autolock _l(mLock);
-        sp<EffectBase> effectBase = handle->effect().promote();
+        sp<IAfEffectBase> effectBase = handle->effect().promote();
         if (effectBase == nullptr) {
             return;
         }
@@ -1667,7 +1668,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::onEffectEnable(const sp<EffectModule>& effect) {
+void AudioFlinger::ThreadBase::onEffectEnable(const sp<IAfEffectModule>& effect) {
     if (isOffloadOrMmap()) {
         Mutex::Autolock _l(mLock);
         broadcast_l();
@@ -1690,33 +1691,33 @@
     }
 }
 
-sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId,
+sp<IAfEffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId,
         int effectId)
 {
     Mutex::Autolock _l(mLock);
     return getEffect_l(sessionId, effectId);
 }
 
-sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(audio_session_t sessionId,
+sp<IAfEffectModule> AudioFlinger::ThreadBase::getEffect_l(audio_session_t sessionId,
         int effectId)
 {
-    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
     return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
 }
 
 std::vector<int> AudioFlinger::ThreadBase::getEffectIds_l(audio_session_t sessionId)
 {
-    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
     return chain != nullptr ? chain->getEffectIds() : std::vector<int>{};
 }
 
 // PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
 // PlaybackThread::mLock held
-status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
+status_t AudioFlinger::ThreadBase::addEffect_l(const sp<IAfEffectModule>& effect)
 {
     // check for existing effect chain with the requested audio session
     audio_session_t sessionId = effect->sessionId();
-    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
     bool chainCreated = false;
 
     ALOGD_IF((mType == OFFLOAD) && !effect->isOffloadable(),
@@ -1726,7 +1727,7 @@
     if (chain == 0) {
         // create a new chain for this session
         ALOGV("addEffect_l() new effect chain for session %d", sessionId);
-        chain = new EffectChain(this, sessionId);
+        chain = IAfEffectChain::create(this, sessionId);
         addEffectChain_l(chain);
         chain->setStrategy(getStrategyForSession_l(sessionId));
         chainCreated = true;
@@ -1757,7 +1758,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect, bool release) {
+void AudioFlinger::ThreadBase::removeEffect_l(const sp<IAfEffectModule>& effect, bool release) {
 
     ALOGV("%s %p effect %p", __FUNCTION__, this, effect.get());
     effect_descriptor_t desc = effect->desc();
@@ -1765,7 +1766,7 @@
         detachAuxEffect_l(effect->id());
     }
 
-    sp<EffectChain> chain = effect->getCallback()->chain().promote();
+    sp<IAfEffectChain> chain = effect->getCallback()->chain().promote();
     if (chain != 0) {
         // remove effect chain if removing last effect
         if (chain->removeEffect_l(effect, release) == 0) {
@@ -1777,7 +1778,7 @@
 }
 
 void AudioFlinger::ThreadBase::lockEffectChains_l(
-        Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+        Vector<sp<IAfEffectChain>>& effectChains)
 NO_THREAD_SAFETY_ANALYSIS  // calls EffectChain::lock()
 {
     effectChains = mEffectChains;
@@ -1787,7 +1788,7 @@
 }
 
 void AudioFlinger::ThreadBase::unlockEffectChains(
-        const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+        const Vector<sp<IAfEffectChain>>& effectChains)
 NO_THREAD_SAFETY_ANALYSIS  // calls EffectChain::unlock()
 {
     for (size_t i = 0; i < effectChains.size(); i++) {
@@ -1795,13 +1796,13 @@
     }
 }
 
-sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(audio_session_t sessionId)
+sp<IAfEffectChain> AudioFlinger::ThreadBase::getEffectChain(audio_session_t sessionId)
 {
     Mutex::Autolock _l(mLock);
     return getEffectChain_l(sessionId);
 }
 
-sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(audio_session_t sessionId)
+sp<IAfEffectChain> AudioFlinger::ThreadBase::getEffectChain_l(audio_session_t sessionId)
         const
 {
     size_t size = mEffectChains.size();
@@ -2350,7 +2351,7 @@
     }
 
     if (isBitPerfect) {
-        sp<EffectChain> chain = getEffectChain_l(sessionId);
+        sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
         if (chain.get() != nullptr) {
             // Bit-perfect is required according to the configuration and preferred mixer
             // attributes, but it is not in the output flag from the client's request. Explicitly
@@ -2407,7 +2408,7 @@
                     AUDIO_SESSION_OUTPUT_MIX,
                     sessionId,
                 }) {
-                sp<EffectChain> chain = getEffectChain_l(session);
+                sp<IAfEffectChain> chain = getEffectChain_l(session);
                 if (chain.get() != nullptr) {
                     audio_output_flags_t old = *flags;
                     chain->checkOutputFlagCompatibility(flags);
@@ -2657,7 +2658,7 @@
             }
         }
 
-        sp<EffectChain> chain = getEffectChain_l(sessionId);
+        sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
         if (chain != 0) {
             ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
             track->setMainBuffer(chain->inBuffer());
@@ -2825,7 +2826,7 @@
                     track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
         }
 
-        sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+        sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
         if (mHapticChannelMask != AUDIO_CHANNEL_NONE
                 && ((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
                         || (chain != nullptr && chain->containsHapticGeneratingEffect_l()))) {
@@ -2918,7 +2919,7 @@
         // redundant as track is about to be destroyed, for dumpsys only
         track->mFastIndex = -1;
     }
-    sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+    sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
     if (chain != 0) {
         chain->decTrackCnt();
     }
@@ -3206,7 +3207,7 @@
     // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
     // matter.
     // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
-    Vector< sp<EffectChain> > effectChains = mEffectChains;
+    Vector<sp<IAfEffectChain>> effectChains = mEffectChains;
     for (size_t i = 0; i < effectChains.size(); i ++) {
         mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(),
             this/* srcThread */, this/* dstThread */);
@@ -3617,7 +3618,7 @@
     return nullptr;
 }
 
-status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
+status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
     sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
@@ -3753,7 +3754,7 @@
     return NO_ERROR;
 }
 
-size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
+size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
 
@@ -3801,7 +3802,7 @@
         track->setAuxBuffer(0, NULL);
     } else {
         // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
-        sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
+        sp<IAfEffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
         if (effect != 0) {
             if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
                 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
@@ -3882,7 +3883,7 @@
 
         cpuStats.sample(myName);
 
-        Vector< sp<EffectChain> > effectChains;
+        Vector<sp<IAfEffectChain>> effectChains;
         audio_session_t activeHapticSessionId = AUDIO_SESSION_NONE;
         bool isHapticSessionSpatialized = false;
         std::vector<sp<Track>> activeTracks;
@@ -4048,7 +4049,7 @@
             // TODO: Write haptic data directly to sink buffer when mixing.
             if (mHapticChannelCount > 0) {
                 for (const auto& track : mActiveTracks) {
-                    sp<EffectChain> effectChain = getEffectChain_l(track->sessionId());
+                    sp<IAfEffectChain> effectChain = getEffectChain_l(track->sessionId());
                     if (effectChain != nullptr
                             && effectChain->containsHapticGeneratingEffect_l()) {
                         activeHapticSessionId = track->sessionId();
@@ -4622,7 +4623,7 @@
     for (const auto& track : tracksToRemove) {
         mActiveTracks.remove(track);
         ALOGV("%s(%d): removing track on session %d", __func__, track->id(), track->sessionId());
-        sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+        sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
         if (chain != 0) {
             ALOGV("%s(%d): stopping track on chain %p for session Id: %d",
                     __func__, track->id(), chain.get(), track->sessionId());
@@ -5343,7 +5344,7 @@
         masterVolume = 0;
     }
     // Delegate master volume control to effect in output mix effect chain if needed
-    sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+    sp<IAfEffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
     if (chain != 0) {
         uint32_t v = (uint32_t)(masterVolume * (1 << 24));
         chain->setVolume_l(&v, &v);
@@ -7714,10 +7715,10 @@
 {
     bool hasVirtualizer = false;
     bool hasDownMixer = false;
-    sp<EffectHandle> finalDownMixer;
+    sp<IAfEffectHandle> finalDownMixer;
     {
         Mutex::Autolock _l(mLock);
-        sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE);
+        sp<IAfEffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE);
         if (chain != 0) {
             hasVirtualizer = chain->getEffectFromType_l(FX_IID_SPATIALIZER) != nullptr;
             hasDownMixer = chain->getEffectFromType_l(EFFECT_UIID_DOWNMIX) != nullptr;
@@ -7730,7 +7731,7 @@
     if (hasVirtualizer) {
         if (finalDownMixer != nullptr) {
             int32_t ret;
-            finalDownMixer->disable(&ret);
+            finalDownMixer->asIEffect()->disable(&ret);
         }
         finalDownMixer.clear();
     } else if (!hasDownMixer) {
@@ -7752,7 +7753,7 @@
             finalDownMixer.clear();
         } else {
             int32_t ret;
-            finalDownMixer->enable(&ret);
+            finalDownMixer->asIEffect()->enable(&ret);
         }
     }
 
@@ -7984,7 +7985,7 @@
 
     // loop while there is work to do
     for (int64_t loopCount = 0;; ++loopCount) {  // loopCount used for statistics tracking
-        Vector< sp<EffectChain> > effectChains;
+        Vector<sp<IAfEffectChain>> effectChains;
 
         // activeTracks accumulates a copy of a subset of mActiveTracks
         Vector< sp<RecordTrack> > activeTracks;
@@ -8671,7 +8672,7 @@
           // check compatibility with audio effects.
           Mutex::Autolock _l(mLock);
           // Do not accept FAST flag if the session has software effects
-          sp<EffectChain> chain = getEffectChain_l(sessionId);
+          sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
           if (chain != 0) {
               audio_input_flags_t old = *flags;
               chain->checkInputFlagCompatibility(flags);
@@ -9496,7 +9497,7 @@
     return mInput->stream;
 }
 
-status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
+status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
     chain->setThread(this);
@@ -9514,7 +9515,7 @@
     return NO_ERROR;
 }
 
-size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
+size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
 
@@ -10042,7 +10043,7 @@
     }
 
     mActiveTracks.add(track);
-    sp<EffectChain> chain = getEffectChain_l(mSessionId);
+    sp<IAfEffectChain> chain = getEffectChain_l(mSessionId);
     if (chain != 0) {
         chain->setStrategy(getStrategyForStream(streamType()));
         chain->incTrackCnt();
@@ -10102,7 +10103,7 @@
     }
     mLock.lock();
 
-    sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+    sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
     if (chain != 0) {
         chain->decActiveTrackCnt();
         chain->decTrackCnt();
@@ -10186,7 +10187,7 @@
 
     while (!exitPending())
     {
-        Vector< sp<EffectChain> > effectChains;
+        Vector<sp<IAfEffectChain>> effectChains;
 
         { // under Thread lock
         Mutex::Autolock _l(mLock);
@@ -10429,7 +10430,7 @@
     }
 }
 
-status_t AudioFlinger::MmapThread::addEffectChain_l(const sp<EffectChain>& chain)
+status_t AudioFlinger::MmapThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
 
@@ -10453,7 +10454,7 @@
     return NO_ERROR;
 }
 
-size_t AudioFlinger::MmapThread::removeEffectChain_l(const sp<EffectChain>& chain)
+size_t AudioFlinger::MmapThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
 
@@ -10524,7 +10525,7 @@
         return BAD_VALUE;
     }
 
-    if (EffectModule::isHapticGenerator(&desc->type)) {
+    if (IAfEffectModule::isHapticGenerator(&desc->type)) {
         ALOGE("%s(): HapticGenerator is not supported for MmapThread", __func__);
         return BAD_VALUE;
     }
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index b2700db..8620c15 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -19,6 +19,7 @@
     #error This header file should only be included from AudioFlinger.h
 #endif
 
+public: // TODO(b/288339104) extract out of AudioFlinger class
 class ThreadBase : public Thread {
 public:
 
@@ -409,7 +410,7 @@
 
     virtual     sp<StreamHalInterface> stream() const = 0;
 
-                sp<EffectHandle> createEffect_l(
+                sp<IAfEffectHandle> createEffect_l(
                                     const sp<AudioFlinger::Client>& client,
                                     const sp<media::IEffectClient>& effectClient,
                                     int32_t priority,
@@ -436,37 +437,37 @@
                 };
 
                 // get effect chain corresponding to session Id.
-                sp<EffectChain> getEffectChain(audio_session_t sessionId);
+                sp<IAfEffectChain> getEffectChain(audio_session_t sessionId);
                 // same as getEffectChain() but must be called with ThreadBase mutex locked
-                sp<EffectChain> getEffectChain_l(audio_session_t sessionId) const;
+                sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const;
                 std::vector<int> getEffectIds_l(audio_session_t sessionId);
                 // add an effect chain to the chain list (mEffectChains)
-    virtual     status_t addEffectChain_l(const sp<EffectChain>& chain) = 0;
+    virtual     status_t addEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
                 // remove an effect chain from the chain list (mEffectChains)
-    virtual     size_t removeEffectChain_l(const sp<EffectChain>& chain) = 0;
+    virtual     size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
                 // lock all effect chains Mutexes. Must be called before releasing the
                 // ThreadBase mutex before processing the mixer and effects. This guarantees the
                 // integrity of the chains during the process.
                 // Also sets the parameter 'effectChains' to current value of mEffectChains.
-                void lockEffectChains_l(Vector< sp<EffectChain> >& effectChains);
+                void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains);
                 // unlock effect chains after process
-                void unlockEffectChains(const Vector< sp<EffectChain> >& effectChains);
+                void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains);
                 // get a copy of mEffectChains vector
-                Vector< sp<EffectChain> > getEffectChains_l() const { return mEffectChains; };
+                Vector<sp<IAfEffectChain>> getEffectChains_l() const { return mEffectChains; };
                 // set audio mode to all effect chains
                 void setMode(audio_mode_t mode);
                 // get effect module with corresponding ID on specified audio session
-                sp<AudioFlinger::EffectModule> getEffect(audio_session_t sessionId, int effectId);
-                sp<AudioFlinger::EffectModule> getEffect_l(audio_session_t sessionId, int effectId);
+                sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId);
+                sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId);
                 // add and effect module. Also creates the effect chain is none exists for
                 // the effects audio session. Only called in a context of moving an effect
                 // from one thread to another
-                status_t addEffect_l(const sp< EffectModule>& effect);
+                status_t addEffect_l(const sp<IAfEffectModule>& effect);
                 // remove and effect module. Also removes the effect chain is this was the last
                 // effect
-                void removeEffect_l(const sp< EffectModule>& effect, bool release = false);
+                void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false);
                 // disconnect an effect handle from module and destroy module if last handle
-                void disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast);
+                void disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast);
                 // detach all tracks connected to an auxiliary effect
     virtual     void detachAuxEffect_l(int effectId __unused) {}
                 // returns a combination of:
@@ -552,7 +553,7 @@
 
     mutable     Mutex                   mLock;
 
-                void onEffectEnable(const sp<EffectModule>& effect);
+                void onEffectEnable(const sp<IAfEffectModule>& effect);
                 void onEffectDisable();
 
                 // invalidateTracksForAudioSession_l must be called with holding mLock.
@@ -607,7 +608,7 @@
                                                       bool suspend,
                                                       audio_session_t sessionId);
                 // check if some effects must be suspended when an effect chain is added
-                void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain);
+                void checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain);
 
                 // sends the metadata of the active tracks to the HAL
                 struct MetadataUpdate {
@@ -627,8 +628,10 @@
                                     ExtendedTimestamp *timestamp __unused) const {
                                 return INVALID_OPERATION;
                             }
-
+public:
+// TODO(b/288339104) organize with publics
                 product_strategy_t getStrategyForStream(audio_stream_type_t stream) const;
+protected:
 
     virtual     void        onHalLatencyModesChanged_l() {}
 
@@ -680,7 +683,7 @@
                 audio_source_t          mAudioSource;
 
                 const audio_io_handle_t mId;
-                Vector< sp<EffectChain> > mEffectChains;
+                Vector<sp<IAfEffectChain>> mEffectChains;
 
                 static const int        kThreadNameLength = 16; // prctl(PR_SET_NAME) limit
                 char                    mThreadName[kThreadNameLength]; // guaranteed NUL-terminated
@@ -844,6 +847,8 @@
                 void dumpEffectChains_l(int fd, const Vector<String16>& args);
 };
 
+private:
+
 class VolumeInterface {
  public:
 
@@ -1030,8 +1035,8 @@
                 status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track>& track,
                         int EffectId);
 
-                virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
-                virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+                virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain);
+                virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain);
                         uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
                             return ThreadBase::hasAudioSession_l(sessionId, mTracks);
                         }
@@ -1857,7 +1862,7 @@
             // Do not request a specific mode by default
             audio_latency_mode_t mRequestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
 
-            sp<EffectHandle> mFinalDownMixer;
+            sp<IAfEffectHandle> mFinalDownMixer;
 };
 
 // record thread
@@ -1984,8 +1989,8 @@
             void        readInputParameters_l();
     virtual uint32_t    getInputFramesLost();
 
-    virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
-    virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+    virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain);
+    virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain);
             uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
                          return ThreadBase::hasAudioSession_l(sessionId, mTracks);
                      }
@@ -2193,8 +2198,8 @@
     virtual     void        toAudioPortConfig(struct audio_port_config *config);
 
     virtual     sp<StreamHalInterface> stream() const { return mHalStream; }
-    virtual     status_t    addEffectChain_l(const sp<EffectChain>& chain);
-    virtual     size_t      removeEffectChain_l(const sp<EffectChain>& chain);
+    virtual     status_t    addEffectChain_l(const sp<IAfEffectChain>& chain);
+    virtual     size_t      removeEffectChain_l(const sp<IAfEffectChain>& chain);
     virtual     status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc,
                                                                audio_session_t sessionId);
 
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 00c88bc..e23b150 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1064,7 +1064,7 @@
         if (isOffloaded()) {
             Mutex::Autolock _laf(thread->mAudioFlinger->mLock);
             Mutex::Autolock _lth(thread->mLock);
-            sp<EffectChain> ec = thread->getEffectChain_l(mSessionId);
+            sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
             if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() ||
                     (ec != 0 && ec->isNonOffloadableEnabled())) {
                 invalidate();