Merge "DO NOT MERGE: Merge Oreo MR1 into master"
diff --git a/Android.bp b/Android.bp
index 4cdb881..e4f12c8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2,7 +2,6 @@
     "camera",
     "drm/*",
     "media/*",
-    "radio",
     "services/*",
     "soundtrigger",
 ]
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 5e4d81d..793cbf4 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -78,6 +78,9 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/soundfx/libbundlewrapper.so)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/soundfx/libaudiopreprocessing.so)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libmediacodecservice.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libstagefright_xmlparser@1.0.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libstagefright_soft_*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk/libstagefright_soft_*)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/camera/Android.bp b/camera/Android.bp
index beb205a..24b3918 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -77,7 +77,7 @@
 
 }
 
-// AIDL interface between libcamera_client and framework.jar.
+// AIDL interface between camera clients and the camera service.
 filegroup {
     name: "libcamera_client_aidl",
     srcs: [
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
index 8308095..28252c0 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -42,7 +42,9 @@
      * Repeating request encountered an error and was stopped.
      *
      * @param lastFrameNumber Frame number of the last frame of the streaming request.
+     * @param repeatingRequestId the ID of the repeating request being stopped
      */
-    oneway void onRepeatingRequestError(in long lastFrameNumber);
+    oneway void onRepeatingRequestError(in long lastFrameNumber,
+                                        in int repeatingRequestId);
     oneway void onRequestQueueEmpty();
 }
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 98571c1..907802c 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -1372,7 +1372,8 @@
 }
 
 binder::Status
-CameraDevice::ServiceCallback::onRepeatingRequestError(int64_t lastFrameNumber) {
+CameraDevice::ServiceCallback::onRepeatingRequestError(
+        int64_t lastFrameNumber, int32_t stoppedSequenceId) {
     binder::Status ret = binder::Status::ok();
 
     sp<CameraDevice> dev = mDevice.promote();
@@ -1383,7 +1384,9 @@
     Mutex::Autolock _l(dev->mDeviceLock);
 
     int repeatingSequenceId = dev->mRepeatingSequenceId;
-    dev->mRepeatingSequenceId = REQUEST_ID_NONE;
+    if (stoppedSequenceId == repeatingSequenceId) {
+        dev->mRepeatingSequenceId = REQUEST_ID_NONE;
+    }
 
     dev->checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
 
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 15dd08d..6ed3881 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -75,7 +75,8 @@
                               const CaptureResultExtras& resultExtras) override;
         binder::Status onPrepared(int streamId) override;
         binder::Status onRequestQueueEmpty() override;
-        binder::Status onRepeatingRequestError(int64_t lastFrameNumber) override;
+        binder::Status onRepeatingRequestError(int64_t lastFrameNumber,
+                int32_t stoppedSequenceId) override;
       private:
         const wp<CameraDevice> mDevice;
     };
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 946e3b8..51d9214 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -217,8 +217,10 @@
         return binder::Status::ok();
     }
 
-    virtual binder::Status onRepeatingRequestError(int64_t lastFrameNumber) {
+    virtual binder::Status onRepeatingRequestError(
+            int64_t lastFrameNumber, int32_t stoppedSequenceId) {
         (void) lastFrameNumber;
+        (void) stoppedSequenceId;
         Mutex::Autolock l(mLock);
         mLastStatus = REPEATING_REQUEST_ERROR;
         mStatusesHit.push_back(mLastStatus);
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index de0167a..bc32bbe 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -78,7 +78,7 @@
 static bool gWantFrameTime = false;     // do we want times on each frame?
 static uint32_t gVideoWidth = 0;        // default width+height
 static uint32_t gVideoHeight = 0;
-static uint32_t gBitRate = 4000000;     // 4Mbps
+static uint32_t gBitRate = 20000000;     // 20Mbps
 static uint32_t gTimeLimitSec = kMaxTimeLimitSec;
 
 // Set by signal handler to stop recording.
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index d7c2e87..d70282b 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -870,7 +870,9 @@
 
             sp<IMemory> mem =
                     retriever->getFrameAtTime(-1,
-                                    MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+                            MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC,
+                            HAL_PIXEL_FORMAT_RGB_565,
+                            false /*metaOnly*/);
 
             if (mem != NULL) {
                 failed = false;
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 444f307..0c14201 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -5,33 +5,31 @@
 cc_library_shared {
     name: "libmediadrm",
 
-    aidl: {
-        local_include_dirs: ["aidl"],
-        export_aidl_headers: true,
-    },
 
     srcs: [
-        ":libmediadrm_aidl",
-
-        "CasImpl.cpp",
-        "DescramblerImpl.cpp",
         "DrmPluginPath.cpp",
         "DrmSessionManager.cpp",
         "ICrypto.cpp",
         "IDrm.cpp",
         "IDrmClient.cpp",
         "IMediaDrmService.cpp",
-        "MediaCasDefs.cpp",
+        "PluginMetricsReporting.cpp",
         "SharedLibrary.cpp",
         "DrmHal.cpp",
         "CryptoHal.cpp",
+        "protos/plugin_metrics.proto",
     ],
 
+    proto: {
+        type: "lite",
+    },
+
     shared_libs: [
         "libbinder",
         "libcutils",
         "libdl",
         "liblog",
+        "libmediametrics",
         "libmediautils",
         "libstagefright_foundation",
         "libutils",
@@ -46,14 +44,3 @@
         "-Wall",
     ],
 }
-
-// AIDL interface between libmediadrm and framework.jar
-filegroup {
-    name: "libmediadrm_aidl",
-    srcs: [
-        "aidl/android/media/ICas.aidl",
-        "aidl/android/media/ICasListener.aidl",
-        "aidl/android/media/IDescrambler.aidl",
-        "aidl/android/media/IMediaCasService.aidl",
-    ],
-}
diff --git a/drm/libmediadrm/CasImpl.cpp b/drm/libmediadrm/CasImpl.cpp
deleted file mode 100644
index 1a33bb0..0000000
--- a/drm/libmediadrm/CasImpl.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-//#define LOG_NDEBUG 0
-#define LOG_TAG "CasImpl"
-
-#include <android/media/ICasListener.h>
-#include <media/cas/CasAPI.h>
-#include <media/CasImpl.h>
-#include <media/SharedLibrary.h>
-#include <utils/Log.h>
-
-namespace android {
-
-static Status getBinderStatus(status_t err) {
-    if (err == OK) {
-        return Status::ok();
-    }
-    if (err == BAD_VALUE) {
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
-    }
-    if (err == INVALID_OPERATION) {
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
-    }
-    return Status::fromServiceSpecificError(err);
-}
-
-static String8 sessionIdToString(const CasSessionId &sessionId) {
-    String8 result;
-    for (size_t i = 0; i < sessionId.size(); i++) {
-        result.appendFormat("%02x ", sessionId[i]);
-    }
-    if (result.isEmpty()) {
-        result.append("(null)");
-    }
-    return result;
-}
-
-struct CasImpl::PluginHolder : public RefBase {
-public:
-    explicit PluginHolder(CasPlugin *plugin) : mPlugin(plugin) {}
-    ~PluginHolder() { if (mPlugin != NULL) delete mPlugin; }
-    CasPlugin* get() { return mPlugin; }
-
-private:
-    CasPlugin *mPlugin;
-    DISALLOW_EVIL_CONSTRUCTORS(PluginHolder);
-};
-
-CasImpl::CasImpl(const sp<ICasListener> &listener)
-    : mPluginHolder(NULL), mListener(listener) {
-    ALOGV("CTOR");
-}
-
-CasImpl::~CasImpl() {
-    ALOGV("DTOR");
-    release();
-}
-
-//static
-void CasImpl::OnEvent(
-        void *appData,
-        int32_t event,
-        int32_t arg,
-        uint8_t *data,
-        size_t size) {
-    if (appData == NULL) {
-        ALOGE("Invalid appData!");
-        return;
-    }
-    CasImpl *casImpl = static_cast<CasImpl *>(appData);
-    casImpl->onEvent(event, arg, data, size);
-}
-
-void CasImpl::init(const sp<SharedLibrary>& library, CasPlugin *plugin) {
-    mLibrary = library;
-    mPluginHolder = new PluginHolder(plugin);
-}
-
-void CasImpl::onEvent(
-        int32_t event, int32_t arg, uint8_t *data, size_t size) {
-    if (mListener == NULL) {
-        return;
-    }
-
-    std::unique_ptr<CasData> eventData;
-    if (data != NULL && size > 0) {
-        eventData.reset(new CasData(data, data + size));
-    }
-
-    mListener->onEvent(event, arg, eventData);
-}
-
-Status CasImpl::setPrivateData(const CasData& pvtData) {
-    ALOGV("setPrivateData");
-    sp<PluginHolder> holder = mPluginHolder;
-    if (holder == NULL) {
-        return getBinderStatus(INVALID_OPERATION);
-    }
-    return getBinderStatus(holder->get()->setPrivateData(pvtData));
-}
-
-Status CasImpl::openSession(CasSessionId* sessionId) {
-    ALOGV("openSession");
-    sp<PluginHolder> holder = mPluginHolder;
-    if (holder == NULL) {
-        return getBinderStatus(INVALID_OPERATION);
-    }
-    status_t err = holder->get()->openSession(sessionId);
-
-    ALOGV("openSession: session opened, sessionId=%s",
-            sessionIdToString(*sessionId).string());
-
-    return getBinderStatus(err);
-}
-
-Status CasImpl::setSessionPrivateData(
-        const CasSessionId &sessionId, const CasData& pvtData) {
-    ALOGV("setSessionPrivateData: sessionId=%s",
-            sessionIdToString(sessionId).string());
-    sp<PluginHolder> holder = mPluginHolder;
-    if (holder == NULL) {
-        return getBinderStatus(INVALID_OPERATION);
-    }
-    return getBinderStatus(holder->get()->setSessionPrivateData(sessionId, pvtData));
-}
-
-Status CasImpl::closeSession(const CasSessionId &sessionId) {
-    ALOGV("closeSession: sessionId=%s",
-            sessionIdToString(sessionId).string());
-    sp<PluginHolder> holder = mPluginHolder;
-    if (holder == NULL) {
-        return getBinderStatus(INVALID_OPERATION);
-    }
-    return getBinderStatus(holder->get()->closeSession(sessionId));
-}
-
-Status CasImpl::processEcm(const CasSessionId &sessionId, const ParcelableCasData& ecm) {
-    ALOGV("processEcm: sessionId=%s",
-            sessionIdToString(sessionId).string());
-    sp<PluginHolder> holder = mPluginHolder;
-    if (holder == NULL) {
-        return getBinderStatus(INVALID_OPERATION);
-    }
-
-    return getBinderStatus(holder->get()->processEcm(sessionId, ecm));
-}
-
-Status CasImpl::processEmm(const ParcelableCasData& emm) {
-    ALOGV("processEmm");
-    sp<PluginHolder> holder = mPluginHolder;
-    if (holder == NULL) {
-        return getBinderStatus(INVALID_OPERATION);
-    }
-
-    return getBinderStatus(holder->get()->processEmm(emm));
-}
-
-Status CasImpl::sendEvent(
-        int32_t event, int32_t arg, const ::std::unique_ptr<CasData> &eventData) {
-    ALOGV("sendEvent");
-    sp<PluginHolder> holder = mPluginHolder;
-    if (holder == NULL) {
-        return getBinderStatus(INVALID_OPERATION);
-    }
-
-    status_t err;
-    if (eventData == nullptr) {
-        err = holder->get()->sendEvent(event, arg, CasData());
-    } else {
-        err = holder->get()->sendEvent(event, arg, *eventData);
-    }
-    return getBinderStatus(err);
-}
-
-Status CasImpl::provision(const String16& provisionString) {
-    ALOGV("provision: provisionString=%s", String8(provisionString).string());
-    sp<PluginHolder> holder = mPluginHolder;
-    if (holder == NULL) {
-        return getBinderStatus(INVALID_OPERATION);
-    }
-
-    return getBinderStatus(holder->get()->provision(String8(provisionString)));
-}
-
-Status CasImpl::refreshEntitlements(
-        int32_t refreshType, const ::std::unique_ptr<CasData> &refreshData) {
-    ALOGV("refreshEntitlements");
-    sp<PluginHolder> holder = mPluginHolder;
-    if (holder == NULL) {
-        return getBinderStatus(INVALID_OPERATION);
-    }
-
-    status_t err;
-    if (refreshData == nullptr) {
-        err = holder->get()->refreshEntitlements(refreshType, CasData());
-    } else {
-        err = holder->get()->refreshEntitlements(refreshType, *refreshData);
-    }
-    return getBinderStatus(err);
-}
-
-Status CasImpl::release() {
-    ALOGV("release: plugin=%p",
-            mPluginHolder == NULL ? mPluginHolder->get() : NULL);
-    mPluginHolder.clear();
-    return Status::ok();
-}
-
-} // namespace android
-
diff --git a/drm/libmediadrm/DescramblerImpl.cpp b/drm/libmediadrm/DescramblerImpl.cpp
deleted file mode 100644
index 94e09e2..0000000
--- a/drm/libmediadrm/DescramblerImpl.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-//#define LOG_NDEBUG 0
-#define LOG_TAG "DescramblerImpl"
-
-#include <media/cas/DescramblerAPI.h>
-#include <media/DescramblerImpl.h>
-#include <media/SharedLibrary.h>
-#include <utils/Log.h>
-#include <binder/IMemory.h>
-
-namespace android {
-
-static Status getBinderStatus(status_t err) {
-    if (err == OK) {
-        return Status::ok();
-    }
-    if (err == BAD_VALUE) {
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
-    }
-    if (err == INVALID_OPERATION) {
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
-    }
-    return Status::fromServiceSpecificError(err);
-}
-
-static String8 sessionIdToString(const CasSessionId &sessionId) {
-    String8 result;
-    for (size_t i = 0; i < sessionId.size(); i++) {
-        result.appendFormat("%02x ", sessionId[i]);
-    }
-    if (result.isEmpty()) {
-        result.append("(null)");
-    }
-    return result;
-}
-
-DescramblerImpl::DescramblerImpl(
-        const sp<SharedLibrary>& library, DescramblerPlugin *plugin) :
-        mLibrary(library), mPlugin(plugin) {
-    ALOGV("CTOR: mPlugin=%p", mPlugin);
-}
-
-DescramblerImpl::~DescramblerImpl() {
-    ALOGV("DTOR: mPlugin=%p", mPlugin);
-    release();
-}
-
-Status DescramblerImpl::setMediaCasSession(const CasSessionId& sessionId) {
-    ALOGV("setMediaCasSession: sessionId=%s",
-            sessionIdToString(sessionId).string());
-
-    return getBinderStatus(mPlugin->setMediaCasSession(sessionId));
-}
-
-Status DescramblerImpl::requiresSecureDecoderComponent(
-        const String16& mime, bool *result) {
-    *result = mPlugin->requiresSecureDecoderComponent(String8(mime));
-
-    return getBinderStatus(OK);
-}
-
-Status DescramblerImpl::descramble(
-        const DescrambleInfo& info, int32_t *result) {
-    ALOGV("descramble");
-
-    *result = mPlugin->descramble(
-            info.dstType != DescrambleInfo::kDestinationTypeVmPointer,
-            info.scramblingControl,
-            info.numSubSamples,
-            info.subSamples,
-            info.srcMem->pointer(),
-            info.srcOffset,
-            info.dstType == DescrambleInfo::kDestinationTypeVmPointer ?
-                    info.srcMem->pointer() : info.dstPtr,
-            info.dstOffset,
-            NULL);
-
-    return getBinderStatus(*result >= 0 ? OK : *result);
-}
-
-Status DescramblerImpl::release() {
-    ALOGV("release: mPlugin=%p", mPlugin);
-
-    if (mPlugin != NULL) {
-        delete mPlugin;
-        mPlugin = NULL;
-    }
-    return Status::ok();
-}
-
-} // namespace android
-
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 074489a..bc37557 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -30,6 +30,7 @@
 #include <media/DrmHal.h>
 #include <media/DrmSessionClientInterface.h>
 #include <media/DrmSessionManager.h>
+#include <media/PluginMetricsReporting.h>
 #include <media/drm/DrmAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AString.h>
@@ -194,7 +195,18 @@
      mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
 }
 
+void DrmHal::closeOpenSessions() {
+    if (mPlugin != NULL) {
+        for (size_t i = 0; i < mOpenSessions.size(); i++) {
+            mPlugin->closeSession(toHidlVec(mOpenSessions[i]));
+            DrmSessionManager::Instance()->removeSession(mOpenSessions[i]);
+        }
+    }
+    mOpenSessions.clear();
+}
+
 DrmHal::~DrmHal() {
+    closeOpenSessions();
     DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
 }
 
@@ -413,11 +425,12 @@
 
 status_t DrmHal::destroyPlugin() {
     Mutex::Autolock autoLock(mLock);
-
     if (mInitCheck != OK) {
         return mInitCheck;
     }
 
+    closeOpenSessions();
+    reportMetrics();
     setListener(NULL);
     mInitCheck = NO_INIT;
 
@@ -471,6 +484,7 @@
     if (err == OK) {
         DrmSessionManager::Instance()->addSession(getCallingPid(),
                 mDrmSessionClient, sessionId);
+        mOpenSessions.push(sessionId);
     }
     return err;
 }
@@ -486,7 +500,14 @@
     if (status.isOk()) {
         if (status == Status::OK) {
             DrmSessionManager::Instance()->removeSession(sessionId);
+            for (size_t i = 0; i < mOpenSessions.size(); i++) {
+                if (mOpenSessions[i] == sessionId) {
+                    mOpenSessions.removeAt(i);
+                    break;
+                }
+            }
         }
+        reportMetrics();
         return toStatusT(status);
     }
     return DEAD_OBJECT;
@@ -740,6 +761,12 @@
 
 status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
     Mutex::Autolock autoLock(mLock);
+    return getPropertyStringInternal(name, value);
+}
+
+status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
+    // This function is internal to the class and should only be called while
+    // mLock is already held.
 
     if (mInitCheck != OK) {
         return mInitCheck;
@@ -761,6 +788,12 @@
 
 status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
     Mutex::Autolock autoLock(mLock);
+    return getPropertyByteArrayInternal(name, value);
+}
+
+status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
+    // This function is internal to the class and should only be called while
+    // mLock is already held.
 
     if (mInitCheck != OK) {
         return mInitCheck;
@@ -975,7 +1008,7 @@
 void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
 {
     Mutex::Autolock autoLock(mLock);
-
+    closeOpenSessions();
     setListener(NULL);
     mInitCheck = NO_INIT;
 
@@ -997,4 +1030,20 @@
     }
 }
 
+void DrmHal::reportMetrics() const
+{
+    Vector<uint8_t> metrics;
+    String8 vendor;
+    String8 description;
+    if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
+            getPropertyStringInternal(String8("description"), description) == OK &&
+            getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
+        status_t res = android::reportDrmPluginMetrics(
+                metrics, vendor, description);
+        if (res != OK) {
+            ALOGE("Metrics were retrieved but could not be reported: %i", res);
+        }
+    }
+}
+
 }  // namespace android
diff --git a/drm/libmediadrm/IDrm.cpp b/drm/libmediadrm/IDrm.cpp
index 4e47112..8ff6e6a 100644
--- a/drm/libmediadrm/IDrm.cpp
+++ b/drm/libmediadrm/IDrm.cpp
@@ -561,8 +561,13 @@
 
 void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
     uint32_t size = data.readInt32();
-    vector.insertAt((size_t)0, size);
-    data.read(vector.editArray(), size);
+    if (vector.insertAt((size_t)0, size) < 0) {
+        vector.clear();
+    }
+    if (data.read(vector.editArray(), size) != NO_ERROR) {
+        vector.clear();
+        android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0);
+    }
 }
 
 void BnDrm::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
diff --git a/drm/libmediadrm/MediaCasDefs.cpp b/drm/libmediadrm/MediaCasDefs.cpp
deleted file mode 100644
index 9c2ba38..0000000
--- a/drm/libmediadrm/MediaCasDefs.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaCas"
-
-#include <media/MediaCasDefs.h>
-#include <utils/Log.h>
-#include <binder/IMemory.h>
-
-namespace android {
-namespace media {
-
-///////////////////////////////////////////////////////////////////////////////
-namespace MediaCas {
-
-status_t ParcelableCasData::readFromParcel(const Parcel* parcel) {
-    return parcel->readByteVector(this);
-}
-
-status_t ParcelableCasData::writeToParcel(Parcel* parcel) const  {
-    return parcel->writeByteVector(*this);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-status_t ParcelableCasPluginDescriptor::readFromParcel(const Parcel* /*parcel*/) {
-    ALOGE("CAPluginDescriptor::readFromParcel() shouldn't be called");
-    return INVALID_OPERATION;
-}
-
-status_t ParcelableCasPluginDescriptor::writeToParcel(Parcel* parcel) const {
-    status_t err = parcel->writeInt32(mCASystemId);
-    if (err != NO_ERROR) {
-        return err;
-    }
-    return parcel->writeString16(mName);
-}
-
-} // namespace MediaCas
-///////////////////////////////////////////////////////////////////////////////
-
-namespace MediaDescrambler {
-
-DescrambleInfo::DescrambleInfo() {}
-
-DescrambleInfo::~DescrambleInfo() {}
-
-status_t DescrambleInfo::readFromParcel(const Parcel* parcel) {
-    status_t err = parcel->readInt32((int32_t*)&dstType);
-    if (err != OK) {
-        return err;
-    }
-    if (dstType != kDestinationTypeNativeHandle
-            && dstType != kDestinationTypeVmPointer) {
-        return BAD_VALUE;
-    }
-
-    err = parcel->readInt32((int32_t*)&scramblingControl);
-    if (err != OK) {
-        return err;
-    }
-
-    err = parcel->readUint32((uint32_t*)&numSubSamples);
-    if (err != OK) {
-        return err;
-    }
-    if (numSubSamples > 0xffff) {
-        return BAD_VALUE;
-    }
-
-    subSamples = new DescramblerPlugin::SubSample[numSubSamples];
-    if (subSamples == NULL) {
-        return NO_MEMORY;
-    }
-
-    for (size_t i = 0; i < numSubSamples; i++) {
-        err = parcel->readUint32(&subSamples[i].mNumBytesOfClearData);
-        if (err != OK) {
-            return err;
-        }
-        err = parcel->readUint32(&subSamples[i].mNumBytesOfEncryptedData);
-        if (err != OK) {
-            return err;
-        }
-    }
-
-    srcMem = interface_cast<IMemory>(parcel->readStrongBinder());
-    if (srcMem == NULL) {
-        return BAD_VALUE;
-    }
-
-    err = parcel->readInt32(&srcOffset);
-    if (err != OK) {
-        return err;
-    }
-
-    native_handle_t *nativeHandle = NULL;
-    if (dstType == kDestinationTypeNativeHandle) {
-        nativeHandle = parcel->readNativeHandle();
-        dstPtr = static_cast<void *>(nativeHandle);
-    } else {
-        dstPtr = NULL;
-    }
-
-    err = parcel->readInt32(&dstOffset);
-    if (err != OK) {
-        return err;
-    }
-
-    return OK;
-}
-
-status_t DescrambleInfo::writeToParcel(Parcel* parcel) const {
-    if (dstType != kDestinationTypeNativeHandle
-            && dstType != kDestinationTypeVmPointer) {
-        return BAD_VALUE;
-    }
-
-    status_t err = parcel->writeInt32((int32_t)dstType);
-    if (err != OK) {
-        return err;
-    }
-
-    err = parcel->writeInt32(scramblingControl);
-    if (err != OK) {
-        return err;
-    }
-
-    err = parcel->writeUint32(numSubSamples);
-    if (err != OK) {
-        return err;
-    }
-
-    for (size_t i = 0; i < numSubSamples; i++) {
-        err = parcel->writeUint32(subSamples[i].mNumBytesOfClearData);
-        if (err != OK) {
-            return err;
-        }
-        err = parcel->writeUint32(subSamples[i].mNumBytesOfEncryptedData);
-        if (err != OK) {
-            return err;
-        }
-    }
-
-    err = parcel->writeStrongBinder(IInterface::asBinder(srcMem));
-    if (err != OK) {
-        return err;
-    }
-
-    err = parcel->writeInt32(srcOffset);
-    if (err != OK) {
-        return err;
-    }
-
-    if (dstType == kDestinationTypeNativeHandle) {
-        parcel->writeNativeHandle(static_cast<native_handle_t *>(dstPtr));
-    }
-
-    err = parcel->writeInt32(dstOffset);
-    if (err != OK) {
-        return err;
-    }
-
-    return OK;
-}
-
-} // namespace MediaDescrambler
-
-} // namespace media
-} // namespace android
-
diff --git a/drm/libmediadrm/PluginMetricsReporting.cpp b/drm/libmediadrm/PluginMetricsReporting.cpp
new file mode 100644
index 0000000..57ff5b8
--- /dev/null
+++ b/drm/libmediadrm/PluginMetricsReporting.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "PluginMetricsReporting"
+#include <utils/Log.h>
+
+#include <media/PluginMetricsReporting.h>
+
+#include <media/MediaAnalyticsItem.h>
+
+#include "protos/plugin_metrics.pb.h"
+
+namespace android {
+
+namespace {
+
+using android::drm_metrics::MetricsGroup;
+using android::drm_metrics::MetricsGroup_Metric;
+using android::drm_metrics::MetricsGroup_Metric_MetricValue;
+
+const char* const kParentAttribute = "/parent/external";
+
+status_t reportMetricsGroup(const MetricsGroup& metricsGroup,
+                            const String8& batchName,
+                            const int64_t* parentId) {
+    MediaAnalyticsItem analyticsItem(batchName.c_str());
+    analyticsItem.generateSessionID();
+    int64_t sessionId = analyticsItem.getSessionID();
+    if (parentId != NULL) {
+        analyticsItem.setInt64(kParentAttribute, *parentId);
+    }
+
+    // Report the package name.
+    if (metricsGroup.has_app_package_name()) {
+      AString app_package_name(metricsGroup.app_package_name().c_str(),
+                               metricsGroup.app_package_name().size());
+      analyticsItem.setPkgName(app_package_name);
+    }
+
+    for (int i = 0; i < metricsGroup.metric_size(); ++i) {
+        const MetricsGroup_Metric& metric = metricsGroup.metric(i);
+        if (!metric.has_name()) {
+            ALOGE("Metric with no name.");
+            return BAD_VALUE;
+        }
+
+        if (!metric.has_value()) {
+            ALOGE("Metric with no value.");
+            return BAD_VALUE;
+        }
+
+        const MetricsGroup_Metric_MetricValue& value = metric.value();
+        if (value.has_int_value()) {
+            analyticsItem.setInt64(metric.name().c_str(),
+                                   value.int_value());
+        } else if (value.has_double_value()) {
+            analyticsItem.setDouble(metric.name().c_str(),
+                                    value.double_value());
+        } else if (value.has_string_value()) {
+            analyticsItem.setCString(metric.name().c_str(),
+                                     value.string_value().c_str());
+        } else {
+            ALOGE("Metric Value with no actual value.");
+            return BAD_VALUE;
+        }
+    }
+
+    analyticsItem.setFinalized(true);
+    if (!analyticsItem.selfrecord()) {
+      // Note the cast to int is because we build on 32 and 64 bit.
+      // The cast prevents a peculiar printf problem where one format cannot
+      // satisfy both.
+      ALOGE("selfrecord() returned false. sessioId %d", (int) sessionId);
+    }
+
+    for (int i = 0; i < metricsGroup.metric_sub_group_size(); ++i) {
+        const MetricsGroup& subGroup = metricsGroup.metric_sub_group(i);
+        status_t res = reportMetricsGroup(subGroup, batchName, &sessionId);
+        if (res != OK) {
+            return res;
+        }
+    }
+
+    return OK;
+}
+
+String8 sanitize(const String8& input) {
+    // Filters the input string down to just alphanumeric characters.
+    String8 output;
+    for (size_t i = 0; i < input.size(); ++i) {
+        char candidate = input[i];
+        if ((candidate >= 'a' && candidate <= 'z') ||
+                (candidate >= 'A' && candidate <= 'Z') ||
+                (candidate >= '0' && candidate <= '9')) {
+            output.append(&candidate, 1);
+        }
+    }
+    return output;
+}
+
+}  // namespace
+
+status_t reportDrmPluginMetrics(const Vector<uint8_t>& serializedMetrics,
+                                const String8& vendor,
+                                const String8& description) {
+    MetricsGroup root_metrics_group;
+    if (!root_metrics_group.ParseFromArray(serializedMetrics.array(),
+                                           serializedMetrics.size())) {
+        ALOGE("Failure to parse.");
+        return BAD_VALUE;
+    }
+
+    String8 name = String8::format("drm.vendor.%s.%s",
+                                   sanitize(vendor).c_str(),
+                                   sanitize(description).c_str());
+
+    return reportMetricsGroup(root_metrics_group, name, NULL);
+}
+
+}  // namespace android
diff --git a/drm/libmediadrm/aidl/android/media/ICas.aidl b/drm/libmediadrm/aidl/android/media/ICas.aidl
deleted file mode 100644
index 9746593..0000000
--- a/drm/libmediadrm/aidl/android/media/ICas.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-package android.media;
-
-import android.media.MediaCas;
-
-/** @hide */
-interface ICas {
-    void setPrivateData(in byte[] pvtData);
-    byte[] openSession();
-    void closeSession(in byte[] sessionId);
-    void setSessionPrivateData(in byte[] sessionId, in byte[] pvtData);
-    void processEcm(in byte[] sessionId, in MediaCas.ParcelableCasData ecm);
-    void processEmm(in MediaCas.ParcelableCasData emm);
-    void sendEvent(int event, int arg, in @nullable byte[] eventData);
-    void provision(String provisionString);
-    void refreshEntitlements(int refreshType, in @nullable byte[] refreshData);
-    void release();
-}
\ No newline at end of file
diff --git a/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl b/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl
deleted file mode 100644
index 44f6825..0000000
--- a/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-package android.media;
-
-import android.media.IDescrambler;
-import android.media.ICas;
-import android.media.ICasListener;
-import android.media.MediaCas;
-
-/** @hide */
-interface IMediaCasService {
-    MediaCas.ParcelableCasPluginDescriptor[] enumeratePlugins();
-    boolean isSystemIdSupported(int CA_system_id);
-    ICas createPlugin(int CA_system_id, ICasListener listener);
-    boolean isDescramblerSupported(int CA_system_id);
-    IDescrambler createDescrambler(int CA_system_id);
-}
-
diff --git a/drm/libmediadrm/aidl/android/media/MediaCas.aidl b/drm/libmediadrm/aidl/android/media/MediaCas.aidl
deleted file mode 100644
index cb8d0c6..0000000
--- a/drm/libmediadrm/aidl/android/media/MediaCas.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-package android.media;
-
-/** @hide */
-parcelable MediaCas.ParcelableCasPluginDescriptor cpp_header "media/MediaCasDefs.h";
-
-/** @hide */
-parcelable MediaCas.ParcelableCasData cpp_header "media/MediaCasDefs.h";
\ No newline at end of file
diff --git a/drm/libmediadrm/aidl/android/media/MediaDescrambler.aidl b/drm/libmediadrm/aidl/android/media/MediaDescrambler.aidl
deleted file mode 100644
index e789244..0000000
--- a/drm/libmediadrm/aidl/android/media/MediaDescrambler.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-package android.media;
-
-/** @hide */
-parcelable MediaDescrambler.DescrambleInfo cpp_header "media/MediaCasDefs.h";
\ No newline at end of file
diff --git a/drm/libmediadrm/protos/plugin_metrics.proto b/drm/libmediadrm/protos/plugin_metrics.proto
new file mode 100644
index 0000000..7e3bcf5
--- /dev/null
+++ b/drm/libmediadrm/protos/plugin_metrics.proto
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto2";
+
+package android.drm_metrics;
+
+// need this if we are using libprotobuf-cpp-2.3.0-lite
+option optimize_for = LITE_RUNTIME;
+
+// The MetricsGroup is a collection of metric name/value pair instances
+// that can be serialized and provided to a caller.
+message MetricsGroup {
+  message Metric {
+    message MetricValue {
+      // Exactly one of the following values must be set.
+      optional int64 int_value = 1;
+      optional double double_value = 2;
+      optional string string_value = 3;
+    }
+
+    // The name of the metric. Must be valid UTF-8. Required.
+    optional string name = 1;
+
+    // The value of the metric. Required.
+    optional MetricValue value = 2;
+  }
+
+  // The list of name/value pairs of metrics.
+  repeated Metric metric = 1;
+
+  // Allow multiple sub groups of metrics.
+  repeated MetricsGroup metric_sub_group = 2;
+
+  // Name of the application package associated with the metrics.
+  optional string app_package_name = 3;
+}
diff --git a/drm/mediacas/plugins/clearkey/Android.mk b/drm/mediacas/plugins/clearkey/Android.mk
index 8fd866c..4b139a8 100644
--- a/drm/mediacas/plugins/clearkey/Android.mk
+++ b/drm/mediacas/plugins/clearkey/Android.mk
@@ -28,8 +28,7 @@
 
 LOCAL_MODULE := libclearkeycasplugin
 
-#TODO: move this back to /vendor/lib after conversion to treble
-#LOCAL_PROPRIETARY_MODULE := true
+LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := mediacas
 
 LOCAL_SHARED_LIBRARIES := \
@@ -39,6 +38,9 @@
     libstagefright_foundation \
     libprotobuf-cpp-lite \
 
+LOCAL_HEADER_LIBRARIES := \
+    media_plugin_headers
+
 LOCAL_STATIC_LIBRARIES := \
     libjsmn \
 
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
index 4ed5fce..e27631f 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
@@ -121,7 +121,7 @@
     sp<ClearKeyCasSession> session =
             ClearKeySessionLibrary::get()->findSession(sessionId);
     if (session == NULL) {
-        return ERROR_DRM_SESSION_NOT_OPENED;
+        return ERROR_CAS_SESSION_NOT_OPENED;
     }
 
     ClearKeySessionLibrary::get()->destroySession(sessionId);
@@ -135,7 +135,7 @@
     sp<ClearKeyCasSession> session =
             ClearKeySessionLibrary::get()->findSession(sessionId);
     if (session == NULL) {
-        return ERROR_DRM_SESSION_NOT_OPENED;
+        return ERROR_CAS_SESSION_NOT_OPENED;
     }
     return OK;
 }
@@ -146,7 +146,7 @@
     sp<ClearKeyCasSession> session =
             ClearKeySessionLibrary::get()->findSession(sessionId);
     if (session == NULL) {
-        return ERROR_DRM_SESSION_NOT_OPENED;
+        return ERROR_CAS_SESSION_NOT_OPENED;
     }
 
     Mutex::Autolock lock(mKeyFetcherLock);
@@ -293,7 +293,7 @@
 status_t ClearKeyCasSession::updateECM(
         KeyFetcher *keyFetcher, void *ecm, size_t size) {
     if (keyFetcher == nullptr) {
-        return ERROR_DRM_NOT_PROVISIONED;
+        return ERROR_CAS_NOT_PROVISIONED;
     }
 
     if (size < kEcmHeaderLength) {
@@ -344,7 +344,7 @@
         size_t numSubSamples, const DescramblerPlugin::SubSample *subSamples,
         const void *srcPtr, void *dstPtr, AString * /* errorDetailMsg */) {
     if (secure) {
-        return ERROR_DRM_CANNOT_HANDLE;
+        return ERROR_CAS_CANNOT_HANDLE;
     }
 
     AES_KEY contentKey;
@@ -356,7 +356,7 @@
         int32_t keyIndex = (scramblingControl & 1);
         if (!mKeyInfo[keyIndex].valid) {
             ALOGE("decrypt: key %d is invalid", keyIndex);
-            return ERROR_DRM_DECRYPT;
+            return ERROR_CAS_DECRYPT;
         }
         contentKey = mKeyInfo[keyIndex].contentKey;
     }
@@ -420,7 +420,7 @@
 
     if (session == NULL) {
         ALOGE("ClearKeyDescramblerPlugin: session not found");
-        return ERROR_DRM_SESSION_NOT_OPENED;
+        return ERROR_CAS_SESSION_NOT_OPENED;
     }
 
     mCASSession = session;
@@ -446,7 +446,7 @@
 
     if (mCASSession == NULL) {
         ALOGE("Uninitialized CAS session!");
-        return ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED;
+        return ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED;
     }
 
     return mCASSession->decrypt(
diff --git a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
index 9cd77e9..6e1004c 100644
--- a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
+++ b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
@@ -48,24 +48,24 @@
  * Extract a clear key asset from a JSON string.
  *
  * Returns OK if a clear key asset is extracted successfully,
- * or ERROR_DRM_NO_LICENSE if the string doesn't contain a valid
+ * or ERROR_CAS_NO_LICENSE if the string doesn't contain a valid
  * clear key asset.
  */
 status_t JsonAssetLoader::extractAssetFromString(
         const String8& jsonAssetString, Asset *asset) {
     if (!parseJsonAssetString(jsonAssetString, &mJsonObjects)) {
-        return ERROR_DRM_NO_LICENSE;
+        return ERROR_CAS_NO_LICENSE;
     }
 
     if (mJsonObjects.size() < 1) {
-        return ERROR_DRM_NO_LICENSE;
+        return ERROR_CAS_NO_LICENSE;
     }
 
     if (!parseJsonObject(mJsonObjects[0], &mTokens))
-        return ERROR_DRM_NO_LICENSE;
+        return ERROR_CAS_NO_LICENSE;
 
     if (!findKey(mJsonObjects[0], asset)) {
-        return ERROR_DRM_NO_LICENSE;
+        return ERROR_CAS_NO_LICENSE;
     }
     return OK;
 }
diff --git a/drm/mediacas/plugins/clearkey/ecm_generator.h b/drm/mediacas/plugins/clearkey/ecm_generator.h
index 2ef06c4..5fbdea5 100644
--- a/drm/mediacas/plugins/clearkey/ecm_generator.h
+++ b/drm/mediacas/plugins/clearkey/ecm_generator.h
@@ -29,7 +29,7 @@
 namespace android {
 namespace clearkeycas {
 enum {
-    CLEARKEY_STATUS_BASE = ERROR_DRM_VENDOR_MAX,
+    CLEARKEY_STATUS_BASE = ERROR_CAS_VENDOR_MAX,
     CLEARKEY_STATUS_INVALIDASSETID = CLEARKEY_STATUS_BASE - 1,
     CLEARKEY_STATUS_INVALIDSYSTEMID = CLEARKEY_STATUS_BASE - 2,
     CLEARKEY_STATUS_INVALID_PARAMETER = CLEARKEY_STATUS_BASE - 3,
diff --git a/drm/mediacas/plugins/clearkey/tests/Android.mk b/drm/mediacas/plugins/clearkey/tests/Android.mk
index cbf7be7..e1545af 100644
--- a/drm/mediacas/plugins/clearkey/tests/Android.mk
+++ b/drm/mediacas/plugins/clearkey/tests/Android.mk
@@ -21,12 +21,13 @@
     ClearKeyFetcherTest.cpp
 
 LOCAL_MODULE := ClearKeyFetcherTest
+LOCAL_VENDOR_MODULE := true
 
 # LOCAL_LDFLAGS is needed here for the test to use the plugin, because
 # the plugin is not in standard library search path. Without this .so
 # loading fails at run-time (linking is okay).
 LOCAL_LDFLAGS := \
-    -Wl,--rpath,\$${ORIGIN}/../../../system/lib/mediacas -Wl,--enable-new-dtags
+    -Wl,--rpath,\$${ORIGIN}/../../../system/vendor/lib/mediacas -Wl,--enable-new-dtags
 
 LOCAL_SHARED_LIBRARIES := \
     libutils libclearkeycasplugin libstagefright_foundation libprotobuf-cpp-lite liblog
diff --git a/drm/mediacas/plugins/mock/Android.mk b/drm/mediacas/plugins/mock/Android.mk
index a97fac6..a1d61da 100644
--- a/drm/mediacas/plugins/mock/Android.mk
+++ b/drm/mediacas/plugins/mock/Android.mk
@@ -28,6 +28,8 @@
 LOCAL_SHARED_LIBRARIES := \
     libutils liblog
 
+LOCAL_HEADER_LIBRARIES := media_plugin_headers
+
 LOCAL_C_INCLUDES += \
     $(TOP)/frameworks/av/include \
     $(TOP)/frameworks/native/include/media \
diff --git a/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp b/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp
index ed050f7..0259a42 100644
--- a/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp
+++ b/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp
@@ -21,12 +21,19 @@
 namespace clearkeydrm {
 
 bool isClearKeyUUID(const uint8_t uuid[16]) {
-    static const uint8_t kClearKeyUUID[16] = {
+    static const uint8_t kCommonPsshBoxUUID[16] = {
         0x10,0x77,0xEF,0xEC,0xC0,0xB2,0x4D,0x02,
         0xAC,0xE3,0x3C,0x1E,0x52,0xE2,0xFB,0x4B
     };
 
-    return !memcmp(uuid, kClearKeyUUID, sizeof(kClearKeyUUID));
+    // To be used in mpd to specify drm scheme for players
+    static const uint8_t kClearKeyUUID[16] = {
+        0xE2,0x71,0x9D,0x58,0xA9,0x85,0xB3,0xC9,
+        0x78,0x1A,0xB0,0x30,0xAF,0x78,0xD3,0x0E
+    };
+
+    return !memcmp(uuid, kCommonPsshBoxUUID, sizeof(kCommonPsshBoxUUID)) ||
+           !memcmp(uuid, kClearKeyUUID, sizeof(kClearKeyUUID));
 }
 
 } // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
index 5fdac5c..ec07d87 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
@@ -25,10 +25,28 @@
 
 #include "Session.h"
 
+namespace {
+const android::String8 kStreaming("Streaming");
+const android::String8 kOffline("Offline");
+const android::String8 kTrue("True");
+
+const android::String8 kQueryKeyLicenseType("LicenseType");
+    // Value: "Streaming" or "Offline"
+const android::String8 kQueryKeyPlayAllowed("PlayAllowed");
+    // Value: "True" or "False"
+const android::String8 kQueryKeyRenewAllowed("RenewAllowed");
+    // Value: "True" or "False"
+};
+
 namespace clearkeydrm {
 
 using android::sp;
 
+DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
+        : mSessionLibrary(sessionLibrary) {
+    mPlayPolicy.clear();
+}
+
 status_t DrmPlugin::openSession(Vector<uint8_t>& sessionId) {
     sp<Session> session = mSessionLibrary->createSession();
     sessionId = session->sessionId();
@@ -60,18 +78,28 @@
     if (scope.size() == 0) {
         return android::BAD_VALUE;
     }
+
     if (keyType != kKeyType_Streaming) {
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
+
     *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
     defaultUrl.clear();
     sp<Session> session = mSessionLibrary->findSession(scope);
     if (!session.get()) {
         return android::ERROR_DRM_SESSION_NOT_OPENED;
     }
+
     return session->getKeyRequest(initData, mimeType, &request);
 }
 
+void DrmPlugin::setPlayPolicy() {
+    mPlayPolicy.clear();
+    mPlayPolicy.add(kQueryKeyLicenseType, kStreaming);
+    mPlayPolicy.add(kQueryKeyPlayAllowed, kTrue);
+    mPlayPolicy.add(kQueryKeyRenewAllowed, kTrue);
+}
+
 status_t DrmPlugin::provideKeyResponse(
         const Vector<uint8_t>& scope,
         const Vector<uint8_t>& response,
@@ -83,6 +111,8 @@
     if (!session.get()) {
         return android::ERROR_DRM_SESSION_NOT_OPENED;
     }
+
+    setPlayPolicy();
     status_t res = session->provideKeyResponse(response);
     if (res == android::OK) {
         // This is for testing AMediaDrm_setOnEventListener only.
@@ -111,4 +141,18 @@
     return android::OK;
 }
 
+status_t DrmPlugin::queryKeyStatus(
+        const Vector<uint8_t>& sessionId,
+        KeyedVector<String8, String8>& infoMap) const {
+
+    if (sessionId.size() == 0) {
+        return android::BAD_VALUE;
+    }
+
+    infoMap.clear();
+    for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
+        infoMap.add(mPlayPolicy.keyAt(i), mPlayPolicy.valueAt(i));
+    }
+    return android::OK;
+}
 }  // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
index 58421b9..f37a706 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
@@ -39,8 +39,8 @@
 
 class DrmPlugin : public android::DrmPlugin {
 public:
-    explicit DrmPlugin(SessionLibrary* sessionLibrary)
-            : mSessionLibrary(sessionLibrary) {}
+    explicit DrmPlugin(SessionLibrary* sessionLibrary);
+
     virtual ~DrmPlugin() {}
 
     virtual status_t openSession(Vector<uint8_t>& sessionId);
@@ -81,13 +81,7 @@
 
     virtual status_t queryKeyStatus(
             const Vector<uint8_t>& sessionId,
-            KeyedVector<String8, String8>& infoMap) const {
-        if (sessionId.size() == 0) {
-            return android::BAD_VALUE;
-        }
-        UNUSED(infoMap);
-        return android::ERROR_DRM_CANNOT_HANDLE;
-    }
+            KeyedVector<String8, String8>& infoMap) const;
 
     virtual status_t getProvisionRequest(
             const String8& cert_type,
@@ -248,9 +242,12 @@
     }
 
 private:
-    DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin);
+    void setPlayPolicy();
 
+    android::KeyedVector<android::String8, android::String8> mPlayPolicy;
     SessionLibrary* mSessionLibrary;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin);
 };
 
 } // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
index 6a4f8d5..caff393 100644
--- a/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
@@ -136,7 +136,7 @@
     AString encodedId;
     for (size_t i = 0; i < keyIds.size(); ++i) {
         encodedId.clear();
-        android::encodeBase64(keyIds[i], kKeyIdSize, &encodedId);
+        android::encodeBase64Url(keyIds[i], kKeyIdSize, &encodedId);
         if (i != 0) {
             request.append(",");
         }
diff --git a/drm/mediadrm/plugins/clearkey/tests/Android.bp b/drm/mediadrm/plugins/clearkey/tests/Android.bp
index 93feb80..ea17bbb 100644
--- a/drm/mediadrm/plugins/clearkey/tests/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/tests/Android.bp
@@ -36,4 +36,5 @@
         "libstagefright_foundation",
         "libutils",
     ],
+    header_libs: ["media_plugin_headers"],
 }
diff --git a/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp b/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
index 84ed242..8c49656 100644
--- a/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
+++ b/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
@@ -59,7 +59,7 @@
                   (size_t)requestString.find(kRequestSuffix));
         for (size_t i = 0; i < expectedKeys.size(); ++i) {
             AString encodedIdAString;
-            android::encodeBase64(expectedKeys[i], kKeyIdSize,
+            android::encodeBase64Url(expectedKeys[i], kKeyIdSize,
                                   &encodedIdAString);
             String8 encodedId(encodedIdAString.c_str());
             encodedId.removeAll(kBase64Padding);
@@ -231,5 +231,4 @@
 
     attemptParseExpectingFailure(initData, kCencMimeType);
 }
-
 }  // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp b/drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp
index c3b0d84..d9f3ea6 100644
--- a/drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp
+++ b/drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp
@@ -284,14 +284,14 @@
                 "\"keys\":"
                     "[{"
                         "\"kid\":\"Y2xlYXJrZXlrZXlpZDAx\""
-                        "\"k\":\"SGVsbG8gRnJpZW5kISE\""
+                        "\"k\":\"SGVsbG8gRnJpZW5kICE-Pw\""
                         "\"kty\":\"oct\""
                         "\"alg\":\"A128KW1\""
                     "}"
                     "{"
                         "\"kty\":\"oct\""
                         "\"alg\":\"A128KW2\""
-                        "\"k\":\"SGVsbG8gRnJpZW5kIQ\""
+                        "\"k\":\"SGVsbG8gRnJpZW5kICE_\""
                         "\"kid\":\"Y2xlYXJrZXlrZXlpZDAy\""
                     "}"
                     "{"
@@ -303,7 +303,7 @@
                     "{"
                         "\"alg\":\"A128KW3\""
                         "\"kid\":\"Y2xlYXJrZXlrZXlpZDAz\""
-                        "\"k\":\"R29vZCBkYXkh\""
+                        "\"k\":\"SGVsbG8gPz4-IEZyaWVuZCA_Pg\""
                         "\"kty\":\"oct\""
                     "}]"
             "}");
@@ -313,8 +313,8 @@
     EXPECT_TRUE(keys.size() == 3);
 
     const String8 clearKeys[] =
-            { String8("Hello Friend!!"), String8("Hello Friend!"),
-              String8("Good day!") };
+            { String8("Hello Friend !>?"), String8("Hello Friend !?"),
+              String8("Hello ?>> Friend ?>") };
     verifyKeys(keys, clearKeys);
 }
 
diff --git a/drm/mediadrm/plugins/mock/Android.bp b/drm/mediadrm/plugins/mock/Android.bp
index f0a1ddd..dd2ad7b 100644
--- a/drm/mediadrm/plugins/mock/Android.bp
+++ b/drm/mediadrm/plugins/mock/Android.bp
@@ -22,6 +22,8 @@
     vendor: true,
     relative_install_path: "mediadrm",
 
+    header_libs: ["media_plugin_headers"],
+
     shared_libs: [
         "libutils",
         "liblog",
diff --git a/include/OWNERS b/include/OWNERS
index 0ec7529..3cb6d9c 100644
--- a/include/OWNERS
+++ b/include/OWNERS
@@ -1,5 +1,6 @@
 elaurent@google.com
 gkasten@android.com
 hunga@google.com
+jtinker@google.com
 lajos@google.com
 marcone@google.com
diff --git a/include/media/AudioClient.h b/include/media/AudioClient.h
deleted file mode 120000
index a0530e4..0000000
--- a/include/media/AudioClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioClient.h
\ No newline at end of file
diff --git a/drm/libmediadrm/aidl/android/media/IDescrambler.aidl b/include/media/AudioClient.h
similarity index 61%
copy from drm/libmediadrm/aidl/android/media/IDescrambler.aidl
copy to include/media/AudioClient.h
index fdf99eb..9efd76d 100644
--- a/drm/libmediadrm/aidl/android/media/IDescrambler.aidl
+++ b/include/media/AudioClient.h
@@ -14,14 +14,25 @@
  * limitations under the License.
  */
 
-package android.media;
 
-import android.media.MediaDescrambler;
+#ifndef ANDROID_AUDIO_CLIENT_H
+#define ANDROID_AUDIO_CLIENT_H
 
-/** @hide */
-interface IDescrambler {
-    void setMediaCasSession(in byte[] sessionId);
-    boolean requiresSecureDecoderComponent(String mime);
-    int descramble(in MediaDescrambler.DescrambleInfo descrambleInfo);
-    void release();
-}
\ No newline at end of file
+#include <system/audio.h>
+#include <utils/String16.h>
+
+namespace android {
+
+class AudioClient {
+ public:
+    AudioClient() :
+        clientUid(-1), clientPid(-1), packageName("") {}
+
+    uid_t clientUid;
+    pid_t clientPid;
+    String16 packageName;
+};
+
+}; // namespace android
+
+#endif  // ANDROID_AUDIO_CLIENT_H
diff --git a/include/media/AudioResampler.h b/include/media/AudioResampler.h
index 50e12f4..771f1b8 120000
--- a/include/media/AudioResampler.h
+++ b/include/media/AudioResampler.h
@@ -1 +1 @@
-../../media/libaudioprocessing/include/AudioResampler.h
\ No newline at end of file
+../../media/libaudioprocessing/include/media/AudioResampler.h
\ No newline at end of file
diff --git a/include/media/AudioResamplerPublic.h b/include/media/AudioResamplerPublic.h
index 309c23d..ce30a78 120000
--- a/include/media/AudioResamplerPublic.h
+++ b/include/media/AudioResamplerPublic.h
@@ -1 +1 @@
-../../media/libaudioprocessing/include/AudioResamplerPublic.h
\ No newline at end of file
+../../media/libaudioprocessing/include/media/AudioResamplerPublic.h
\ No newline at end of file
diff --git a/include/media/CasImpl.h b/include/media/CasImpl.h
deleted file mode 100644
index 726f1ce..0000000
--- a/include/media/CasImpl.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CAS_IMPL_H_
-#define CAS_IMPL_H_
-
-#include <media/stagefright/foundation/ABase.h>
-#include <android/media/BnCas.h>
-
-namespace android {
-namespace media {
-class ICasListener;
-}
-using namespace media;
-using namespace MediaCas;
-using binder::Status;
-struct CasPlugin;
-class SharedLibrary;
-
-class CasImpl : public BnCas {
-public:
-    CasImpl(const sp<ICasListener> &listener);
-    virtual ~CasImpl();
-
-    static void OnEvent(
-            void *appData,
-            int32_t event,
-            int32_t arg,
-            uint8_t *data,
-            size_t size);
-
-    void init(const sp<SharedLibrary>& library, CasPlugin *plugin);
-    void onEvent(
-            int32_t event,
-            int32_t arg,
-            uint8_t *data,
-            size_t size);
-
-    // ICas inherits
-
-    virtual Status setPrivateData(
-            const CasData& pvtData) override;
-
-    virtual Status openSession(CasSessionId* _aidl_return) override;
-
-    virtual Status closeSession(const CasSessionId& sessionId) override;
-
-    virtual Status setSessionPrivateData(
-            const CasSessionId& sessionId,
-            const CasData& pvtData) override;
-
-    virtual Status processEcm(
-            const CasSessionId& sessionId, const ParcelableCasData& ecm) override;
-
-    virtual Status processEmm(const ParcelableCasData& emm) override;
-
-    virtual Status sendEvent(
-            int32_t event, int32_t arg, const ::std::unique_ptr<CasData> &eventData) override;
-
-    virtual Status provision(const String16& provisionString) override;
-
-    virtual Status refreshEntitlements(
-            int32_t refreshType, const ::std::unique_ptr<CasData> &refreshData) override;
-
-    virtual Status release() override;
-
-private:
-    struct PluginHolder;
-    sp<SharedLibrary> mLibrary;
-    sp<PluginHolder> mPluginHolder;
-    sp<ICasListener> mListener;
-
-    DISALLOW_EVIL_CONSTRUCTORS(CasImpl);
-};
-
-} // namespace android
-
-#endif // CAS_IMPL_H_
diff --git a/include/media/DescramblerImpl.h b/include/media/DescramblerImpl.h
deleted file mode 100644
index 9f212ac..0000000
--- a/include/media/DescramblerImpl.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef DESCRAMBLER_IMPL_H_
-#define DESCRAMBLER_IMPL_H_
-
-#include <media/stagefright/foundation/ABase.h>
-#include <android/media/BnDescrambler.h>
-
-namespace android {
-using namespace media;
-using namespace MediaDescrambler;
-using binder::Status;
-struct DescramblerPlugin;
-class SharedLibrary;
-
-class DescramblerImpl : public BnDescrambler {
-public:
-    DescramblerImpl(const sp<SharedLibrary>& library, DescramblerPlugin *plugin);
-    virtual ~DescramblerImpl();
-
-    virtual Status setMediaCasSession(
-            const CasSessionId& sessionId) override;
-
-    virtual Status requiresSecureDecoderComponent(
-            const String16& mime, bool *result) override;
-
-    virtual Status descramble(
-            const DescrambleInfo& descrambleInfo, int32_t *result) override;
-
-    virtual Status release() override;
-
-private:
-    sp<SharedLibrary> mLibrary;
-    DescramblerPlugin *mPlugin;
-
-    DISALLOW_EVIL_CONSTRUCTORS(DescramblerImpl);
-};
-
-} // namespace android
-
-#endif // DESCRAMBLER_IMPL_H_
diff --git a/include/media/MediaCasDefs.h b/include/media/MediaCasDefs.h
deleted file mode 100644
index 8c5a967..0000000
--- a/include/media/MediaCasDefs.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MEDIA_CAS_DEFS_H_
-#define MEDIA_CAS_DEFS_H_
-
-#include <binder/Parcel.h>
-#include <media/cas/CasAPI.h>
-#include <media/cas/DescramblerAPI.h>
-#include <media/stagefright/foundation/ABase.h>
-
-namespace android {
-class IMemory;
-namespace media {
-
-namespace MediaCas {
-class ParcelableCasData : public CasData,
-                          public Parcelable {
-public:
-    ParcelableCasData() {}
-    ParcelableCasData(const uint8_t *data, size_t size) :
-        CasData(data, data + size) {}
-    virtual ~ParcelableCasData() {}
-    status_t readFromParcel(const Parcel* parcel) override;
-    status_t writeToParcel(Parcel* parcel) const override;
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(ParcelableCasData);
-};
-
-class ParcelableCasPluginDescriptor : public Parcelable {
-public:
-    ParcelableCasPluginDescriptor(int32_t CA_system_id, const char *name)
-        : mCASystemId(CA_system_id), mName(name) {}
-
-    ParcelableCasPluginDescriptor() : mCASystemId(0) {}
-
-    ParcelableCasPluginDescriptor(ParcelableCasPluginDescriptor&& desc) = default;
-
-    virtual ~ParcelableCasPluginDescriptor() {}
-
-    status_t readFromParcel(const Parcel* parcel) override;
-    status_t writeToParcel(Parcel* parcel) const override;
-
-private:
-    int32_t mCASystemId;
-    String16 mName;
-    DISALLOW_EVIL_CONSTRUCTORS(ParcelableCasPluginDescriptor);
-};
-}
-
-namespace MediaDescrambler {
-class DescrambleInfo : public Parcelable {
-public:
-    enum DestinationType {
-        kDestinationTypeVmPointer,    // non-secure
-        kDestinationTypeNativeHandle  // secure
-    };
-
-    DestinationType dstType;
-    DescramblerPlugin::ScramblingControl scramblingControl;
-    size_t numSubSamples;
-    DescramblerPlugin::SubSample *subSamples;
-    sp<IMemory> srcMem;
-    int32_t srcOffset;
-    void *dstPtr;
-    int32_t dstOffset;
-
-    DescrambleInfo();
-    virtual ~DescrambleInfo();
-    status_t readFromParcel(const Parcel* parcel) override;
-    status_t writeToParcel(Parcel* parcel) const override;
-
-private:
-
-    DISALLOW_EVIL_CONSTRUCTORS(DescrambleInfo);
-};
-}
-
-} // namespace media
-} // namespace android
-
-
-#endif // MEDIA_CAS_DEFS_H_
diff --git a/include/media/PluginMetricsReporting.h b/include/media/PluginMetricsReporting.h
new file mode 120000
index 0000000..7d9a7a0
--- /dev/null
+++ b/include/media/PluginMetricsReporting.h
@@ -0,0 +1 @@
+../../media/libmedia/include/media/PluginMetricsReporting.h
\ No newline at end of file
diff --git a/include/media/audiohal b/include/media/audiohal
index 37e2c39..f400582 120000
--- a/include/media/audiohal
+++ b/include/media/audiohal
@@ -1 +1 @@
-../../media/libaudiohal/include
\ No newline at end of file
+../../media/libaudiohal/include/media/audiohal/
\ No newline at end of file
diff --git a/include/media/nbaio b/include/media/nbaio
deleted file mode 120000
index 67d0ba6..0000000
--- a/include/media/nbaio
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libnbaio/include
\ No newline at end of file
diff --git a/include/media/nbaio/AudioBufferProviderSource.h b/include/media/nbaio/AudioBufferProviderSource.h
new file mode 120000
index 0000000..55841e7
--- /dev/null
+++ b/include/media/nbaio/AudioBufferProviderSource.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/AudioBufferProviderSource.h
\ No newline at end of file
diff --git a/include/media/nbaio/AudioStreamInSource.h b/include/media/nbaio/AudioStreamInSource.h
new file mode 120000
index 0000000..f5bcc76
--- /dev/null
+++ b/include/media/nbaio/AudioStreamInSource.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/AudioStreamInSource.h
\ No newline at end of file
diff --git a/include/media/nbaio/AudioStreamOutSink.h b/include/media/nbaio/AudioStreamOutSink.h
new file mode 120000
index 0000000..43bfac5
--- /dev/null
+++ b/include/media/nbaio/AudioStreamOutSink.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/AudioStreamOutSink.h
\ No newline at end of file
diff --git a/include/media/nbaio/LibsndfileSink.h b/include/media/nbaio/LibsndfileSink.h
new file mode 120000
index 0000000..8a13b6c
--- /dev/null
+++ b/include/media/nbaio/LibsndfileSink.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/LibsndfileSink.h
\ No newline at end of file
diff --git a/include/media/nbaio/LibsndfileSource.h b/include/media/nbaio/LibsndfileSource.h
new file mode 120000
index 0000000..2750fde
--- /dev/null
+++ b/include/media/nbaio/LibsndfileSource.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/LibsndfileSource.h
\ No newline at end of file
diff --git a/include/media/nbaio/MonoPipe.h b/include/media/nbaio/MonoPipe.h
new file mode 120000
index 0000000..4ea43be
--- /dev/null
+++ b/include/media/nbaio/MonoPipe.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include_mono/media/nbaio/MonoPipe.h
\ No newline at end of file
diff --git a/include/media/nbaio/MonoPipeReader.h b/include/media/nbaio/MonoPipeReader.h
new file mode 120000
index 0000000..30f426c
--- /dev/null
+++ b/include/media/nbaio/MonoPipeReader.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include_mono/media/nbaio/MonoPipeReader.h
\ No newline at end of file
diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h
new file mode 120000
index 0000000..ff6a151
--- /dev/null
+++ b/include/media/nbaio/NBAIO.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include_mono/media/nbaio/NBAIO.h
\ No newline at end of file
diff --git a/include/media/nbaio/NBLog.h b/include/media/nbaio/NBLog.h
new file mode 120000
index 0000000..c35401e
--- /dev/null
+++ b/include/media/nbaio/NBLog.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/NBLog.h
\ No newline at end of file
diff --git a/include/media/nbaio/PerformanceAnalysis.h b/include/media/nbaio/PerformanceAnalysis.h
new file mode 120000
index 0000000..7acfc90
--- /dev/null
+++ b/include/media/nbaio/PerformanceAnalysis.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/PerformanceAnalysis.h
\ No newline at end of file
diff --git a/include/media/nbaio/Pipe.h b/include/media/nbaio/Pipe.h
new file mode 120000
index 0000000..a4bbbc9
--- /dev/null
+++ b/include/media/nbaio/Pipe.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/Pipe.h
\ No newline at end of file
diff --git a/include/media/nbaio/PipeReader.h b/include/media/nbaio/PipeReader.h
new file mode 120000
index 0000000..64b21cf
--- /dev/null
+++ b/include/media/nbaio/PipeReader.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/PipeReader.h
\ No newline at end of file
diff --git a/include/media/nbaio/SourceAudioBufferProvider.h b/include/media/nbaio/SourceAudioBufferProvider.h
new file mode 120000
index 0000000..74a3b06
--- /dev/null
+++ b/include/media/nbaio/SourceAudioBufferProvider.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include/media/nbaio/SourceAudioBufferProvider.h
\ No newline at end of file
diff --git a/include/media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h b/include/media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h
deleted file mode 100644
index b324cd8..0000000
--- a/include/media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MEDIA_CODECS_XML_PARSER_H_
-
-#define MEDIA_CODECS_XML_PARSER_H_
-
-#include <map>
-#include <vector>
-
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/foundation/AString.h>
-
-#include <sys/types.h>
-#include <utils/Errors.h>
-#include <utils/Vector.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-struct AMessage;
-
-// Quirk still supported, even though deprecated
-enum Quirks {
-    kRequiresAllocateBufferOnInputPorts   = 1,
-    kRequiresAllocateBufferOnOutputPorts  = 2,
-
-    kQuirksMask = kRequiresAllocateBufferOnInputPorts
-                | kRequiresAllocateBufferOnOutputPorts,
-};
-
-// Lightweight struct for querying components.
-struct TypeInfo {
-    AString mName;
-    std::map<AString, AString> mStringFeatures;
-    std::map<AString, bool> mBoolFeatures;
-    std::map<AString, AString> mDetails;
-};
-
-struct ProfileLevel {
-    uint32_t mProfile;
-    uint32_t mLevel;
-};
-
-struct CodecInfo {
-    std::vector<TypeInfo> mTypes;
-    std::vector<ProfileLevel> mProfileLevels;
-    std::vector<uint32_t> mColorFormats;
-    uint32_t mFlags;
-    bool mIsEncoder;
-};
-
-class MediaCodecsXmlParser {
-public:
-    MediaCodecsXmlParser();
-    ~MediaCodecsXmlParser();
-
-    void getGlobalSettings(std::map<AString, AString> *settings) const;
-
-    status_t getCodecInfo(const char *name, CodecInfo *info) const;
-
-    status_t getQuirks(const char *name, std::vector<AString> *quirks) const;
-
-private:
-    enum Section {
-        SECTION_TOPLEVEL,
-        SECTION_SETTINGS,
-        SECTION_DECODERS,
-        SECTION_DECODER,
-        SECTION_DECODER_TYPE,
-        SECTION_ENCODERS,
-        SECTION_ENCODER,
-        SECTION_ENCODER_TYPE,
-        SECTION_INCLUDE,
-    };
-
-    status_t mInitCheck;
-    Section mCurrentSection;
-    bool mUpdate;
-    Vector<Section> mPastSections;
-    int32_t mDepth;
-    AString mHrefBase;
-
-    std::map<AString, AString> mGlobalSettings;
-
-    // name -> CodecInfo
-    std::map<AString, CodecInfo> mCodecInfos;
-    std::map<AString, std::vector<AString>> mQuirks;
-    AString mCurrentName;
-    std::vector<TypeInfo>::iterator mCurrentType;
-
-    status_t initCheck() const;
-    void parseTopLevelXMLFile(const char *path, bool ignore_errors = false);
-
-    void parseXMLFile(const char *path);
-
-    static void StartElementHandlerWrapper(
-            void *me, const char *name, const char **attrs);
-
-    static void EndElementHandlerWrapper(void *me, const char *name);
-
-    void startElementHandler(const char *name, const char **attrs);
-    void endElementHandler(const char *name);
-
-    status_t includeXMLFile(const char **attrs);
-    status_t addSettingFromAttributes(const char **attrs);
-    status_t addMediaCodecFromAttributes(bool encoder, const char **attrs);
-    void addMediaCodec(bool encoder, const char *name, const char *type = NULL);
-
-    status_t addQuirk(const char **attrs);
-    status_t addTypeFromAttributes(const char **attrs, bool encoder);
-    status_t addLimit(const char **attrs);
-    status_t addFeature(const char **attrs);
-    void addType(const char *name);
-
-    DISALLOW_EVIL_CONSTRUCTORS(MediaCodecsXmlParser);
-};
-
-}  // namespace android
-
-#endif  // MEDIA_CODECS_XML_PARSER_H_
-
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 9da5ef3..ff440bc 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -568,6 +568,9 @@
     // which may include non-contiguous frames
     virtual size_t      framesReady();
 
+    // Safe frames ready query used by dump() - this has no side effects.
+    virtual size_t      framesReadySafe() const;
+
     // Currently AudioFlinger will call framesReady() for a fast track from two threads:
     // FastMixer thread, and normal mixer thread.  This is dangerous, as the proxy is intended
     // to be called from at most one thread of server, and one thread of client.
@@ -620,6 +623,7 @@
 
 public:
     virtual size_t      framesReady();
+    virtual size_t      framesReadySafe() const override;
     virtual void        framesReadyIsCalledByMultipleThreads();
     virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush);
     virtual void        releaseBuffer(Buffer* buffer);
diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h
index 51050cd..a9d4dd1 100644
--- a/include/private/media/VideoFrame.h
+++ b/include/private/media/VideoFrame.h
@@ -30,14 +30,41 @@
 class VideoFrame
 {
 public:
-    VideoFrame(): mWidth(0), mHeight(0), mDisplayWidth(0), mDisplayHeight(0), mSize(0),
-            mRotationAngle(0), mData(0) {}
+    // Construct a VideoFrame object with the specified parameters,
+    // will allocate frame buffer if |allocate| is set to true, will
+    // allocate buffer to hold ICC data if |iccData| and |iccSize|
+    // indicate its presence.
+    VideoFrame(uint32_t width, uint32_t height,
+            uint32_t displayWidth, uint32_t displayHeight,
+            uint32_t angle, uint32_t bpp, bool allocate,
+            const void *iccData, size_t iccSize):
+        mWidth(width), mHeight(height),
+        mDisplayWidth(displayWidth), mDisplayHeight(displayHeight),
+        mRotationAngle(angle), mBytesPerPixel(bpp), mRowBytes(bpp * width),
+        mSize(0), mIccSize(0), mReserved(0), mData(0), mIccData(0) {
+        if (allocate) {
+            mSize = mRowBytes * mHeight;
+            mData = new uint8_t[mSize];
+            if (mData == NULL) {
+                mSize = 0;
+            }
+        }
 
+        if (iccData != NULL && iccSize > 0) {
+            mIccSize = iccSize;
+            mIccData = new uint8_t[iccSize];
+            if (mIccData != NULL) {
+                memcpy(mIccData, iccData, iccSize);
+            } else {
+                mIccSize = 0;
+            }
+        }
+    }
+
+    // Deep copy of both the information fields and the frame data
     VideoFrame(const VideoFrame& copy) {
-        mWidth = copy.mWidth;
-        mHeight = copy.mHeight;
-        mDisplayWidth = copy.mDisplayWidth;
-        mDisplayHeight = copy.mDisplayHeight;
+        copyInfoOnly(copy);
+
         mSize = copy.mSize;
         mData = NULL;  // initialize it first
         if (mSize > 0 && copy.mData != NULL) {
@@ -48,26 +75,99 @@
                 mSize = 0;
             }
         }
-        mRotationAngle = copy.mRotationAngle;
+
+        mIccSize = copy.mIccSize;
+        mIccData = NULL;  // initialize it first
+        if (mIccSize > 0 && copy.mIccData != NULL) {
+            mIccData = new uint8_t[mIccSize];
+            if (mIccData != NULL) {
+                memcpy(mIccData, copy.mIccData, mIccSize);
+            } else {
+                mIccSize = 0;
+            }
+        }
     }
 
     ~VideoFrame() {
         if (mData != 0) {
             delete[] mData;
         }
+        if (mIccData != 0) {
+            delete[] mIccData;
+        }
+    }
+
+    // Copy |copy| to a flattened VideoFrame in IMemory, 'this' must point to
+    // a chunk of memory back by IMemory of size at least getFlattenedSize()
+    // of |copy|.
+    void copyFlattened(const VideoFrame& copy) {
+        copyInfoOnly(copy);
+
+        mSize = copy.mSize;
+        mData = NULL;  // initialize it first
+        if (copy.mSize > 0 && copy.mData != NULL) {
+            memcpy(getFlattenedData(), copy.mData, copy.mSize);
+        }
+
+        mIccSize = copy.mIccSize;
+        mIccData = NULL;  // initialize it first
+        if (copy.mIccSize > 0 && copy.mIccData != NULL) {
+            memcpy(getFlattenedIccData(), copy.mIccData, copy.mIccSize);
+        }
+    }
+
+    // Calculate the flattened size to put it in IMemory
+    size_t getFlattenedSize() const {
+        return sizeof(VideoFrame) + mSize + mIccSize;
+    }
+
+    // Get the pointer to the frame data in a flattened VideoFrame in IMemory
+    uint8_t* getFlattenedData() const {
+        return (uint8_t*)this + sizeof(VideoFrame);
+    }
+
+    // Get the pointer to the ICC data in a flattened VideoFrame in IMemory
+    uint8_t* getFlattenedIccData() const {
+        return (uint8_t*)this + sizeof(VideoFrame) + mSize;
     }
 
     // Intentional public access modifier:
-    uint32_t mWidth;
-    uint32_t mHeight;
-    uint32_t mDisplayWidth;
-    uint32_t mDisplayHeight;
+    uint32_t mWidth;           // Decoded image width before rotation
+    uint32_t mHeight;          // Decoded image height before rotation
+    uint32_t mDisplayWidth;    // Display width before rotation
+    uint32_t mDisplayHeight;   // Display height before rotation
+    int32_t  mRotationAngle;   // Rotation angle, clockwise, should be multiple of 90
+    uint32_t mBytesPerPixel;   // Number of bytes per pixel
+    uint32_t mRowBytes;        // Number of bytes per row before rotation
     uint32_t mSize;            // Number of bytes in mData
-    int32_t  mRotationAngle;   // rotation angle, clockwise, should be multiple of 90
-    // mData should be 64 bit aligned to prevent additional padding
+    uint32_t mIccSize;         // Number of bytes in mIccData
+    uint32_t mReserved;        // (padding to make mData 64-bit aligned)
+
+    // mData should be 64-bit aligned to prevent additional padding
     uint8_t* mData;            // Actual binary data
-    // pad structure so it's the same size on 64 bit and 32 bit
+    // pad structure so it's the same size on 64-bit and 32-bit
     char     mPadding[8 - sizeof(mData)];
+
+    // mIccData should be 64-bit aligned to prevent additional padding
+    uint8_t* mIccData;            // Actual binary data
+    // pad structure so it's the same size on 64-bit and 32-bit
+    char     mIccPadding[8 - sizeof(mIccData)];
+
+private:
+    //
+    // Utility methods used only within VideoFrame struct
+    //
+
+    // Copy the information fields only
+    void copyInfoOnly(const VideoFrame& copy) {
+        mWidth = copy.mWidth;
+        mHeight = copy.mHeight;
+        mDisplayWidth = copy.mDisplayWidth;
+        mDisplayHeight = copy.mDisplayHeight;
+        mRotationAngle = copy.mRotationAngle;
+        mBytesPerPixel = copy.mBytesPerPixel;
+        mRowBytes = copy.mRowBytes;
+    }
 };
 
 }; // namespace android
diff --git a/include/radio/IRadio.h b/include/radio/IRadio.h
deleted file mode 100644
index 1877f8f..0000000
--- a/include/radio/IRadio.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_IRADIO_H
-#define ANDROID_HARDWARE_IRADIO_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <system/radio.h>
-
-namespace android {
-
-class IRadio : public IInterface
-{
-public:
-
-    DECLARE_META_INTERFACE(Radio);
-
-    virtual void detach() = 0;
-
-    virtual status_t setConfiguration(const struct radio_band_config *config) = 0;
-
-    virtual status_t getConfiguration(struct radio_band_config *config) = 0;
-
-    virtual status_t setMute(bool mute) = 0;
-
-    virtual status_t getMute(bool *mute) = 0;
-
-    virtual status_t step(radio_direction_t direction, bool skipSubChannel) = 0;
-
-    virtual status_t scan(radio_direction_t direction, bool skipSubChannel) = 0;
-
-    virtual status_t tune(unsigned int channel, unsigned int subChannel) = 0;
-
-    virtual status_t cancel() = 0;
-
-    virtual status_t getProgramInformation(struct radio_program_info *info) = 0;
-
-    virtual status_t hasControl(bool *hasControl) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnRadio: public BnInterface<IRadio>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_IRADIO_H
diff --git a/include/radio/IRadioClient.h b/include/radio/IRadioClient.h
deleted file mode 100644
index 9062ad6..0000000
--- a/include/radio/IRadioClient.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_IRADIO_CLIENT_H
-#define ANDROID_HARDWARE_IRADIO_CLIENT_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class IRadioClient : public IInterface
-{
-public:
-
-    DECLARE_META_INTERFACE(RadioClient);
-
-    virtual void onEvent(const sp<IMemory>& eventMemory) = 0;
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnRadioClient : public BnInterface<IRadioClient>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_IRADIO_CLIENT_H
diff --git a/include/radio/IRadioService.h b/include/radio/IRadioService.h
deleted file mode 100644
index a946dd5..0000000
--- a/include/radio/IRadioService.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_IRADIO_SERVICE_H
-#define ANDROID_HARDWARE_IRADIO_SERVICE_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <system/radio.h>
-
-namespace android {
-
-class IRadio;
-class IRadioClient;
-
-class IRadioService : public IInterface
-{
-public:
-
-    DECLARE_META_INTERFACE(RadioService);
-
-    virtual status_t listModules(struct radio_properties *properties,
-                                 uint32_t *numModules) = 0;
-
-    virtual status_t attach(const radio_handle_t handle,
-                            const sp<IRadioClient>& client,
-                            const struct radio_band_config *config,
-                            bool withAudio,
-                            sp<IRadio>& radio) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnRadioService: public BnInterface<IRadioService>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_IRADIO_SERVICE_H
diff --git a/include/radio/Radio.h b/include/radio/Radio.h
deleted file mode 100644
index fb4dd2f..0000000
--- a/include/radio/Radio.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_H
-#define ANDROID_HARDWARE_RADIO_H
-
-#include <binder/IBinder.h>
-#include <utils/threads.h>
-#include <radio/RadioCallback.h>
-#include <radio/IRadio.h>
-#include <radio/IRadioService.h>
-#include <radio/IRadioClient.h>
-#include <system/radio.h>
-
-namespace android {
-
-class MemoryDealer;
-
-class Radio : public BnRadioClient,
-                        public IBinder::DeathRecipient
-{
-public:
-
-    virtual ~Radio();
-
-    static  status_t listModules(struct radio_properties *properties,
-                                 uint32_t *numModules);
-    static  sp<Radio> attach(radio_handle_t handle,
-                             const struct radio_band_config *config,
-                             bool withAudio,
-                             const sp<RadioCallback>& callback);
-
-
-            void detach();
-
-            status_t setConfiguration(const struct radio_band_config *config);
-
-            status_t getConfiguration(struct radio_band_config *config);
-
-            status_t setMute(bool mute);
-
-            status_t getMute(bool *mute);
-
-            status_t step(radio_direction_t direction, bool skipSubChannel);
-
-            status_t scan(radio_direction_t direction, bool skipSubChannel);
-
-            status_t tune(unsigned int channel, unsigned int subChannel);
-
-            status_t cancel();
-
-            status_t getProgramInformation(struct radio_program_info *info);
-
-            status_t hasControl(bool *hasControl);
-
-            // BpRadioClient
-            virtual void onEvent(const sp<IMemory>& eventMemory);
-
-            //IBinder::DeathRecipient
-            virtual void binderDied(const wp<IBinder>& who);
-
-private:
-            Radio(radio_handle_t handle,
-                            const sp<RadioCallback>&);
-            static const sp<IRadioService> getRadioService();
-
-            Mutex                   mLock;
-            sp<IRadio>              mIRadio;
-            sp<RadioCallback>       mCallback;
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_RADIO_H
diff --git a/include/radio/RadioCallback.h b/include/radio/RadioCallback.h
deleted file mode 100644
index 4a7f1a6..0000000
--- a/include/radio/RadioCallback.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_CALLBACK_H
-#define ANDROID_HARDWARE_RADIO_CALLBACK_H
-
-#include <utils/RefBase.h>
-#include <system/radio.h>
-
-namespace android {
-
-class RadioCallback : public RefBase
-{
-public:
-
-            RadioCallback() {}
-    virtual ~RadioCallback() {}
-
-    virtual void onEvent(struct radio_event *event) = 0;
-
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_RADIO_CALLBACK_H
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index afd1189..3ee7494 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -14,7 +14,6 @@
 	liblog \
 	libmedialogservice \
 	libnbaio \
-	libradioservice \
 	libsoundtriggerservice \
 	libutils \
 	libhwbinder
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index ee02d23..474ef97 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -32,11 +32,12 @@
 #include <hwbinder/ProcessState.h>
 
 // from LOCAL_C_INCLUDES
+#include "aaudio/AAudioTesting.h"
 #include "AudioFlinger.h"
 #include "AudioPolicyService.h"
 #include "AAudioService.h"
+#include "utility/AAudioUtilities.h"
 #include "MediaLogService.h"
-#include "RadioService.h"
 #include "SoundTriggerHwService.h"
 
 using namespace android;
@@ -132,8 +133,16 @@
         ALOGI("ServiceManager: %p", sm.get());
         AudioFlinger::instantiate();
         AudioPolicyService::instantiate();
-        AAudioService::instantiate();
-        RadioService::instantiate();
+
+        // AAudioService should only be used in OC-MR1 and later.
+        // And only enable the AAudioService if the system MMAP policy explicitly allows it.
+        // This prevents a client from misusing AAudioService when it is not supported.
+        aaudio_policy_t mmapPolicy = property_get_int32(AAUDIO_PROP_MMAP_POLICY,
+                                                        AAUDIO_POLICY_NEVER);
+        if (mmapPolicy == AAUDIO_POLICY_AUTO || mmapPolicy == AAUDIO_POLICY_ALWAYS) {
+            AAudioService::instantiate();
+        }
+
         SoundTriggerHwService::instantiate();
         ProcessState::self()->startThreadPool();
 
diff --git a/media/libaaudio/Doxyfile b/media/libaaudio/Doxyfile
index e2c4960..7298d11 100644
--- a/media/libaaudio/Doxyfile
+++ b/media/libaaudio/Doxyfile
@@ -744,12 +744,12 @@
 # Note: If this tag is empty the current directory is searched.
 
 INPUT                  = include/aaudio/AAudio.h \
+                         src/binding/AAudioCommon.h \
                          src/legacy/AudioStreamTrack.h \
                          src/legacy/AudioStreamRecord.h \
                          src/legacy/AAudioLegacy.h \
                          src/core/AudioStreamBuilder.h \
                          src/core/AudioStream.h \
-                         src/utility/HandleTracker.h \
                          src/utility/MonotonicCounter.h \
                          src/utility/AudioClock.h \
                          src/utility/AAudioUtilities.h
diff --git a/media/libaaudio/OWNERS b/media/libaaudio/OWNERS
new file mode 100644
index 0000000..f4d51f9
--- /dev/null
+++ b/media/libaaudio/OWNERS
@@ -0,0 +1 @@
+philburk@google.com
diff --git a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
index d1ae160..e5ad2d9 100644
--- a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
+++ b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
@@ -27,9 +27,11 @@
 #include "AAudioSimpleRecorder.h"
 
 // TODO support FLOAT
-#define REQUIRED_FORMAT  AAUDIO_FORMAT_PCM_I16
+#define REQUIRED_FORMAT    AAUDIO_FORMAT_PCM_I16
 #define MIN_FRAMES_TO_READ 48  /* arbitrary, 1 msec at 48000 Hz */
 
+static const int FRAMES_PER_LINE = 20000;
+
 int main(int argc, const char **argv)
 {
     AAudioArgsParser   argParser;
@@ -45,17 +47,19 @@
     int32_t framesPerRead = 0;
     int32_t framesToRecord = 0;
     int32_t framesLeft = 0;
+    int32_t nextFrameCount = 0;
+    int32_t frameCount = 0;
     int32_t xRunCount = 0;
+    int64_t previousFramePosition = -1;
     int16_t *data = nullptr;
     float peakLevel = 0.0;
-    int loopCounter = 0;
     int32_t deviceId;
 
     // Make printf print immediately so that debug info is not stuck
     // in a buffer if we hang or crash.
     setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
 
-    printf("%s - Monitor input level using AAudio\n", argv[0]);
+    printf("%s - Monitor input level using AAudio read, V0.1.2\n", argv[0]);
 
     argParser.setFormat(REQUIRED_FORMAT);
     if (argParser.parseArgs(argc, argv)) {
@@ -73,7 +77,7 @@
     deviceId = AAudioStream_getDeviceId(aaudioStream);
     printf("deviceId = %d\n", deviceId);
 
-    actualSamplesPerFrame = AAudioStream_getSamplesPerFrame(aaudioStream);
+    actualSamplesPerFrame = AAudioStream_getChannelCount(aaudioStream);
     printf("SamplesPerFrame = %d\n", actualSamplesPerFrame);
     actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
     printf("SamplesPerFrame = %d\n", actualSampleRate);
@@ -132,6 +136,7 @@
             goto finish;
         }
         framesLeft -= actual;
+        frameCount += actual;
 
         // Peak finder.
         for (int frameIndex = 0; frameIndex < actual; frameIndex++) {
@@ -142,9 +147,36 @@
         }
 
         // Display level as stars, eg. "******".
-        if ((loopCounter++ % 10) == 0) {
+        if (frameCount > nextFrameCount) {
             displayPeakLevel(peakLevel);
             peakLevel = 0.0;
+            nextFrameCount += FRAMES_PER_LINE;
+        }
+
+        // Print timestamps.
+        int64_t framePosition = 0;
+        int64_t frameTime = 0;
+        aaudio_result_t timeResult;
+        timeResult = AAudioStream_getTimestamp(aaudioStream, CLOCK_MONOTONIC,
+                                               &framePosition, &frameTime);
+
+        if (timeResult == AAUDIO_OK) {
+            if (framePosition > (previousFramePosition + FRAMES_PER_LINE)) {
+                int64_t realTime = getNanoseconds();
+                int64_t framesRead = AAudioStream_getFramesRead(aaudioStream);
+
+                double latencyMillis = calculateLatencyMillis(framesRead, realTime,
+                                                              framePosition, frameTime,
+                                                              actualSampleRate);
+
+                printf("--- timestamp: result = %4d, position = %lld, at %lld nanos"
+                               ", latency = %7.2f msec\n",
+                       timeResult,
+                       (long long) framePosition,
+                       (long long) frameTime,
+                       latencyMillis);
+                previousFramePosition = framePosition;
+            }
         }
     }
 
diff --git a/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp b/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp
index 9de2eb0..893795b 100644
--- a/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp
+++ b/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp
@@ -41,7 +41,7 @@
     // Make printf print immediately so that debug info is not stuck
     // in a buffer if we hang or crash.
     setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
-    printf("%s - Display audio input using an AAudio callback\n", argv[0]);
+    printf("%s - Display audio input using an AAudio callback, V0.1.2\n", argv[0]);
 
     result = recorder.open(2, 48000, AAUDIO_FORMAT_PCM_I16,
                        SimpleRecorderDataCallbackProc, SimpleRecorderErrorCallbackProc, &myData);
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index d3b6ff7..b678d8a 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -413,11 +413,18 @@
             sleep(1);
             printf("%4d: ", i);
             loopbackData.loopbackProcessor->printStatus();
-            int64_t framesWritten = AAudioStream_getFramesWritten(loopbackData.inputStream);
-            int64_t framesRead = AAudioStream_getFramesRead(loopbackData.inputStream);
-            printf(" input written = %lld, read %lld, xruns = %d\n",
-                   (long long) framesWritten,
-                   (long long) framesRead,
+
+            int64_t inputFramesWritten = AAudioStream_getFramesWritten(loopbackData.inputStream);
+            int64_t inputFramesRead = AAudioStream_getFramesRead(loopbackData.inputStream);
+            int64_t outputFramesWritten = AAudioStream_getFramesWritten(outputStream);
+            int64_t outputFramesRead = AAudioStream_getFramesRead(outputStream);
+            printf(" INPUT: wr %lld rd %lld state %s, OUTPUT: wr %lld rd %lld state %s, xruns %d\n",
+                   (long long) inputFramesWritten,
+                   (long long) inputFramesRead,
+                   AAudio_convertStreamStateToText(AAudioStream_getState(loopbackData.inputStream)),
+                   (long long) outputFramesWritten,
+                   (long long) outputFramesRead,
+                   AAudio_convertStreamStateToText(AAudioStream_getState(outputStream)),
                    AAudioStream_getXRunCount(outputStream)
             );
         }
diff --git a/media/libaaudio/examples/utils/AAudioArgsParser.h b/media/libaaudio/examples/utils/AAudioArgsParser.h
index 46bc99e..ada37e2 100644
--- a/media/libaaudio/examples/utils/AAudioArgsParser.h
+++ b/media/libaaudio/examples/utils/AAudioArgsParser.h
@@ -24,7 +24,8 @@
 
 #include <aaudio/AAudio.h>
 #include <aaudio/AAudioTesting.h>
-#include <AAudioExampleUtils.h>
+
+#include "AAudioExampleUtils.h"
 
 // TODO use this as a base class within AAudio
 class AAudioParameters {
@@ -149,6 +150,9 @@
                     setChannelCount(atoi(&arg[2]));
                     break;
                 case 'd':
+                    setDeviceId(atoi(&arg[2]));
+                    break;
+                case 's':
                     mDurationSeconds = atoi(&arg[2]);
                     break;
                 case 'm': {
@@ -201,7 +205,8 @@
         printf("      Default values are UNSPECIFIED unless otherwise stated.\n");
         printf("      -b{bufferCapacity} frames\n");
         printf("      -c{channels} for example 2 for stereo\n");
-        printf("      -d{duration} in seconds, default is %d\n", DEFAULT_DURATION_SECONDS);
+        printf("      -d{deviceId} default is %d\n", AAUDIO_UNSPECIFIED);
+        printf("      -s{duration} in seconds, default is %d\n", DEFAULT_DURATION_SECONDS);
         printf("      -m{0|1|2|3} set MMAP policy\n");
         printf("          0 = _UNSPECIFIED, default\n");
         printf("          1 = _NEVER\n");
@@ -239,7 +244,7 @@
      * Print stream parameters in comparison with requested values.
      * @param stream
      */
-    void compareWithStream(AAudioStream *stream) {
+    void compareWithStream(AAudioStream *stream) const {
 
         printf("  DeviceId:     requested = %d, actual = %d\n",
                getDeviceId(), AAudioStream_getDeviceId(stream));
diff --git a/media/libaaudio/examples/utils/AAudioExampleUtils.h b/media/libaaudio/examples/utils/AAudioExampleUtils.h
index 156c7be..2671c3a 100644
--- a/media/libaaudio/examples/utils/AAudioExampleUtils.h
+++ b/media/libaaudio/examples/utils/AAudioExampleUtils.h
@@ -17,31 +17,74 @@
 #ifndef AAUDIO_EXAMPLE_UTILS_H
 #define AAUDIO_EXAMPLE_UTILS_H
 
+#include <atomic>
 #include <errno.h>
+#include <linux/futex.h>
 #include <sched.h>
 #include <string.h>
+#include <sys/syscall.h>
 #include <unistd.h>
 
 #include <aaudio/AAudio.h>
+#include <utils/Errors.h>
 
 #define NANOS_PER_MICROSECOND ((int64_t)1000)
 #define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
 #define NANOS_PER_SECOND      (NANOS_PER_MILLISECOND * 1000)
 
-template <class T = aaudio_sharing_mode_t>
 const char *getSharingModeText(aaudio_sharing_mode_t mode) {
-    const char *modeText = "unknown";
+    const char *text = "unknown";
     switch (mode) {
-    case AAUDIO_SHARING_MODE_EXCLUSIVE:
-        modeText = "EXCLUSIVE";
-        break;
-    case AAUDIO_SHARING_MODE_SHARED:
-        modeText = "SHARED";
-        break;
-    default:
-        break;
+        case AAUDIO_SHARING_MODE_EXCLUSIVE:
+            text = "EXCLUSIVE";
+            break;
+        case AAUDIO_SHARING_MODE_SHARED:
+            text = "SHARED";
+            break;
+        default:
+            break;
     }
-    return modeText;
+    return text;
+}
+
+const char *getPerformanceModeText(aaudio_performance_mode_t mode) {
+    const char *text = "unknown";
+    switch (mode) {
+        case AAUDIO_PERFORMANCE_MODE_NONE:
+            text = "NONE";
+            break;
+        case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
+            text = "LOW_LATENCY";
+            break;
+        case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
+            text = "POWER_SAVING";
+            break;
+        default:
+            break;
+    }
+    return text;
+}
+
+const char *getDirectionText(aaudio_direction_t direction) {
+    const char *text = "unknown";
+    switch (direction) {
+        case AAUDIO_DIRECTION_INPUT:
+            text = "INPUT";
+            break;
+        case AAUDIO_DIRECTION_OUTPUT:
+            text = "OUTPUT";
+            break;
+        default:
+            break;
+    }
+    return text;
+}
+
+template <class T = int64_t>
+void convertNanosecondsToTimespec(int64_t nanoseconds, struct timespec *time) {
+    time->tv_sec = nanoseconds / NANOS_PER_SECOND;
+    // Calculate the fractional nanoseconds. Avoids expensive % operation.
+    time->tv_nsec = nanoseconds - (time->tv_sec * NANOS_PER_SECOND);
 }
 
 template <class T = clockid_t>
@@ -54,6 +97,7 @@
     return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
 }
 
+template <class T = float>
 void displayPeakLevel(float peakLevel) {
     printf("%5.3f ", peakLevel);
     const int maxStars = 50; // arbitrary, fits on one line
@@ -64,4 +108,101 @@
     printf("\n");
 }
 
+/**
+ * @param position1 position of hardware frame
+ * @param nanoseconds1
+ * @param position2 position of client read/write
+ * @param nanoseconds2
+ * @param sampleRate
+ * @return latency in milliseconds
+ */
+template <class T = int64_t>
+double calculateLatencyMillis(int64_t position1, int64_t nanoseconds1,
+                              int64_t position2, int64_t nanoseconds2,
+                              int64_t sampleRate) {
+    int64_t deltaFrames = position2 - position1;
+    int64_t deltaTime =
+            (NANOS_PER_SECOND * deltaFrames / sampleRate);
+    int64_t timeCurrentFramePlayed = nanoseconds1 + deltaTime;
+    int64_t latencyNanos = timeCurrentFramePlayed - nanoseconds2;
+    double latencyMillis = latencyNanos / 1000000.0;
+    return latencyMillis;
+}
+
+// ================================================================================
+// These Futex calls are common online examples.
+template <class T = int>
+android::status_t sys_futex(void *addr1, int op, int val1,
+                      struct timespec *timeout, void *addr2, int val3) {
+    android::status_t result = (android::status_t) syscall(SYS_futex, addr1,
+                                                           op, val1, timeout,
+                                                           addr2, val3);
+    return (result == 0) ? 0 : -errno;
+}
+
+template <class T = int>
+android::status_t futex_wake(void *addr, int numWake) {
+    // Use _PRIVATE because we are just using the futex in one process.
+    return sys_futex(addr, FUTEX_WAKE_PRIVATE, numWake, NULL, NULL, 0);
+}
+
+template <class T = int>
+android::status_t futex_wait(void *addr, int current, struct timespec *time) {
+    // Use _PRIVATE because we are just using the futex in one process.
+    return sys_futex(addr, FUTEX_WAIT_PRIVATE, current, time, NULL, 0);
+}
+
+// TODO better name?
+/**
+ * The WakeUp class is used to send a wakeup signal to one or more sleeping threads.
+ */
+class WakeUp {
+public:
+    WakeUp() : mValue(0) {}
+    explicit WakeUp(int32_t value) : mValue(value) {}
+
+    /**
+     * Wait until the internal value no longer matches the given value.
+     * Note that this code uses a futex, which is subject to spurious wake-ups.
+     * So check to make sure that the desired condition has been met.
+     *
+     * @return zero if the value changes or various negative errors including
+     *    -ETIMEDOUT if a timeout occurs,
+     *    or -EINTR if interrupted by a signal,
+     *    or -EAGAIN or -EWOULDBLOCK if the internal value does not match the specified value
+     */
+    android::status_t wait(int32_t value, int64_t timeoutNanoseconds) {
+        struct timespec time;
+        convertNanosecondsToTimespec(timeoutNanoseconds, &time);
+        return futex_wait(&mValue, value, &time);
+    }
+
+    /**
+     * Increment value and wake up any threads that need to be woken.
+     *
+     * @return number of waiters woken up
+     */
+    android::status_t wake() {
+        ++mValue;
+        return futex_wake(&mValue, INT_MAX);
+    }
+
+    /**
+     * Set value and wake up any threads that need to be woken.
+     *
+     * @return number of waiters woken up
+     */
+    android::status_t wake(int32_t value) {
+        mValue.store(value);
+        return futex_wake(&mValue, INT_MAX);
+    }
+
+    int32_t get() {
+        return mValue.load();
+    }
+
+private:
+    std::atomic<int32_t>   mValue;
+};
+
 #endif // AAUDIO_EXAMPLE_UTILS_H
diff --git a/media/libaaudio/examples/utils/AAudioSimplePlayer.h b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
index cc0cb34..606c4ba 100644
--- a/media/libaaudio/examples/utils/AAudioSimplePlayer.h
+++ b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
@@ -23,6 +23,7 @@
 #include <sched.h>
 
 #include <aaudio/AAudio.h>
+#include <atomic>
 #include "AAudioArgsParser.h"
 #include "SineGenerator.h"
 
@@ -35,6 +36,13 @@
 // How long to sleep in a callback to cause an intentional glitch. For testing.
 #define FORCED_UNDERRUN_SLEEP_MICROS     (10 * 1000)
 
+#define MAX_TIMESTAMPS   16
+
+typedef struct Timestamp {
+    int64_t position;
+    int64_t nanoseconds;
+} Timestamp;
+
 /**
  * Simple wrapper for AAudio that opens an output stream either in callback or blocking write mode.
  */
@@ -219,18 +227,28 @@
     AAudioStream             *mStream = nullptr;
     aaudio_sharing_mode_t     mRequestedSharingMode = SHARING_MODE;
     aaudio_performance_mode_t mRequestedPerformanceMode = PERFORMANCE_MODE;
+
 };
 
 typedef struct SineThreadedData_s {
+
     SineGenerator  sineOsc1;
     SineGenerator  sineOsc2;
+    Timestamp      timestamps[MAX_TIMESTAMPS];
     int64_t        framesTotal = 0;
     int64_t        nextFrameToGlitch = FORCED_UNDERRUN_PERIOD_FRAMES;
     int32_t        minNumFrames = INT32_MAX;
     int32_t        maxNumFrames = 0;
-    int            scheduler;
+    int32_t        timestampCount = 0; // in timestamps
+
+    int            scheduler = 0;
     bool           schedulerChecked = false;
     bool           forceUnderruns = false;
+
+    AAudioSimplePlayer simplePlayer;
+    int32_t            callbackCount = 0;
+    WakeUp             waker{AAUDIO_OK};
+
 } SineThreadedData_t;
 
 // Callback function that fills the audio output buffer.
@@ -247,6 +265,7 @@
         return AAUDIO_CALLBACK_RESULT_STOP;
     }
     SineThreadedData_t *sineData = (SineThreadedData_t *) userData;
+    sineData->callbackCount++;
 
     sineData->framesTotal += numFrames;
 
@@ -263,6 +282,17 @@
         sineData->schedulerChecked = true;
     }
 
+    if (sineData->timestampCount < MAX_TIMESTAMPS) {
+        Timestamp *timestamp = &sineData->timestamps[sineData->timestampCount];
+        aaudio_result_t result = AAudioStream_getTimestamp(stream,
+            CLOCK_MONOTONIC, &timestamp->position, &timestamp->nanoseconds);
+        if (result == AAUDIO_OK && // valid?
+                (sineData->timestampCount == 0 || // first one?
+                (timestamp->position != (timestamp - 1)->position))) { // advanced position?
+            sineData->timestampCount++; // keep this one
+        }
+    }
+
     if (numFrames > sineData->maxNumFrames) {
         sineData->maxNumFrames = numFrames;
     }
@@ -304,9 +334,16 @@
 void SimplePlayerErrorCallbackProc(
         AAudioStream *stream __unused,
         void *userData __unused,
-        aaudio_result_t error)
-{
-    printf("Error Callback, error: %d\n",(int)error);
+        aaudio_result_t error) {
+    // should not happen but just in case...
+    if (userData == nullptr) {
+        printf("ERROR - MyPlayerErrorCallbackProc needs userData\n");
+        return;
+    }
+    SineThreadedData_t *sineData = (SineThreadedData_t *) userData;
+    android::status_t ret = sineData->waker.wake(error);
+    printf("Error Callback, error: %d, futex wake returns %d\n", error, ret);
 }
 
+
 #endif //AAUDIO_SIMPLE_PLAYER_H
diff --git a/media/libaaudio/examples/utils/AAudioSimpleRecorder.h b/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
index 5ecac04..1344273 100644
--- a/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
+++ b/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
@@ -77,7 +77,7 @@
         if (mStream == nullptr) {
             return AAUDIO_ERROR_INVALID_STATE;
         }
-        return AAudioStream_getChannelCount(mStream);
+        return AAudioStream_getChannelCount(mStream);;
     }
 
     /**
@@ -187,7 +187,7 @@
 
     // Write zero data to fill up the buffer and prevent underruns.
     aaudio_result_t prime() {
-        int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(mStream);
+        int32_t samplesPerFrame = AAudioStream_getChannelCount(mStream);
         const int numFrames = 32; // arbitrary
         float zeros[numFrames * samplesPerFrame];
         memset(zeros, 0, sizeof(zeros));
@@ -260,7 +260,7 @@
     }
     PeakTrackerData_t *data = (PeakTrackerData_t *) userData;
     // printf("MyCallbackProc(): frameCount = %d\n", numFrames);
-    int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
+    int32_t samplesPerFrame = AAudioStream_getChannelCount(stream);
     float sample;
     // This code assume mono or stereo.
     switch (AAudioStream_getFormat(stream)) {
diff --git a/media/libaaudio/examples/utils/SineGenerator.h b/media/libaaudio/examples/utils/SineGenerator.h
index 64b772d..a755582 100644
--- a/media/libaaudio/examples/utils/SineGenerator.h
+++ b/media/libaaudio/examples/utils/SineGenerator.h
@@ -58,6 +58,13 @@
         }
     }
 
+    void setAmplitude(double amplitude) {
+        mAmplitude = amplitude;
+    }
+    double getAmplitude() const {
+        return mAmplitude;
+    }
+
 private:
     void advancePhase() {
         mPhase += mPhaseIncrement;
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index 656ab05..8c6f783 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -56,7 +56,7 @@
     // in a buffer if we hang or crash.
     setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
 
-    printf("%s - Play a sine wave using AAudio V0.1.1\n", argv[0]);
+    printf("%s - Play a sine wave using AAudio V0.1.2\n", argv[0]);
 
     if (argParser.parseArgs(argc, argv)) {
         return EXIT_FAILURE;
diff --git a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
index b5602e9..4f9cde6 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
@@ -15,6 +15,7 @@
  */
 
 // Play sine waves using an AAudio callback.
+// If a disconnection occurs then reopen the stream on the new device.
 
 #include <assert.h>
 #include <unistd.h>
@@ -22,33 +23,32 @@
 #include <sched.h>
 #include <stdio.h>
 #include <math.h>
+#include <string.h>
 #include <time.h>
 #include <aaudio/AAudio.h>
 #include "AAudioExampleUtils.h"
 #include "AAudioSimplePlayer.h"
 #include "../../utils/AAudioSimplePlayer.h"
 
-int main(int argc, const char **argv)
+/**
+ * Open stream, play some sine waves, then close the stream.
+ *
+ * @param argParser
+ * @return AAUDIO_OK or negative error code
+ */
+static aaudio_result_t testOpenPlayClose(AAudioArgsParser &argParser)
 {
-    AAudioArgsParser   argParser;
-    AAudioSimplePlayer player;
     SineThreadedData_t myData;
-    aaudio_result_t result;
-    int32_t actualSampleRate;
+    AAudioSimplePlayer &player = myData.simplePlayer;
+    aaudio_result_t    result = AAUDIO_OK;
+    bool               disconnected = false;
+    int64_t            startedAtNanos;
 
-    // Make printf print immediately so that debug info is not stuck
-    // in a buffer if we hang or crash.
-    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
-
-    printf("%s - Play a sine sweep using an AAudio callback V0.1.2\n", argv[0]);
-
+    printf("----------------------- run complete test --------------------------\n");
     myData.schedulerChecked = false;
+    myData.callbackCount = 0;
     myData.forceUnderruns = false; // set true to test AAudioStream_getXRunCount()
 
-    if (argParser.parseArgs(argc, argv)) {
-        return EXIT_FAILURE;
-    }
-
     result = player.open(argParser,
                          SimplePlayerDataCallbackProc, SimplePlayerErrorCallbackProc, &myData);
     if (result != AAUDIO_OK) {
@@ -58,13 +58,19 @@
 
     argParser.compareWithStream(player.getStream());
 
-    actualSampleRate = player.getSampleRate();
-    myData.sineOsc1.setup(440.0, actualSampleRate);
-    myData.sineOsc1.setSweep(300.0, 600.0, 5.0);
-    myData.sineOsc2.setup(660.0, actualSampleRate);
-    myData.sineOsc2.setSweep(350.0, 900.0, 7.0);
+    // Setup sine wave generators.
+    {
+        int32_t actualSampleRate = player.getSampleRate();
+        myData.sineOsc1.setup(440.0, actualSampleRate);
+        myData.sineOsc1.setSweep(300.0, 600.0, 5.0);
+        myData.sineOsc1.setAmplitude(0.2);
+        myData.sineOsc2.setup(660.0, actualSampleRate);
+        myData.sineOsc2.setSweep(350.0, 900.0, 7.0);
+        myData.sineOsc2.setAmplitude(0.2);
+    }
 
 #if 0
+    //  writes not allowed for callback streams
     result = player.prime(); // FIXME crashes AudioTrack.cpp
     if (result != AAUDIO_OK) {
         fprintf(stderr, "ERROR - player.prime() returned %d\n", result);
@@ -78,34 +84,32 @@
         goto error;
     }
 
+    // Play a sine wave in the background.
     printf("Sleep for %d seconds while audio plays in a callback thread.\n",
            argParser.getDurationSeconds());
+    startedAtNanos = getNanoseconds(CLOCK_MONOTONIC);
     for (int second = 0; second < argParser.getDurationSeconds(); second++)
     {
-        const struct timespec request = { .tv_sec = 1, .tv_nsec = 0 };
-        (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
-
-        aaudio_stream_state_t state;
-        result = AAudioStream_waitForStateChange(player.getStream(),
-                                                 AAUDIO_STREAM_STATE_CLOSED,
-                                                 &state,
-                                                 0);
+        // Sleep a while. Wake up early if there is an error, for example a DISCONNECT.
+        long ret = myData.waker.wait(AAUDIO_OK, NANOS_PER_SECOND);
+        int64_t millis = (getNanoseconds(CLOCK_MONOTONIC) - startedAtNanos) / NANOS_PER_MILLISECOND;
+        result = myData.waker.get();
+        printf("wait() returns %ld, aaudio_result = %d, at %6d millis"
+               ", second = %d, framesWritten = %8d, underruns = %d\n",
+               ret, result, (int) millis,
+               second,
+               (int) AAudioStream_getFramesWritten(player.getStream()),
+               (int) AAudioStream_getXRunCount(player.getStream()));
         if (result != AAUDIO_OK) {
-            fprintf(stderr, "ERROR - AAudioStream_waitForStateChange() returned %d\n", result);
-            goto error;
-        }
-        if (state != AAUDIO_STREAM_STATE_STARTING && state != AAUDIO_STREAM_STATE_STARTED) {
-            printf("Stream state is %d %s!\n", state, AAudio_convertStreamStateToText(state));
+            if (result == AAUDIO_ERROR_DISCONNECTED) {
+                disconnected = true;
+            }
             break;
         }
-        printf("framesWritten = %d, underruns = %d\n",
-               (int) AAudioStream_getFramesWritten(player.getStream()),
-               (int) AAudioStream_getXRunCount(player.getStream())
-        );
     }
-    printf("Woke up now.\n");
+    printf("AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
 
-    printf("call stop()\n");
+    printf("call stop() callback # = %d\n", myData.callbackCount);
     result = player.stop();
     if (result != AAUDIO_OK) {
         goto error;
@@ -116,6 +120,18 @@
         goto error;
     }
 
+    for (int i = 0; i < myData.timestampCount; i++) {
+        Timestamp *timestamp = &myData.timestamps[i];
+        bool retro = (i > 0 &&
+                      ((timestamp->position < (timestamp - 1)->position)
+                       || ((timestamp->nanoseconds < (timestamp - 1)->nanoseconds))));
+        const char *message = retro ? "  <= RETROGRADE!" : "";
+        printf("Timestamp %3d : %8lld, %8lld %s\n", i,
+               (long long) timestamp->position,
+               (long long) timestamp->nanoseconds,
+               message);
+    }
+
     if (myData.schedulerChecked) {
         printf("scheduler = 0x%08x, SCHED_FIFO = 0x%08X\n",
                myData.scheduler,
@@ -126,10 +142,28 @@
     printf("max numFrames = %8d\n", (int) myData.maxNumFrames);
 
     printf("SUCCESS\n");
-    return EXIT_SUCCESS;
 error:
     player.close();
-    printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
-    return EXIT_FAILURE;
+    return disconnected ? AAUDIO_ERROR_DISCONNECTED : result;
 }
 
+int main(int argc, const char **argv)
+{
+    AAudioArgsParser   argParser;
+    aaudio_result_t    result;
+
+    // Make printf print immediately so that debug info is not stuck
+    // in a buffer if we hang or crash.
+    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
+
+    printf("%s - Play a sine sweep using an AAudio callback V0.1.2\n", argv[0]);
+
+    if (argParser.parseArgs(argc, argv)) {
+        return EXIT_FAILURE;
+    }
+
+    // Keep looping until we can complete the test without disconnecting.
+    while((result = testOpenPlayClose(argParser)) == AAUDIO_ERROR_DISCONNECTED);
+
+    return (result) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index e1886ac..3c23736 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -234,10 +234,11 @@
                                                    int32_t channelCount);
 
 /**
+ * Identical to AAudioStreamBuilder_setChannelCount().
  *
- * @deprecated use AAudioStreamBuilder_setChannelCount()
+ * @param builder reference provided by AAudio_createStreamBuilder()
+ * @param samplesPerFrame Number of samples in a frame.
  */
-// TODO remove as soon as the NDK and OS are in sync, before RC1
 AAUDIO_API void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder,
                                                        int32_t samplesPerFrame);
 
@@ -729,11 +730,10 @@
 AAUDIO_API int32_t AAudioStream_getChannelCount(AAudioStream* stream);
 
 /**
- * The samplesPerFrame is also known as channelCount.
+ * Identical to AAudioStream_getChannelCount().
  *
- * @deprecated use AAudioStream_getChannelCount()
  * @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return actual samples per frame
+ * @return actual number of samples frame
  */
 AAUDIO_API int32_t AAudioStream_getSamplesPerFrame(AAudioStream* stream);
 
@@ -810,7 +810,7 @@
  * The position and time passed back are monotonically increasing.
  *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
- * @param clockid AAUDIO_CLOCK_MONOTONIC or AAUDIO_CLOCK_BOOTTIME
+ * @param clockid CLOCK_MONOTONIC or CLOCK_BOOTTIME
  * @param framePosition pointer to a variable to receive the position
  * @param timeNanoseconds pointer to a variable to receive the time
  * @return AAUDIO_OK or a negative error
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index 42f577e..788833b 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -21,7 +21,6 @@
         "legacy/AudioStreamLegacy.cpp",
         "legacy/AudioStreamRecord.cpp",
         "legacy/AudioStreamTrack.cpp",
-        "utility/HandleTracker.cpp",
         "utility/AAudioUtilities.cpp",
         "utility/FixedBlockAdapter.cpp",
         "utility/FixedBlockReader.cpp",
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.cpp b/media/libaaudio/src/binding/AAudioBinderClient.cpp
index a268e49..07ee2de 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderClient.cpp
@@ -45,6 +45,7 @@
 using android::IInterface;
 using android::IAAudioService;
 using android::Mutex;
+using android::ProcessState;
 using android::sp;
 using android::wp;
 
@@ -52,15 +53,19 @@
 
 ANDROID_SINGLETON_STATIC_INSTANCE(AAudioBinderClient);
 
+// If we don't keep a strong pointer here then this singleton can get deleted!
+android::sp<AAudioBinderClient> gKeepBinderClient;
+
 AAudioBinderClient::AAudioBinderClient()
         : AAudioServiceInterface()
         , Singleton<AAudioBinderClient>() {
-
+    gKeepBinderClient = this; // so this singleton won't get deleted
     mAAudioClient = new AAudioClient(this);
-    ALOGV("AAudioBinderClient() created mAAudioClient = %p", mAAudioClient.get());
+    ALOGV("AAudioBinderClient() this = %p, created mAAudioClient = %p", this, mAAudioClient.get());
 }
 
 AAudioBinderClient::~AAudioBinderClient() {
+    ALOGV("AAudioBinderClient()::~AAudioBinderClient() destroying %p", this);
     Mutex::Autolock _l(mServiceLock);
     if (mAAudioService != 0) {
         IInterface::asBinder(mAAudioService)->unlinkToDeath(mAAudioClient);
@@ -75,19 +80,19 @@
     bool needToRegister = false;
     {
         Mutex::Autolock _l(mServiceLock);
-        if (mAAudioService == 0) {
+        if (mAAudioService.get() == nullptr) {
             sp<IBinder> binder;
             sp<IServiceManager> sm = defaultServiceManager();
             // Try several times to get the service.
             int retries = 4;
             do {
                 binder = sm->getService(String16(AAUDIO_SERVICE_NAME)); // This will wait a while.
-                if (binder != 0) {
+                if (binder.get() != nullptr) {
                     break;
                 }
             } while (retries-- > 0);
 
-            if (binder != 0) {
+            if (binder.get() != nullptr) {
                 // Ask for notification if the service dies.
                 status_t status = binder->linkToDeath(mAAudioClient);
                 // TODO review what we should do if this fails
@@ -98,7 +103,7 @@
                 mAAudioService = interface_cast<IAAudioService>(binder);
                 needToRegister = true;
                 // Make sure callbacks can be received by mAAudioClient
-                android::ProcessState::self()->startThreadPool();
+                ProcessState::self()->startThreadPool();
             } else {
                 ALOGE("AAudioBinderClient could not connect to %s", AAUDIO_SERVICE_NAME);
             }
@@ -106,7 +111,7 @@
         aaudioService = mAAudioService;
     }
     // Do this outside the mutex lock.
-    if (needToRegister && aaudioService != 0) { // new client?
+    if (needToRegister && aaudioService.get() != nullptr) { // new client?
         aaudioService->registerClient(mAAudioClient);
     }
     return aaudioService;
@@ -117,7 +122,6 @@
     mAAudioService.clear(); // force a reconnect
 }
 
-
 /**
 * @param request info needed to create the stream
 * @param configuration contains information about the created stream
@@ -128,14 +132,12 @@
     aaudio_handle_t stream;
     for (int i = 0; i < 2; i++) {
         const sp<IAAudioService> &service = getAAudioService();
-        if (service == 0) {
-            return AAUDIO_ERROR_NO_SERVICE;
-        }
+        if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
 
         stream = service->openStream(request, configurationOutput);
 
         if (stream == AAUDIO_ERROR_NO_SERVICE) {
-            ALOGE("AAudioBinderClient: lost connection to AAudioService.");
+            ALOGE("AAudioBinderClient::openStream lost connection to AAudioService.");
             dropAAudioService(); // force a reconnect
         } else {
             break;
@@ -145,8 +147,8 @@
 }
 
 aaudio_result_t AAudioBinderClient::closeStream(aaudio_handle_t streamHandle) {
-    const sp<IAAudioService> &service = getAAudioService();
-    if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
+    const sp<IAAudioService> service = getAAudioService();
+    if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
     return service->closeStream(streamHandle);
 }
 
@@ -155,32 +157,32 @@
 */
 aaudio_result_t AAudioBinderClient::getStreamDescription(aaudio_handle_t streamHandle,
                                                          AudioEndpointParcelable &parcelable) {
-    const sp<IAAudioService> &service = getAAudioService();
-    if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
+    const sp<IAAudioService> service = getAAudioService();
+    if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
     return service->getStreamDescription(streamHandle, parcelable);
 }
 
 aaudio_result_t AAudioBinderClient::startStream(aaudio_handle_t streamHandle) {
-    const sp<IAAudioService> &service = getAAudioService();
-    if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
+    const sp<IAAudioService> service = getAAudioService();
+    if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
     return service->startStream(streamHandle);
 }
 
 aaudio_result_t AAudioBinderClient::pauseStream(aaudio_handle_t streamHandle) {
-    const sp<IAAudioService> &service = getAAudioService();
-    if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
+    const sp<IAAudioService> service = getAAudioService();
+    if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
     return service->pauseStream(streamHandle);
 }
 
 aaudio_result_t AAudioBinderClient::stopStream(aaudio_handle_t streamHandle) {
-    const sp<IAAudioService> &service = getAAudioService();
-    if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
+    const sp<IAAudioService> service = getAAudioService();
+    if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
     return service->stopStream(streamHandle);
 }
 
 aaudio_result_t AAudioBinderClient::flushStream(aaudio_handle_t streamHandle) {
-    const sp<IAAudioService> &service = getAAudioService();
-    if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
+    const sp<IAAudioService> service = getAAudioService();
+    if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
     return service->flushStream(streamHandle);
 }
 
@@ -190,8 +192,8 @@
 aaudio_result_t AAudioBinderClient::registerAudioThread(aaudio_handle_t streamHandle,
                                                         pid_t clientThreadId,
                                                         int64_t periodNanoseconds) {
-    const sp<IAAudioService> &service = getAAudioService();
-    if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
+    const sp<IAAudioService> service = getAAudioService();
+    if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
     return service->registerAudioThread(streamHandle,
                                         clientThreadId,
                                         periodNanoseconds);
@@ -199,8 +201,8 @@
 
 aaudio_result_t AAudioBinderClient::unregisterAudioThread(aaudio_handle_t streamHandle,
                                                           pid_t clientThreadId) {
-    const sp<IAAudioService> &service = getAAudioService();
-    if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
+    const sp<IAAudioService> service = getAAudioService();
+    if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
     return service->unregisterAudioThread(streamHandle,
                                           clientThreadId);
 }
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.h b/media/libaaudio/src/binding/AAudioBinderClient.h
index 89ae85c..f9da8b4 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.h
+++ b/media/libaaudio/src/binding/AAudioBinderClient.h
@@ -118,13 +118,13 @@
     {
     public:
         AAudioClient(android::wp<AAudioBinderClient> aaudioBinderClient)
-            : mBinderClient(aaudioBinderClient) {
+                : mBinderClient(aaudioBinderClient) {
         }
 
         // implement DeathRecipient
         virtual void binderDied(const android::wp<android::IBinder>& who __unused) {
             android::sp<AAudioBinderClient> client = mBinderClient.promote();
-            if (client != 0) {
+            if (client.get() != nullptr) {
                 client->dropAAudioService();
             }
             ALOGW("AAudio service binderDied()!");
@@ -133,7 +133,7 @@
         // implement BnAAudioClient
         void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) {
             android::sp<AAudioBinderClient> client = mBinderClient.promote();
-            if (client != 0) {
+            if (client.get() != nullptr) {
                 client->onStreamChange(handle, opcode, value);
             }
         }
@@ -141,10 +141,11 @@
         android::wp<AAudioBinderClient> mBinderClient;
     };
 
+private:
 
-    android::Mutex               mServiceLock;
+    android::Mutex                  mServiceLock;
     android::sp<android::IAAudioService>  mAAudioService;
-    android::sp<AAudioClient>    mAAudioClient;
+    android::sp<AAudioClient>       mAAudioClient;
 
 };
 
diff --git a/drm/libmediadrm/aidl/android/media/ICasListener.aidl b/media/libaaudio/src/binding/AAudioCommon.h
similarity index 69%
rename from drm/libmediadrm/aidl/android/media/ICasListener.aidl
rename to media/libaaudio/src/binding/AAudioCommon.h
index 01a5abc..e3e9e82 100644
--- a/drm/libmediadrm/aidl/android/media/ICasListener.aidl
+++ b/media/libaaudio/src/binding/AAudioCommon.h
@@ -14,9 +14,19 @@
  * limitations under the License.
  */
 
-package android.media;
+#ifndef ANDROID_AAUDIO_COMMON_H
+#define ANDROID_AAUDIO_COMMON_H
 
-/** @hide */
-interface ICasListener {
-    void onEvent(int event, int arg, in @nullable byte[] data);
-}
\ No newline at end of file
+#include <stdint.h>
+
+/*
+ * Internal header that is common to both client and server.
+ *
+ */
+namespace aaudio {
+
+typedef int32_t aaudio_handle_t;
+
+} /* namespace aaudio */
+
+#endif // ANDROID_AAUDIO_COMMON_H
diff --git a/media/libaaudio/src/binding/AAudioServiceMessage.h b/media/libaaudio/src/binding/AAudioServiceMessage.h
index b4377fb..54e8001 100644
--- a/media/libaaudio/src/binding/AAudioServiceMessage.h
+++ b/media/libaaudio/src/binding/AAudioServiceMessage.h
@@ -28,7 +28,6 @@
 // Used to send information about the HAL to the client.
 struct AAudioMessageTimestamp {
     int64_t position;     // number of frames transferred so far
-    int64_t deviceOffset; // add to client position to get device position
     int64_t timestamp;    // time when that position was reached
 };
 
@@ -51,7 +50,8 @@
 typedef struct AAudioServiceMessage_s {
     enum class code : uint32_t {
         NOTHING,
-        TIMESTAMP,
+        TIMESTAMP_SERVICE, // when frame is read or written by the service to the client
+        TIMESTAMP_HARDWARE, // when frame is at DAC or ADC
         EVENT,
     };
 
diff --git a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
index e763934..153fce3 100644
--- a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
+++ b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
@@ -46,6 +46,8 @@
     if (status != NO_ERROR) goto error;
     status = parcel->writeInt32((int32_t) getFormat());
     if (status != NO_ERROR) goto error;
+    status = parcel->writeInt32((int32_t) getDirection());
+    if (status != NO_ERROR) goto error;
     status = parcel->writeInt32(getBufferCapacity());
     if (status != NO_ERROR) goto error;
     return NO_ERROR;
@@ -73,9 +75,12 @@
     setFormat(value);
     status = parcel->readInt32(&value);
     if (status != NO_ERROR) goto error;
+    setDirection((aaudio_direction_t) value);
+    status = parcel->readInt32(&value);
+    if (status != NO_ERROR) goto error;
     setBufferCapacity(value);
     return NO_ERROR;
 error:
     ALOGE("AAudioStreamConfiguration.readFromParcel(): read failed = %d", status);
     return status;
-}
\ No newline at end of file
+}
diff --git a/media/libaaudio/src/binding/AAudioStreamRequest.cpp b/media/libaaudio/src/binding/AAudioStreamRequest.cpp
index abdcf5b..1200ab2 100644
--- a/media/libaaudio/src/binding/AAudioStreamRequest.cpp
+++ b/media/libaaudio/src/binding/AAudioStreamRequest.cpp
@@ -46,9 +46,6 @@
     status_t status = parcel->writeInt32((int32_t) mUserId);
     if (status != NO_ERROR) goto error;
 
-    status = parcel->writeInt32((int32_t) mDirection);
-    if (status != NO_ERROR) goto error;
-
     status = parcel->writeBool(mSharingModeMatchRequired);
     if (status != NO_ERROR) goto error;
 
@@ -71,10 +68,6 @@
     if (status != NO_ERROR) goto error;
     mUserId = (uid_t) temp;
 
-    status = parcel->readInt32(&temp);
-    if (status != NO_ERROR) goto error;
-    mDirection = (aaudio_direction_t) temp;
-
     status = parcel->readBool(&mSharingModeMatchRequired);
     if (status != NO_ERROR) goto error;
 
@@ -98,7 +91,6 @@
 void AAudioStreamRequest::dump() const {
     ALOGD("AAudioStreamRequest mUserId    = %d", mUserId);
     ALOGD("AAudioStreamRequest mProcessId = %d", mProcessId);
-    ALOGD("AAudioStreamRequest mDirection = %d", mDirection);
     ALOGD("AAudioStreamRequest mSharingModeMatchRequired = %d", mSharingModeMatchRequired);
     ALOGD("AAudioStreamRequest mInService = %d", mInService);
     mConfiguration.dump();
diff --git a/media/libaaudio/src/binding/AAudioStreamRequest.h b/media/libaaudio/src/binding/AAudioStreamRequest.h
index b0fa96a..492f69d 100644
--- a/media/libaaudio/src/binding/AAudioStreamRequest.h
+++ b/media/libaaudio/src/binding/AAudioStreamRequest.h
@@ -52,14 +52,6 @@
         mProcessId = processId;
     }
 
-    aaudio_direction_t getDirection() const {
-        return mDirection;
-    }
-
-    void setDirection(aaudio_direction_t direction) {
-        mDirection = direction;
-    }
-
     bool isSharingModeMatchRequired() const {
         return mSharingModeMatchRequired;
     }
@@ -94,9 +86,8 @@
 
 protected:
     AAudioStreamConfiguration  mConfiguration;
-    uid_t                      mUserId;
-    pid_t                      mProcessId;
-    aaudio_direction_t         mDirection;
+    uid_t                      mUserId = (uid_t) -1;
+    pid_t                      mProcessId = (pid_t) -1;
     bool                       mSharingModeMatchRequired = false;
     bool                       mInService = false; // Stream opened by AAudioservice
 };
diff --git a/media/libaaudio/src/binding/IAAudioClient.h b/media/libaaudio/src/binding/IAAudioClient.h
index 21cc33b..f21fd93 100644
--- a/media/libaaudio/src/binding/IAAudioClient.h
+++ b/media/libaaudio/src/binding/IAAudioClient.h
@@ -22,7 +22,7 @@
 
 #include <aaudio/AAudio.h>
 
-#include "utility/HandleTracker.h"
+#include "binding/AAudioCommon.h"
 
 namespace android {
 
@@ -33,7 +33,7 @@
 
     DECLARE_META_INTERFACE(AAudioClient);
 
-    virtual void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) = 0;
+    virtual void onStreamChange(aaudio::aaudio_handle_t handle, int32_t opcode, int32_t value) = 0;
 
 };
 
diff --git a/media/libaaudio/src/binding/IAAudioService.h b/media/libaaudio/src/binding/IAAudioService.h
index 30b3ead..6bdb826 100644
--- a/media/libaaudio/src/binding/IAAudioService.h
+++ b/media/libaaudio/src/binding/IAAudioService.h
@@ -24,12 +24,12 @@
 
 #include <aaudio/AAudio.h>
 
+#include "binding/AAudioCommon.h"
 #include "binding/AAudioServiceDefinitions.h"
-#include "binding/AudioEndpointParcelable.h"
-#include "binding/AAudioStreamRequest.h"
 #include "binding/AAudioStreamConfiguration.h"
+#include "binding/AAudioStreamRequest.h"
+#include "binding/AudioEndpointParcelable.h"
 #include "binding/IAAudioClient.h"
-#include "utility/HandleTracker.h"
 
 namespace android {
 
@@ -51,7 +51,7 @@
      * @param configuration contains information about the created stream
      * @return handle to the stream or a negative error
      */
-    virtual aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
+    virtual aaudio::aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
                                      aaudio::AAudioStreamConfiguration &configurationOutput) = 0;
 
     virtual aaudio_result_t closeStream(aaudio::aaudio_handle_t streamHandle) = 0;
@@ -89,11 +89,11 @@
     /**
      * Manage the specified thread as a low latency audio thread.
      */
-    virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
+    virtual aaudio_result_t registerAudioThread(aaudio::aaudio_handle_t streamHandle,
                                               pid_t clientThreadId,
                                               int64_t periodNanoseconds) = 0;
 
-    virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
+    virtual aaudio_result_t unregisterAudioThread(aaudio::aaudio_handle_t streamHandle,
                                                 pid_t clientThreadId) = 0;
 };
 
diff --git a/media/libaaudio/src/client/AudioEndpoint.cpp b/media/libaaudio/src/client/AudioEndpoint.cpp
index 6ec285f..604eed5 100644
--- a/media/libaaudio/src/client/AudioEndpoint.cpp
+++ b/media/libaaudio/src/client/AudioEndpoint.cpp
@@ -32,14 +32,17 @@
 #define RIDICULOUSLY_LARGE_FRAME_SIZE        4096
 
 AudioEndpoint::AudioEndpoint()
-    : mFreeRunning(false)
+    : mUpCommandQueue(nullptr)
+    , mDataQueue(nullptr)
+    , mFreeRunning(false)
     , mDataReadCounter(0)
     , mDataWriteCounter(0)
 {
 }
 
-AudioEndpoint::~AudioEndpoint()
-{
+AudioEndpoint::~AudioEndpoint() {
+    delete mDataQueue;
+    delete mUpCommandQueue;
 }
 
 static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type,
@@ -118,24 +121,28 @@
 {
     aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor);
     if (result != AAUDIO_OK) {
-        ALOGE("AudioEndpoint_validateQueueDescriptor returned %d %s",
-              result, AAudio_convertResultToText(result));
         return result;
     }
 
     // ============================ up message queue =============================
     const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
     if(descriptor->bytesPerFrame != sizeof(AAudioServiceMessage)) {
-        ALOGE("AudioEndpoint::configure() bytesPerFrame != sizeof(AAudioServiceMessage) = %d",
+        ALOGE("AudioEndpoint.configure() bytesPerFrame != sizeof(AAudioServiceMessage) = %d",
               descriptor->bytesPerFrame);
         return AAUDIO_ERROR_INTERNAL;
     }
 
     if(descriptor->readCounterAddress == nullptr || descriptor->writeCounterAddress == nullptr) {
-        ALOGE("AudioEndpoint_validateQueueDescriptor() NULL counter address");
+        ALOGE("AudioEndpoint.configure() NULL counter address");
         return AAUDIO_ERROR_NULL;
     }
 
+    // Prevent memory leak and reuse.
+    if(mUpCommandQueue != nullptr || mDataQueue != nullptr) {
+        ALOGE("AudioEndpoint.configure() endpoint already used");
+        return AAUDIO_ERROR_INTERNAL;
+    }
+
     mUpCommandQueue = new FifoBuffer(
             descriptor->bytesPerFrame,
             descriptor->capacityInFrames,
@@ -146,8 +153,8 @@
 
     // ============================ data queue =============================
     descriptor = &pEndpointDescriptor->dataQueueDescriptor;
-    ALOGV("AudioEndpoint::configure() data framesPerBurst = %d", descriptor->framesPerBurst);
-    ALOGV("AudioEndpoint::configure() data readCounterAddress = %p",
+    ALOGV("AudioEndpoint.configure() data framesPerBurst = %d", descriptor->framesPerBurst);
+    ALOGV("AudioEndpoint.configure() data readCounterAddress = %p",
           descriptor->readCounterAddress);
 
     // An example of free running is when the other side is read or written by hardware DMA
@@ -156,7 +163,7 @@
                              ? descriptor->readCounterAddress // read by other side
                              : descriptor->writeCounterAddress; // written by other side
     mFreeRunning = (remoteCounter == nullptr);
-    ALOGV("AudioEndpoint::configure() mFreeRunning = %d", mFreeRunning ? 1 : 0);
+    ALOGV("AudioEndpoint.configure() mFreeRunning = %d", mFreeRunning ? 1 : 0);
 
     int64_t *readCounterAddress = (descriptor->readCounterAddress == nullptr)
                                   ? &mDataReadCounter
@@ -254,3 +261,7 @@
     ALOGD("AudioEndpoint: data readCounter  = %lld", (long long) mDataQueue->getReadCounter());
     ALOGD("AudioEndpoint: data writeCounter = %lld", (long long) mDataQueue->getWriteCounter());
 }
+
+void AudioEndpoint::eraseDataMemory() {
+    mDataQueue->eraseMemory();
+}
diff --git a/media/libaaudio/src/client/AudioEndpoint.h b/media/libaaudio/src/client/AudioEndpoint.h
index 81a4f7b..f5b67e8 100644
--- a/media/libaaudio/src/client/AudioEndpoint.h
+++ b/media/libaaudio/src/client/AudioEndpoint.h
@@ -86,6 +86,11 @@
 
     int32_t getBufferCapacityInFrames() const;
 
+    /**
+     * Write zeros to the data queue memory.
+     */
+    void eraseDataMemory();
+
     void dump() const;
 
 private:
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 4c7d0f7..2fdbfaf 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -23,7 +23,6 @@
 #define ATRACE_TAG ATRACE_TAG_AUDIO
 
 #include <stdint.h>
-#include <assert.h>
 
 #include <binder/IServiceManager.h>
 
@@ -55,7 +54,7 @@
 // Wait at least this many times longer than the operation should take.
 #define MIN_TIMEOUT_OPERATIONS    4
 
-#define LOG_TIMESTAMPS   0
+#define LOG_TIMESTAMPS            0
 
 AudioStreamInternal::AudioStreamInternal(AAudioServiceInterface  &serviceInterface, bool inService)
         : AudioStream()
@@ -63,9 +62,9 @@
         , mAudioEndpoint()
         , mServiceStreamHandle(AAUDIO_HANDLE_INVALID)
         , mFramesPerBurst(16)
-        , mStreamVolume(1.0f)
         , mInService(inService)
         , mServiceInterface(serviceInterface)
+        , mAtomicTimestamp()
         , mWakeupDelayNanos(AAudioProperty_getWakeupDelayMicros() * AAUDIO_NANOS_PER_MICROSECOND)
         , mMinimumSleepNanos(AAudioProperty_getMinimumSleepMicros() * AAUDIO_NANOS_PER_MICROSECOND)
         {
@@ -79,9 +78,16 @@
 aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
 
     aaudio_result_t result = AAUDIO_OK;
+    int32_t capacity;
     AAudioStreamRequest request;
-    AAudioStreamConfiguration configuration;
+    AAudioStreamConfiguration configurationOutput;
 
+    if (getState() != AAUDIO_STREAM_STATE_UNINITIALIZED) {
+        ALOGE("AudioStreamInternal::open(): already open! state = %d", getState());
+        return AAUDIO_ERROR_INVALID_STATE;
+    }
+
+    // Copy requested parameters to the stream.
     result = AudioStream::open(builder);
     if (result < 0) {
         return result;
@@ -97,103 +103,108 @@
     // Build the request to send to the server.
     request.setUserId(getuid());
     request.setProcessId(getpid());
-    request.setDirection(getDirection());
     request.setSharingModeMatchRequired(isSharingModeMatchRequired());
     request.setInService(mInService);
 
     request.getConfiguration().setDeviceId(getDeviceId());
     request.getConfiguration().setSampleRate(getSampleRate());
     request.getConfiguration().setSamplesPerFrame(getSamplesPerFrame());
+    request.getConfiguration().setDirection(getDirection());
     request.getConfiguration().setSharingMode(getSharingMode());
 
     request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
 
-    mServiceStreamHandle = mServiceInterface.openStream(request, configuration);
+    mServiceStreamHandle = mServiceInterface.openStream(request, configurationOutput);
     if (mServiceStreamHandle < 0) {
         result = mServiceStreamHandle;
-        ALOGE("AudioStreamInternal.open(): openStream() returned %d", result);
-    } else {
-        result = configuration.validate();
-        if (result != AAUDIO_OK) {
-            close();
-            return result;
-        }
-        // Save results of the open.
-        setSampleRate(configuration.getSampleRate());
-        setSamplesPerFrame(configuration.getSamplesPerFrame());
-        setDeviceId(configuration.getDeviceId());
-        setSharingMode(configuration.getSharingMode());
-
-        // Save device format so we can do format conversion and volume scaling together.
-        mDeviceFormat = configuration.getFormat();
-
-        result = mServiceInterface.getStreamDescription(mServiceStreamHandle, mEndPointParcelable);
-        if (result != AAUDIO_OK) {
-            mServiceInterface.closeStream(mServiceStreamHandle);
-            return result;
-        }
-
-        // resolve parcelable into a descriptor
-        result = mEndPointParcelable.resolve(&mEndpointDescriptor);
-        if (result != AAUDIO_OK) {
-            mServiceInterface.closeStream(mServiceStreamHandle);
-            return result;
-        }
-
-        // Configure endpoint based on descriptor.
-        mAudioEndpoint.configure(&mEndpointDescriptor, getDirection());
-
-        mFramesPerBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
-        int32_t capacity = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames;
-
-        // Validate result from server.
-        if (mFramesPerBurst < 16 || mFramesPerBurst > 16 * 1024) {
-            ALOGE("AudioStream::open(): framesPerBurst out of range = %d", mFramesPerBurst);
-            return AAUDIO_ERROR_OUT_OF_RANGE;
-        }
-        if (capacity < mFramesPerBurst || capacity > 32 * 1024) {
-            ALOGE("AudioStream::open(): bufferCapacity out of range = %d", capacity);
-            return AAUDIO_ERROR_OUT_OF_RANGE;
-        }
-
-        mClockModel.setSampleRate(getSampleRate());
-        mClockModel.setFramesPerBurst(mFramesPerBurst);
-
-        if (getDataCallbackProc()) {
-            mCallbackFrames = builder.getFramesPerDataCallback();
-            if (mCallbackFrames > getBufferCapacity() / 2) {
-                ALOGE("AudioStreamInternal::open(): framesPerCallback too big = %d, capacity = %d",
-                      mCallbackFrames, getBufferCapacity());
-                mServiceInterface.closeStream(mServiceStreamHandle);
-                return AAUDIO_ERROR_OUT_OF_RANGE;
-
-            } else if (mCallbackFrames < 0) {
-                ALOGE("AudioStreamInternal::open(): framesPerCallback negative");
-                mServiceInterface.closeStream(mServiceStreamHandle);
-                return AAUDIO_ERROR_OUT_OF_RANGE;
-
-            }
-            if (mCallbackFrames == AAUDIO_UNSPECIFIED) {
-                mCallbackFrames = mFramesPerBurst;
-            }
-
-            int32_t bytesPerFrame = getSamplesPerFrame()
-                                    * AAudioConvert_formatToSizeInBytes(getFormat());
-            int32_t callbackBufferSize = mCallbackFrames * bytesPerFrame;
-            mCallbackBuffer = new uint8_t[callbackBufferSize];
-        }
-
-        setState(AAUDIO_STREAM_STATE_OPEN);
-        // only connect to AudioManager if this is a playback stream running in client process
-        if (!mInService && getDirection() == AAUDIO_DIRECTION_OUTPUT) {
-            init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
-        }
+        ALOGE("AudioStreamInternal::open(): openStream() returned %d", result);
+        return result;
     }
+
+    result = configurationOutput.validate();
+    if (result != AAUDIO_OK) {
+        goto error;
+    }
+    // Save results of the open.
+    setSampleRate(configurationOutput.getSampleRate());
+    setSamplesPerFrame(configurationOutput.getSamplesPerFrame());
+    setDeviceId(configurationOutput.getDeviceId());
+    setSharingMode(configurationOutput.getSharingMode());
+
+    // Save device format so we can do format conversion and volume scaling together.
+    mDeviceFormat = configurationOutput.getFormat();
+
+    result = mServiceInterface.getStreamDescription(mServiceStreamHandle, mEndPointParcelable);
+    if (result != AAUDIO_OK) {
+        goto error;
+    }
+
+    // Resolve parcelable into a descriptor.
+    result = mEndPointParcelable.resolve(&mEndpointDescriptor);
+    if (result != AAUDIO_OK) {
+        goto error;
+    }
+
+    // Configure endpoint based on descriptor.
+    result = mAudioEndpoint.configure(&mEndpointDescriptor, getDirection());
+    if (result != AAUDIO_OK) {
+        goto error;
+    }
+
+    mFramesPerBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
+    capacity = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames;
+
+    // Validate result from server.
+    if (mFramesPerBurst < 16 || mFramesPerBurst > 16 * 1024) {
+        ALOGE("AudioStreamInternal::open(): framesPerBurst out of range = %d", mFramesPerBurst);
+        result = AAUDIO_ERROR_OUT_OF_RANGE;
+        goto error;
+    }
+    if (capacity < mFramesPerBurst || capacity > 32 * 1024) {
+        ALOGE("AudioStreamInternal::open(): bufferCapacity out of range = %d", capacity);
+        result = AAUDIO_ERROR_OUT_OF_RANGE;
+        goto error;
+    }
+
+    mClockModel.setSampleRate(getSampleRate());
+    mClockModel.setFramesPerBurst(mFramesPerBurst);
+
+    if (getDataCallbackProc()) {
+        mCallbackFrames = builder.getFramesPerDataCallback();
+        if (mCallbackFrames > getBufferCapacity() / 2) {
+            ALOGE("AudioStreamInternal::open(): framesPerCallback too big = %d, capacity = %d",
+                  mCallbackFrames, getBufferCapacity());
+            result = AAUDIO_ERROR_OUT_OF_RANGE;
+            goto error;
+
+        } else if (mCallbackFrames < 0) {
+            ALOGE("AudioStreamInternal::open(): framesPerCallback negative");
+            result = AAUDIO_ERROR_OUT_OF_RANGE;
+            goto error;
+
+        }
+        if (mCallbackFrames == AAUDIO_UNSPECIFIED) {
+            mCallbackFrames = mFramesPerBurst;
+        }
+
+        int32_t bytesPerFrame = getSamplesPerFrame()
+                                * AAudioConvert_formatToSizeInBytes(getFormat());
+        int32_t callbackBufferSize = mCallbackFrames * bytesPerFrame;
+        mCallbackBuffer = new uint8_t[callbackBufferSize];
+    }
+
+    setState(AAUDIO_STREAM_STATE_OPEN);
+
+    return result;
+
+error:
+    close();
     return result;
 }
 
 aaudio_result_t AudioStreamInternal::close() {
-    ALOGD("AudioStreamInternal::close(): mServiceStreamHandle = 0x%08X",
+    aaudio_result_t result = AAUDIO_OK;
+    ALOGD("close(): mServiceStreamHandle = 0x%08X",
              mServiceStreamHandle);
     if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
         // Don't close a stream while it is running.
@@ -202,10 +213,10 @@
             requestStop();
             aaudio_stream_state_t nextState;
             int64_t timeoutNanoseconds = MIN_TIMEOUT_NANOS;
-            aaudio_result_t result = waitForStateChange(currentState, &nextState,
+            result = waitForStateChange(currentState, &nextState,
                                                        timeoutNanoseconds);
             if (result != AAUDIO_OK) {
-                ALOGE("AudioStreamInternal::close() waitForStateChange() returned %d %s",
+                ALOGE("close() waitForStateChange() returned %d %s",
                 result, AAudio_convertResultToText(result));
             }
         }
@@ -216,14 +227,16 @@
         mServiceInterface.closeStream(serviceStreamHandle);
         delete[] mCallbackBuffer;
         mCallbackBuffer = nullptr;
+
         setState(AAUDIO_STREAM_STATE_CLOSED);
-        return mEndPointParcelable.close();
+        result = mEndPointParcelable.close();
+        aaudio_result_t result2 = AudioStream::close();
+        return (result != AAUDIO_OK) ? result : result2;
     } else {
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
 }
 
-
 static void *aaudio_callback_thread_proc(void *context)
 {
     AudioStreamInternal *stream = (AudioStreamInternal *)context;
@@ -235,24 +248,46 @@
     }
 }
 
+/*
+ * It normally takes about 20-30 msec to start a stream on the server.
+ * But the first time can take as much as 200-300 msec. The HW
+ * starts right away so by the time the client gets a chance to write into
+ * the buffer, it is already in a deep underflow state. That can cause the
+ * XRunCount to be non-zero, which could lead an app to tune its latency higher.
+ * To avoid this problem, we set a request for the processing code to start the
+ * client stream at the same position as the server stream.
+ * The processing code will then save the current offset
+ * between client and server and apply that to any position given to the app.
+ */
 aaudio_result_t AudioStreamInternal::requestStart()
 {
     int64_t startTime;
-    ALOGD("AudioStreamInternal()::requestStart()");
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
+        ALOGE("requestStart() mServiceStreamHandle invalid");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     if (isActive()) {
+        ALOGE("requestStart() already active");
         return AAUDIO_ERROR_INVALID_STATE;
     }
-    aaudio_stream_state_t originalState = getState();
 
+    aaudio_stream_state_t originalState = getState();
+    if (originalState == AAUDIO_STREAM_STATE_DISCONNECTED) {
+        ALOGE("requestStart() but DISCONNECTED");
+        return AAUDIO_ERROR_DISCONNECTED;
+    }
     setState(AAUDIO_STREAM_STATE_STARTING);
-    aaudio_result_t result = AAudioConvert_androidToAAudioResult(startWithStatus());
+
+    // Clear any stale timestamps from the previous run.
+    drainTimestampsFromService();
+
+    aaudio_result_t result = mServiceInterface.startStream(mServiceStreamHandle);
 
     startTime = AudioClock::getNanoseconds();
     mClockModel.start(startTime);
+    mNeedCatchUp.request();  // Ask data processing code to catch up when first timestamp received.
 
+    // Start data callback thread.
     if (result == AAUDIO_OK && getDataCallbackProc() != nullptr) {
         // Launch the callback loop thread.
         int64_t periodNanos = mCallbackFrames
@@ -297,14 +332,16 @@
 aaudio_result_t AudioStreamInternal::requestStopInternal()
 {
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
-        ALOGE("AudioStreamInternal::requestStopInternal() mServiceStreamHandle invalid = 0x%08X",
+        ALOGE("requestStopInternal() mServiceStreamHandle invalid = 0x%08X",
               mServiceStreamHandle);
         return AAUDIO_ERROR_INVALID_STATE;
     }
 
     mClockModel.stop(AudioClock::getNanoseconds());
     setState(AAUDIO_STREAM_STATE_STOPPING);
-    return AAudioConvert_androidToAAudioResult(stopWithStatus());
+    mAtomicTimestamp.clear();
+
+    return mServiceInterface.stopStream(mServiceStreamHandle);
 }
 
 aaudio_result_t AudioStreamInternal::requestStop()
@@ -319,6 +356,7 @@
 
 aaudio_result_t AudioStreamInternal::registerThread() {
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
+        ALOGE("registerThread() mServiceStreamHandle invalid");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     return mServiceInterface.registerAudioThread(mServiceStreamHandle,
@@ -328,6 +366,7 @@
 
 aaudio_result_t AudioStreamInternal::unregisterThread() {
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
+        ALOGE("unregisterThread() mServiceStreamHandle invalid");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, gettid());
@@ -338,6 +377,7 @@
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
         return AAUDIO_ERROR_INVALID_STATE;
     }
+
     return mServiceInterface.startClient(mServiceStreamHandle, client, clientHandle);
 }
 
@@ -351,15 +391,20 @@
 aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
                            int64_t *framePosition,
                            int64_t *timeNanoseconds) {
-    // TODO Generate in server and pass to client. Return latest.
-    int64_t time = AudioClock::getNanoseconds();
-    *framePosition = mClockModel.convertTimeToPosition(time) + mFramesOffsetFromService;
-    // TODO Get a more accurate timestamp from the service. This code just adds a fudge factor.
-    *timeNanoseconds = time + (6 * AAUDIO_NANOS_PER_MILLISECOND);
-    return AAUDIO_OK;
+    // Generated in server and passed to client. Return latest.
+    if (mAtomicTimestamp.isValid()) {
+        Timestamp timestamp = mAtomicTimestamp.read();
+        int64_t position = timestamp.getPosition() + mFramesOffsetFromService;
+        if (position >= 0) {
+            *framePosition = position;
+            *timeNanoseconds = timestamp.getNanoseconds();
+            return AAUDIO_OK;
+        }
+    }
+    return AAUDIO_ERROR_INVALID_STATE;
 }
 
-aaudio_result_t AudioStreamInternal::updateStateWhileWaiting() {
+aaudio_result_t AudioStreamInternal::updateStateMachine() {
     if (isDataCallbackActive()) {
         return AAUDIO_OK; // state is getting updated by the callback thread read/write call
     }
@@ -371,21 +416,21 @@
     static int64_t oldTime = 0;
     int64_t framePosition = command.timestamp.position;
     int64_t nanoTime = command.timestamp.timestamp;
-    ALOGD("AudioStreamInternal: timestamp says framePosition = %08lld at nanoTime %lld",
+    ALOGD("logTimestamp: timestamp says framePosition = %8lld at nanoTime %lld",
          (long long) framePosition,
          (long long) nanoTime);
     int64_t nanosDelta = nanoTime - oldTime;
     if (nanosDelta > 0 && oldTime > 0) {
         int64_t framesDelta = framePosition - oldPosition;
         int64_t rate = (framesDelta * AAUDIO_NANOS_PER_SECOND) / nanosDelta;
-        ALOGD("AudioStreamInternal: framesDelta = %08lld, nanosDelta = %08lld, rate = %lld",
+        ALOGD("logTimestamp:     framesDelta = %8lld, nanosDelta = %8lld, rate = %lld",
               (long long) framesDelta, (long long) nanosDelta, (long long) rate);
     }
     oldPosition = framePosition;
     oldTime = nanoTime;
 }
 
-aaudio_result_t AudioStreamInternal::onTimestampFromServer(AAudioServiceMessage *message) {
+aaudio_result_t AudioStreamInternal::onTimestampService(AAudioServiceMessage *message) {
 #if LOG_TIMESTAMPS
     logTimestamp(*message);
 #endif
@@ -393,23 +438,29 @@
     return AAUDIO_OK;
 }
 
+aaudio_result_t AudioStreamInternal::onTimestampHardware(AAudioServiceMessage *message) {
+    Timestamp timestamp(message->timestamp.position, message->timestamp.timestamp);
+    mAtomicTimestamp.write(timestamp);
+    return AAUDIO_OK;
+}
+
 aaudio_result_t AudioStreamInternal::onEventFromServer(AAudioServiceMessage *message) {
     aaudio_result_t result = AAUDIO_OK;
     switch (message->event.event) {
         case AAUDIO_SERVICE_EVENT_STARTED:
-            ALOGD("AudioStreamInternal::onEventFromServergot() AAUDIO_SERVICE_EVENT_STARTED");
+            ALOGD("AudioStreamInternal::onEventFromServer() got AAUDIO_SERVICE_EVENT_STARTED");
             if (getState() == AAUDIO_STREAM_STATE_STARTING) {
                 setState(AAUDIO_STREAM_STATE_STARTED);
             }
             break;
         case AAUDIO_SERVICE_EVENT_PAUSED:
-            ALOGD("AudioStreamInternal::onEventFromServergot() AAUDIO_SERVICE_EVENT_PAUSED");
+            ALOGD("AudioStreamInternal::onEventFromServer() got AAUDIO_SERVICE_EVENT_PAUSED");
             if (getState() == AAUDIO_STREAM_STATE_PAUSING) {
                 setState(AAUDIO_STREAM_STATE_PAUSED);
             }
             break;
         case AAUDIO_SERVICE_EVENT_STOPPED:
-            ALOGD("AudioStreamInternal::onEventFromServergot() AAUDIO_SERVICE_EVENT_STOPPED");
+            ALOGD("AudioStreamInternal::onEventFromServer() got AAUDIO_SERVICE_EVENT_STOPPED");
             if (getState() == AAUDIO_STREAM_STATE_STOPPING) {
                 setState(AAUDIO_STREAM_STATE_STOPPED);
             }
@@ -426,10 +477,14 @@
             setState(AAUDIO_STREAM_STATE_CLOSED);
             break;
         case AAUDIO_SERVICE_EVENT_DISCONNECTED:
+            // Prevent hardware from looping on old data and making buzzing sounds.
+            if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
+                mAudioEndpoint.eraseDataMemory();
+            }
             result = AAUDIO_ERROR_DISCONNECTED;
             setState(AAUDIO_STREAM_STATE_DISCONNECTED);
             ALOGW("WARNING - AudioStreamInternal::onEventFromServer()"
-                          " AAUDIO_SERVICE_EVENT_DISCONNECTED");
+                          " AAUDIO_SERVICE_EVENT_DISCONNECTED - FIFO cleared");
             break;
         case AAUDIO_SERVICE_EVENT_VOLUME:
             mStreamVolume = (float)message->event.dataDouble;
@@ -445,6 +500,34 @@
     return result;
 }
 
+aaudio_result_t AudioStreamInternal::drainTimestampsFromService() {
+    aaudio_result_t result = AAUDIO_OK;
+
+    while (result == AAUDIO_OK) {
+        AAudioServiceMessage message;
+        if (mAudioEndpoint.readUpCommand(&message) != 1) {
+            break; // no command this time, no problem
+        }
+        switch (message.what) {
+            // ignore most messages
+            case AAudioServiceMessage::code::TIMESTAMP_SERVICE:
+            case AAudioServiceMessage::code::TIMESTAMP_HARDWARE:
+                break;
+
+            case AAudioServiceMessage::code::EVENT:
+                result = onEventFromServer(&message);
+                break;
+
+            default:
+                ALOGE("WARNING - drainTimestampsFromService() Unrecognized what = %d",
+                      (int) message.what);
+                result = AAUDIO_ERROR_INTERNAL;
+                break;
+        }
+    }
+    return result;
+}
+
 // Process all the commands coming from the server.
 aaudio_result_t AudioStreamInternal::processCommands() {
     aaudio_result_t result = AAUDIO_OK;
@@ -456,8 +539,12 @@
             break; // no command this time, no problem
         }
         switch (message.what) {
-        case AAudioServiceMessage::code::TIMESTAMP:
-            result = onTimestampFromServer(&message);
+        case AAudioServiceMessage::code::TIMESTAMP_SERVICE:
+            result = onTimestampService(&message);
+            break;
+
+        case AAudioServiceMessage::code::TIMESTAMP_HARDWARE:
+            result = onTimestampHardware(&message);
             break;
 
         case AAudioServiceMessage::code::EVENT:
@@ -465,7 +552,7 @@
             break;
 
         default:
-            ALOGE("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d",
+            ALOGE("WARNING - processCommands() Unrecognized what = %d",
                  (int) message.what);
             result = AAUDIO_ERROR_INTERNAL;
             break;
@@ -517,12 +604,19 @@
                 wakeTimeNanos += mWakeupDelayNanos;
             }
 
+            currentTimeNanos = AudioClock::getNanoseconds();
+            int64_t earliestWakeTime = currentTimeNanos + mMinimumSleepNanos;
+            // Guarantee a minimum sleep time.
+            if (wakeTimeNanos < earliestWakeTime) {
+                wakeTimeNanos = earliestWakeTime;
+            }
+
             if (wakeTimeNanos > deadlineNanos) {
                 // If we time out, just return the framesWritten so far.
                 // TODO remove after we fix the deadline bug
                 ALOGW("AudioStreamInternal::processData(): entered at %lld nanos, currently %lld",
                       (long long) entryTimeNanos, (long long) currentTimeNanos);
-                ALOGW("AudioStreamInternal::processData(): timed out after %lld nanos",
+                ALOGW("AudioStreamInternal::processData(): TIMEOUT after %lld nanos",
                       (long long) timeoutNanoseconds);
                 ALOGW("AudioStreamInternal::processData(): wakeTime = %lld, deadline = %lld nanos",
                       (long long) wakeTimeNanos, (long long) deadlineNanos);
@@ -533,13 +627,6 @@
                 break;
             }
 
-            currentTimeNanos = AudioClock::getNanoseconds();
-            int64_t earliestWakeTime = currentTimeNanos + mMinimumSleepNanos;
-            // Guarantee a minimum sleep time.
-            if (wakeTimeNanos < earliestWakeTime) {
-                wakeTimeNanos = earliestWakeTime;
-            }
-
             if (ATRACE_ENABLED()) {
                 int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable();
                 ATRACE_INT(fifoName, fullFrames);
@@ -576,7 +663,7 @@
     }
 
     aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(requestedFrames, &actualFrames);
-    ALOGD("AudioStreamInternal::setBufferSize() req = %d => %d", requestedFrames, actualFrames);
+    ALOGD("setBufferSize() req = %d => %d", requestedFrames, actualFrames);
     if (result < 0) {
         return result;
     } else {
@@ -599,32 +686,3 @@
 aaudio_result_t AudioStreamInternal::joinThread(void** returnArg) {
     return AudioStream::joinThread(returnArg, calculateReasonableTimeout(getFramesPerBurst()));
 }
-
-void AudioStreamInternal::doSetVolume() {
-    // No pan and only left volume is taken into account from IPLayer interface
-    mVolumeRamp.setTarget(mStreamVolume * mVolumeMultiplierL /* * mPanMultiplierL */);
-}
-
-
-//------------------------------------------------------------------------------
-// Implementation of PlayerBase
-status_t AudioStreamInternal::playerStart() {
-    return AAudioConvert_aaudioToAndroidStatus(mServiceInterface.startStream(mServiceStreamHandle));
-}
-
-status_t AudioStreamInternal::playerPause() {
-    return AAudioConvert_aaudioToAndroidStatus(mServiceInterface.pauseStream(mServiceStreamHandle));
-}
-
-status_t AudioStreamInternal::playerStop() {
-    return AAudioConvert_aaudioToAndroidStatus(mServiceInterface.stopStream(mServiceStreamHandle));
-}
-
-status_t AudioStreamInternal::playerSetVolume() {
-    doSetVolume();
-    return NO_ERROR;
-}
-
-void AudioStreamInternal::destroy() {
-    baseDestroy();
-}
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index 1b991de..47024c0 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -18,7 +18,6 @@
 #define ANDROID_AAUDIO_AUDIO_STREAM_INTERNAL_H
 
 #include <stdint.h>
-#include <media/PlayerBase.h>
 #include <aaudio/AAudio.h>
 
 #include "binding/IAAudioService.h"
@@ -36,7 +35,7 @@
 namespace aaudio {
 
 // A stream that talks to the AAudioService or directly to a HAL.
-class AudioStreamInternal : public AudioStream, public android::PlayerBase  {
+class AudioStreamInternal : public AudioStream {
 
 public:
     AudioStreamInternal(AAudioServiceInterface  &serviceInterface, bool inService);
@@ -50,7 +49,7 @@
                                        int64_t *framePosition,
                                        int64_t *timeNanoseconds) override;
 
-    virtual aaudio_result_t updateStateWhileWaiting() override;
+    virtual aaudio_result_t updateStateMachine() override;
 
     aaudio_result_t open(const AudioStreamBuilder &builder) override;
 
@@ -85,14 +84,15 @@
     // Calculate timeout based on framesPerBurst
     int64_t calculateReasonableTimeout();
 
-    //PlayerBase virtuals
-    virtual void destroy();
-
     aaudio_result_t startClient(const android::AudioClient& client,
                                 audio_port_handle_t *clientHandle);
 
     aaudio_result_t stopClient(audio_port_handle_t clientHandle);
 
+    aaudio_handle_t getServiceHandle() const {
+        return mServiceStreamHandle;
+    }
+
 protected:
 
     aaudio_result_t processData(void *buffer,
@@ -111,32 +111,29 @@
                             int64_t currentTimeNanos,
                             int64_t *wakeTimePtr) = 0;
 
+    aaudio_result_t drainTimestampsFromService();
+
     aaudio_result_t processCommands();
 
     aaudio_result_t requestStopInternal();
 
     aaudio_result_t stopCallback();
 
+    virtual void advanceClientToMatchServerPosition() = 0;
 
     virtual void onFlushFromServer() {}
 
     aaudio_result_t onEventFromServer(AAudioServiceMessage *message);
 
-    aaudio_result_t onTimestampFromServer(AAudioServiceMessage *message);
+    aaudio_result_t onTimestampService(AAudioServiceMessage *message);
+
+    aaudio_result_t onTimestampHardware(AAudioServiceMessage *message);
 
     void logTimestamp(AAudioServiceMessage &message);
 
     // Calculate timeout for an operation involving framesPerOperation.
     int64_t calculateReasonableTimeout(int32_t framesPerOperation);
 
-    void doSetVolume();
-
-    //PlayerBase virtuals
-    virtual status_t playerStart();
-    virtual status_t playerPause();
-    virtual status_t playerStop();
-    virtual status_t playerSetVolume();
-
     aaudio_format_t          mDeviceFormat = AAUDIO_FORMAT_UNSPECIFIED;
 
     IsochronousClockModel    mClockModel;      // timing model for chasing the HAL
@@ -147,9 +144,6 @@
     int32_t                  mFramesPerBurst;     // frames per HAL transfer
     int32_t                  mXRunCount = 0;      // how many underrun events?
 
-    LinearRamp               mVolumeRamp;
-    float                    mStreamVolume;
-
     // Offset from underlying frame position.
     int64_t                  mFramesOffsetFromService = 0; // offset for timestamps
 
@@ -161,6 +155,12 @@
 
     AAudioServiceInterface  &mServiceInterface;   // abstract interface to the service
 
+    SimpleDoubleBuffer<Timestamp>  mAtomicTimestamp;
+
+    AtomicRequestor          mNeedCatchUp;   // Ask read() or write() to sync on first timestamp.
+
+    float                    mStreamVolume = 1.0f;
+
 private:
     /*
      * Asynchronous write with data conversion.
@@ -181,6 +181,8 @@
 
     AudioEndpointParcelable  mEndPointParcelable; // description of the buffers filled by service
     EndpointDescriptor       mEndpointDescriptor; // buffer description with resolved addresses
+
+    int64_t                  mServiceLatencyNanos = 0;
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 7b1e53e..b792ecd 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -39,6 +39,21 @@
 
 AudioStreamInternalCapture::~AudioStreamInternalCapture() {}
 
+void AudioStreamInternalCapture::advanceClientToMatchServerPosition() {
+    int64_t readCounter = mAudioEndpoint.getDataReadCounter();
+    int64_t writeCounter = mAudioEndpoint.getDataWriteCounter();
+
+    // Bump offset so caller does not see the retrograde motion in getFramesRead().
+    int64_t offset = readCounter - writeCounter;
+    mFramesOffsetFromService += offset;
+    ALOGD("advanceClientToMatchServerPosition() readN = %lld, writeN = %lld, offset = %lld",
+          (long long)readCounter, (long long)writeCounter, (long long)mFramesOffsetFromService);
+
+    // Force readCounter to match writeCounter.
+    // This is because we cannot change the write counter in the hardware.
+    mAudioEndpoint.setDataReadCounter(writeCounter);
+}
+
 // Write the data, block if needed and timeoutMillis > 0
 aaudio_result_t AudioStreamInternalCapture::read(void *buffer, int32_t numFrames,
                                                int64_t timeoutNanoseconds)
@@ -57,6 +72,18 @@
     const char *traceName = "aaRdNow";
     ATRACE_BEGIN(traceName);
 
+    if (mClockModel.isStarting()) {
+        // Still haven't got any timestamps from server.
+        // Keep waiting until we get some valid timestamps then start writing to the
+        // current buffer position.
+        ALOGD("processDataNow() wait for valid timestamps");
+        // Sleep very briefly and hope we get a timestamp soon.
+        *wakeTimePtr = currentNanoTime + (2000 * AAUDIO_NANOS_PER_MICROSECOND);
+        ATRACE_END();
+        return 0;
+    }
+    // If we have gotten this far then we have at least one timestamp from server.
+
     if (mAudioEndpoint.isFreeRunning()) {
         //ALOGD("AudioStreamInternalCapture::processDataNow() - update remote counter");
         // Update data queue based on the timing model.
@@ -65,6 +92,14 @@
         mAudioEndpoint.setDataWriteCounter(estimatedRemoteCounter);
     }
 
+    // This code assumes that we have already received valid timestamps.
+    if (mNeedCatchUp.isRequested()) {
+        // Catch an MMAP pointer that is already advancing.
+        // This will avoid initial underruns caused by a slow cold start.
+        advanceClientToMatchServerPosition();
+        mNeedCatchUp.acknowledge();
+    }
+
     // If the write index passed the read index then consider it an overrun.
     if (mAudioEndpoint.getEmptyFramesAvailable() < 0) {
         mXRunCount++;
@@ -100,8 +135,8 @@
                 // Calculate frame position based off of the readCounter because
                 // the writeCounter might have just advanced in the background,
                 // causing us to sleep until a later burst.
-                int64_t nextReadPosition = mAudioEndpoint.getDataReadCounter() + mFramesPerBurst;
-                wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
+                int64_t nextPosition = mAudioEndpoint.getDataReadCounter() + mFramesPerBurst;
+                wakeTime = mClockModel.convertPositionToTime(nextPosition);
             }
                 break;
             default:
@@ -186,8 +221,7 @@
 }
 
 int64_t AudioStreamInternalCapture::getFramesRead() {
-    int64_t frames = mAudioEndpoint.getDataWriteCounter()
-                               + mFramesOffsetFromService;
+    int64_t frames = mAudioEndpoint.getDataReadCounter() + mFramesOffsetFromService;
     //ALOGD("AudioStreamInternalCapture::getFramesRead() returns %lld", (long long)frames);
     return frames;
 }
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.h b/media/libaaudio/src/client/AudioStreamInternalCapture.h
index 17f37e8..294dbaf 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.h
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.h
@@ -46,6 +46,8 @@
     }
 protected:
 
+    void advanceClientToMatchServerPosition() override;
+
 /**
  * Low level data processing that will not block. It will just read or write as much as it can.
  *
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 31e0a40..1e02eee 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -48,7 +48,8 @@
 
     mClockModel.stop(AudioClock::getNanoseconds());
     setState(AAUDIO_STREAM_STATE_PAUSING);
-    return AAudioConvert_androidToAAudioResult(pauseWithStatus());
+    mAtomicTimestamp.clear();
+    return mServiceInterface.pauseStream(mServiceStreamHandle);
 }
 
 aaudio_result_t AudioStreamInternalPlay::requestPause()
@@ -72,21 +73,25 @@
     return mServiceInterface.flushStream(mServiceStreamHandle);
 }
 
-void AudioStreamInternalPlay::onFlushFromServer() {
+void AudioStreamInternalPlay::advanceClientToMatchServerPosition() {
     int64_t readCounter = mAudioEndpoint.getDataReadCounter();
     int64_t writeCounter = mAudioEndpoint.getDataWriteCounter();
 
     // Bump offset so caller does not see the retrograde motion in getFramesRead().
-    int64_t framesFlushed = writeCounter - readCounter;
-    mFramesOffsetFromService += framesFlushed;
-    ALOGD("AudioStreamInternal::onFlushFromServer() readN = %lld, writeN = %lld, offset = %lld",
+    int64_t offset = writeCounter - readCounter;
+    mFramesOffsetFromService += offset;
+    ALOGD("advanceClientToMatchServerPosition() readN = %lld, writeN = %lld, offset = %lld",
           (long long)readCounter, (long long)writeCounter, (long long)mFramesOffsetFromService);
 
-    // Flush written frames by forcing writeCounter to readCounter.
-    // This is because we cannot move the read counter in the hardware.
+    // Force writeCounter to match readCounter.
+    // This is because we cannot change the read counter in the hardware.
     mAudioEndpoint.setDataWriteCounter(readCounter);
 }
 
+void AudioStreamInternalPlay::onFlushFromServer() {
+    advanceClientToMatchServerPosition();
+}
+
 // Write the data, block if needed and timeoutMillis > 0
 aaudio_result_t AudioStreamInternalPlay::write(const void *buffer, int32_t numFrames,
                                            int64_t timeoutNanoseconds)
@@ -106,6 +111,18 @@
     const char *traceName = "aaWrNow";
     ATRACE_BEGIN(traceName);
 
+    if (mClockModel.isStarting()) {
+        // Still haven't got any timestamps from server.
+        // Keep waiting until we get some valid timestamps then start writing to the
+        // current buffer position.
+        ALOGD("processDataNow() wait for valid timestamps");
+        // Sleep very briefly and hope we get a timestamp soon.
+        *wakeTimePtr = currentNanoTime + (2000 * AAUDIO_NANOS_PER_MICROSECOND);
+        ATRACE_END();
+        return 0;
+    }
+    // If we have gotten this far then we have at least one timestamp from server.
+
     // If a DMA channel or DSP is reading the other end then we have to update the readCounter.
     if (mAudioEndpoint.isFreeRunning()) {
         // Update data queue based on the timing model.
@@ -114,6 +131,13 @@
         mAudioEndpoint.setDataReadCounter(estimatedReadCounter);
     }
 
+    if (mNeedCatchUp.isRequested()) {
+        // Catch an MMAP pointer that is already advancing.
+        // This will avoid initial underruns caused by a slow cold start.
+        advanceClientToMatchServerPosition();
+        mNeedCatchUp.acknowledge();
+    }
+
     // If the read index passed the write index then consider it an underrun.
     if (mAudioEndpoint.getFullFramesAvailable() < 0) {
         mXRunCount++;
@@ -153,9 +177,9 @@
                 // Calculate frame position based off of the writeCounter because
                 // the readCounter might have just advanced in the background,
                 // causing us to sleep until a later burst.
-                int64_t nextReadPosition = mAudioEndpoint.getDataWriteCounter() + mFramesPerBurst
+                int64_t nextPosition = mAudioEndpoint.getDataWriteCounter() + mFramesPerBurst
                         - mAudioEndpoint.getBufferSizeInFrames();
-                wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
+                wakeTime = mClockModel.convertPositionToTime(nextPosition);
             }
                 break;
             default:
@@ -266,7 +290,6 @@
     return framesWritten;
 }
 
-
 int64_t AudioStreamInternalPlay::getFramesRead()
 {
     int64_t framesReadHardware;
@@ -340,3 +363,10 @@
           result, (int) isActive());
     return NULL;
 }
+
+//------------------------------------------------------------------------------
+// Implementation of PlayerBase
+status_t AudioStreamInternalPlay::doSetVolume() {
+    mVolumeRamp.setTarget(mStreamVolume * getDuckAndMuteVolume());
+    return android::NO_ERROR;
+}
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.h b/media/libaaudio/src/client/AudioStreamInternalPlay.h
index e59d02c..d5c1b1e 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.h
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.h
@@ -54,8 +54,12 @@
 
     aaudio_result_t requestPauseInternal();
 
+    void advanceClientToMatchServerPosition() override;
+
     void onFlushFromServer() override;
 
+    android::status_t doSetVolume() override;
+
 /**
  * Low level write that will not block. It will just write as much as it can.
  *
@@ -78,6 +82,9 @@
                                            int32_t numFrames);
 
     int64_t                  mLastFramesRead = 0; // used to prevent retrograde motion
+
+    LinearRamp               mVolumeRamp;
+
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/client/IsochronousClockModel.cpp b/media/libaaudio/src/client/IsochronousClockModel.cpp
index c06c8a9..bac69f1 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.cpp
+++ b/media/libaaudio/src/client/IsochronousClockModel.cpp
@@ -48,19 +48,26 @@
 }
 
 void IsochronousClockModel::start(int64_t nanoTime) {
-    ALOGD("IsochronousClockModel::start(nanos = %lld)\n", (long long) nanoTime);
+    ALOGV("IsochronousClockModel::start(nanos = %lld)\n", (long long) nanoTime);
     mMarkerNanoTime = nanoTime;
     mState = STATE_STARTING;
 }
 
 void IsochronousClockModel::stop(int64_t nanoTime) {
-    ALOGD("IsochronousClockModel::stop(nanos = %lld)\n", (long long) nanoTime);
+    ALOGV("IsochronousClockModel::stop(nanos = %lld)\n", (long long) nanoTime);
     setPositionAndTime(convertTimeToPosition(nanoTime), nanoTime);
     // TODO should we set position?
     mState = STATE_STOPPED;
 }
 
+bool IsochronousClockModel::isStarting() {
+    return mState == STATE_STARTING;
+}
+
 void IsochronousClockModel::processTimestamp(int64_t framePosition, int64_t nanoTime) {
+//    ALOGD("processTimestamp() - framePosition = %lld at nanoTime %llu",
+//         (long long)framePosition,
+//         (long long)nanoTime);
     int64_t framesDelta = framePosition - mMarkerFramePosition;
     int64_t nanosDelta = nanoTime - mMarkerNanoTime;
     if (nanosDelta < 1000) {
@@ -70,9 +77,6 @@
 //    ALOGD("processTimestamp() - mMarkerFramePosition = %lld at mMarkerNanoTime %llu",
 //         (long long)mMarkerFramePosition,
 //         (long long)mMarkerNanoTime);
-//    ALOGD("processTimestamp() - framePosition = %lld at nanoTime %llu",
-//         (long long)framePosition,
-//         (long long)nanoTime);
 
     int64_t expectedNanosDelta = convertDeltaPositionToTime(framesDelta);
 //    ALOGD("processTimestamp() - expectedNanosDelta = %lld, nanosDelta = %llu",
@@ -116,6 +120,8 @@
     default:
         break;
     }
+
+//    ALOGD("processTimestamp() - mState = %d", mState);
 }
 
 void IsochronousClockModel::setSampleRate(int32_t sampleRate) {
diff --git a/media/libaaudio/src/client/IsochronousClockModel.h b/media/libaaudio/src/client/IsochronousClockModel.h
index 585f53a..7182376 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.h
+++ b/media/libaaudio/src/client/IsochronousClockModel.h
@@ -36,6 +36,8 @@
     void start(int64_t nanoTime);
     void stop(int64_t nanoTime);
 
+    bool isStarting();
+
     void processTimestamp(int64_t framePosition, int64_t nanoTime);
 
     /**
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 3f5de77..1eaee81 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -24,15 +24,14 @@
 #include <aaudio/AAudio.h>
 #include <aaudio/AAudioTesting.h>
 
+#include "AudioClock.h"
 #include "AudioStreamBuilder.h"
 #include "AudioStream.h"
-#include "AudioClock.h"
+#include "binding/AAudioCommon.h"
 #include "client/AudioStreamInternal.h"
-#include "HandleTracker.h"
 
 using namespace aaudio;
 
-
 // Macros for common code that includes a return.
 // TODO Consider using do{}while(0) construct. I tried but it hung AndroidStudio
 #define CONVERT_BUILDER_HANDLE_OR_RETURN() \
@@ -101,7 +100,6 @@
  */
 static aaudio_policy_t s_MMapPolicy = AAUDIO_UNSPECIFIED;
 
-
 static AudioStream *convertAAudioStreamToAudioStream(AAudioStream* stream)
 {
     return (AudioStream*) stream;
@@ -144,17 +142,16 @@
 }
 
 AAUDIO_API void AAudioStreamBuilder_setChannelCount(AAudioStreamBuilder* builder,
-                                                       int32_t channelCount)
+                                                    int32_t channelCount)
 {
     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
     streamBuilder->setSamplesPerFrame(channelCount);
 }
 
 AAUDIO_API void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder,
-                                                       int32_t samplesPerFrame)
+                                                       int32_t channelCount)
 {
-    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
-    streamBuilder->setSamplesPerFrame(samplesPerFrame);
+    AAudioStreamBuilder_setChannelCount(builder, channelCount);
 }
 
 AAUDIO_API void AAudioStreamBuilder_setDirection(AAudioStreamBuilder* builder,
@@ -221,6 +218,7 @@
     ALOGD("AAudioStreamBuilder_openStream() returns %d = %s for (%p) ----------------",
           result, AAudio_convertResultToText(result), audioStream);
     if (result == AAUDIO_OK) {
+        audioStream->registerPlayerBase();
         *streamPtr = (AAudioStream*) audioStream;
     } else {
         *streamPtr = nullptr;
@@ -244,6 +242,7 @@
     ALOGD("AAudioStream_close(%p)", stream);
     if (audioStream != nullptr) {
         audioStream->close();
+        audioStream->unregisterPlayerBase();
         delete audioStream;
         return AAUDIO_OK;
     }
@@ -254,8 +253,8 @@
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
     ALOGD("AAudioStream_requestStart(%p) called --------------", stream);
-    aaudio_result_t result = audioStream->requestStart();
-    ALOGD("AAudioStream_requestStart(%p) returned ------------", stream);
+    aaudio_result_t result = audioStream->systemStart();
+    ALOGD("AAudioStream_requestStart(%p) returned %d ---------", stream, result);
     return result;
 }
 
@@ -263,7 +262,7 @@
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
     ALOGD("AAudioStream_requestPause(%p)", stream);
-    return audioStream->requestPause();
+    return audioStream->systemPause();
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_requestFlush(AAudioStream* stream)
@@ -277,7 +276,7 @@
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
     ALOGD("AAudioStream_requestStop(%p)", stream);
-    return audioStream->requestStop();
+    return audioStream->systemStop();
 }
 
 AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange(AAudioStream* stream,
@@ -359,8 +358,7 @@
 
 AAUDIO_API int32_t AAudioStream_getSamplesPerFrame(AAudioStream* stream)
 {
-    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    return audioStream->getSamplesPerFrame();
+    return AAudioStream_getChannelCount(stream);
 }
 
 AAUDIO_API aaudio_stream_state_t AAudioStream_getState(AAudioStream* stream)
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index 65c2b46..82445e7 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -34,6 +34,16 @@
 AAudioStreamParameters::AAudioStreamParameters() {}
 AAudioStreamParameters::~AAudioStreamParameters() {}
 
+void AAudioStreamParameters::copyFrom(const AAudioStreamParameters &other) {
+    mSamplesPerFrame = other.mSamplesPerFrame;
+    mSampleRate      = other.mSampleRate;
+    mDeviceId        = other.mDeviceId;
+    mSharingMode     = other.mSharingMode;
+    mAudioFormat     = other.mAudioFormat;
+    mDirection       = other.mDirection;
+    mBufferCapacity  = other.mBufferCapacity;
+}
+
 aaudio_result_t AAudioStreamParameters::validate() const {
     if (mSamplesPerFrame != AAUDIO_UNSPECIFIED
         && (mSamplesPerFrame < SAMPLES_PER_FRAME_MIN || mSamplesPerFrame > SAMPLES_PER_FRAME_MAX)) {
@@ -78,6 +88,16 @@
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
 
+    switch (mDirection) {
+        case AAUDIO_DIRECTION_INPUT:
+        case AAUDIO_DIRECTION_OUTPUT:
+            break; // valid
+        default:
+            ALOGE("AAudioStreamParameters: direction not valid = %d", mDirection);
+            return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+            // break;
+    }
+
     return AAUDIO_OK;
 }
 
@@ -87,5 +107,7 @@
     ALOGD("AAudioStreamParameters mSamplesPerFrame = %d", mSamplesPerFrame);
     ALOGD("AAudioStreamParameters mSharingMode     = %d", (int)mSharingMode);
     ALOGD("AAudioStreamParameters mAudioFormat     = %d", (int)mAudioFormat);
+    ALOGD("AAudioStreamParameters mDirection       = %d", mDirection);
     ALOGD("AAudioStreamParameters mBufferCapacity  = %d", mBufferCapacity);
-}
\ No newline at end of file
+}
+
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.h b/media/libaaudio/src/core/AAudioStreamParameters.h
index 97379cc..5e67c93 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.h
+++ b/media/libaaudio/src/core/AAudioStreamParameters.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 
 #include <aaudio/AAudio.h>
+#include <utility/AAudioUtilities.h>
 
 namespace aaudio {
 
@@ -79,6 +80,24 @@
         mBufferCapacity = frames;
     }
 
+    aaudio_direction_t getDirection() const {
+        return mDirection;
+    }
+
+    void setDirection(aaudio_direction_t direction) {
+        mDirection = direction;
+    }
+
+    int32_t calculateBytesPerFrame() const {
+        return getSamplesPerFrame() * AAudioConvert_formatToSizeInBytes(getFormat());
+    }
+
+    /**
+     * Copy variables defined in other AAudioStreamParameters instance to this one.
+     * @param other
+     */
+    void copyFrom(const AAudioStreamParameters &other);
+
     virtual aaudio_result_t validate() const;
 
     void dump() const;
@@ -89,9 +108,10 @@
     int32_t                    mDeviceId        = AAUDIO_UNSPECIFIED;
     aaudio_sharing_mode_t      mSharingMode     = AAUDIO_SHARING_MODE_SHARED;
     aaudio_format_t            mAudioFormat     = AAUDIO_FORMAT_UNSPECIFIED;
+    aaudio_direction_t         mDirection       = AAUDIO_DIRECTION_OUTPUT;
     int32_t                    mBufferCapacity  = AAUDIO_UNSPECIFIED;
 };
 
 } /* namespace aaudio */
 
-#endif //AAUDIO_STREAM_PARAMETERS_H
\ No newline at end of file
+#endif //AAUDIO_STREAM_PARAMETERS_H
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 4859c69..8dcc37a 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AAudio"
+#define LOG_TAG "AAudioStream"
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
@@ -29,13 +29,26 @@
 using namespace aaudio;
 
 AudioStream::AudioStream()
-        : mCallbackEnabled(false)
+        : mPlayerBase(new MyPlayerBase(this))
 {
     // mThread is a pthread_t of unknown size so we need memset.
     memset(&mThread, 0, sizeof(mThread));
     setPeriodNanoseconds(0);
 }
 
+AudioStream::~AudioStream() {
+    ALOGD("destroying %p, state = %s", this, AAudio_convertStreamStateToText(getState()));
+    // If the stream is deleted when OPEN or in use then audio resources will leak.
+    // This would indicate an internal error. So we want to find this ASAP.
+    LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
+                          || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
+                          || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
+                        "aaudio stream still in use, state = %s",
+                        AAudio_convertStreamStateToText(getState()));
+
+    mPlayerBase->clearParentReference(); // remove reference to this AudioStream
+}
+
 static const char *AudioStream_convertSharingModeToShortText(aaudio_sharing_mode_t sharingMode) {
     const char *result;
     switch (sharingMode) {
@@ -90,15 +103,12 @@
     return AAUDIO_OK;
 }
 
-AudioStream::~AudioStream() {
-    close();
-}
 
 aaudio_result_t AudioStream::waitForStateChange(aaudio_stream_state_t currentState,
                                                 aaudio_stream_state_t *nextState,
                                                 int64_t timeoutNanoseconds)
 {
-    aaudio_result_t result = updateStateWhileWaiting();
+    aaudio_result_t result = updateStateMachine();
     if (result != AAUDIO_OK) {
         return result;
     }
@@ -112,7 +122,7 @@
         AudioClock::sleepForNanos(durationNanos);
         timeoutNanoseconds -= durationNanos;
 
-        aaudio_result_t result = updateStateWhileWaiting();
+        aaudio_result_t result = updateStateMachine();
         if (result != AAUDIO_OK) {
             return result;
         }
@@ -153,6 +163,7 @@
                                      void* threadArg)
 {
     if (mHasThread) {
+        ALOGE("AudioStream::createThread() - mHasThread already true");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     if (threadProc == nullptr) {
@@ -174,6 +185,7 @@
 aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanoseconds)
 {
     if (!mHasThread) {
+        ALOGE("AudioStream::joinThread() - but has no thread");
         return AAUDIO_ERROR_INVALID_STATE;
     }
 #if 0
@@ -187,3 +199,38 @@
     return err ? AAudioConvert_androidToAAudioResult(-errno) : mThreadRegistrationResult;
 }
 
+
+#if AAUDIO_USE_VOLUME_SHAPER
+android::media::VolumeShaper::Status AudioStream::applyVolumeShaper(
+        const android::media::VolumeShaper::Configuration& configuration __unused,
+        const android::media::VolumeShaper::Operation& operation __unused) {
+    ALOGW("applyVolumeShaper() is not supported");
+    return android::media::VolumeShaper::Status::ok();
+}
+#endif
+
+AudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
+}
+
+AudioStream::MyPlayerBase::~MyPlayerBase() {
+    ALOGV("MyPlayerBase::~MyPlayerBase(%p) deleted", this);
+}
+
+void AudioStream::MyPlayerBase::registerWithAudioManager() {
+    if (!mRegistered) {
+        init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
+        mRegistered = true;
+    }
+}
+
+void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
+    if (mRegistered) {
+        baseDestroy();
+        mRegistered = false;
+    }
+}
+
+
+void AudioStream::MyPlayerBase::destroy() {
+    unregisterWithAudioManager();
+}
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index e5fdcc6..34202d2 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -21,10 +21,18 @@
 #include <mutex>
 #include <stdint.h>
 #include <aaudio/AAudio.h>
+#include <binder/IServiceManager.h>
+#include <binder/Status.h>
+#include <utils/StrongPointer.h>
 
+#include "media/VolumeShaper.h"
+#include "media/PlayerBase.h"
 #include "utility/AAudioUtilities.h"
 #include "utility/MonotonicCounter.h"
 
+// Cannot get android::media::VolumeShaper to compile!
+#define AAUDIO_USE_VOLUME_SHAPER  0
+
 namespace aaudio {
 
 typedef void *(*aaudio_audio_thread_proc_t)(void *);
@@ -68,10 +76,10 @@
 
 
     /**
-     * Update state while in the middle of waitForStateChange()
+     * Update state machine.()
      * @return
      */
-    virtual aaudio_result_t updateStateWhileWaiting() = 0;
+    virtual aaudio_result_t updateStateMachine() = 0;
 
 
     // =========== End ABSTRACT methods ===========================
@@ -234,8 +242,132 @@
         return AAUDIO_ERROR_UNIMPLEMENTED;
     }
 
+    // This is used by the AudioManager to duck and mute the stream when changing audio focus.
+    void setDuckAndMuteVolume(float duckAndMuteVolume) {
+        mDuckAndMuteVolume = duckAndMuteVolume;
+        doSetVolume(); // apply this change
+    }
+
+    float getDuckAndMuteVolume() {
+        return mDuckAndMuteVolume;
+    }
+
+    // Implement this in the output subclasses.
+    virtual android::status_t doSetVolume() { return android::NO_ERROR; }
+
+#if AAUDIO_USE_VOLUME_SHAPER
+    virtual ::android::binder::Status applyVolumeShaper(
+            const ::android::media::VolumeShaper::Configuration& configuration __unused,
+            const ::android::media::VolumeShaper::Operation& operation __unused);
+#endif
+
+    /**
+     * Register this stream's PlayerBase with the AudioManager if needed.
+     * Only register output streams.
+     * This should only be called for client streams and not for streams
+     * that run in the service.
+     */
+    void registerPlayerBase() {
+        if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
+            mPlayerBase->registerWithAudioManager();
+        }
+    }
+
+    /**
+     * Unregister this stream's PlayerBase with the AudioManager.
+     * This will only unregister if already registered.
+     */
+    void unregisterPlayerBase() {
+        mPlayerBase->unregisterWithAudioManager();
+    }
+
+    // Pass start request through PlayerBase for tracking.
+    aaudio_result_t systemStart() {
+        mPlayerBase->start();
+        // Pass aaudio_result_t around the PlayerBase interface, which uses status__t.
+        return mPlayerBase->getResult();
+    }
+
+    aaudio_result_t systemPause() {
+        mPlayerBase->pause();
+        return mPlayerBase->getResult();
+    }
+
+    aaudio_result_t systemStop() {
+        mPlayerBase->stop();
+        return mPlayerBase->getResult();
+    }
+
 protected:
 
+    // PlayerBase allows the system to control the stream.
+    // Calling through PlayerBase->start() notifies the AudioManager of the player state.
+    // The AudioManager also can start/stop a stream by calling mPlayerBase->playerStart().
+    // systemStart() ==> mPlayerBase->start()   mPlayerBase->playerStart() ==> requestStart()
+    //                        \                           /
+    //                         ------ AudioManager -------
+    class MyPlayerBase : public android::PlayerBase {
+    public:
+        explicit MyPlayerBase(AudioStream *parent);
+
+        virtual ~MyPlayerBase();
+
+        /**
+         * Register for volume changes and remote control.
+         */
+        void registerWithAudioManager();
+
+        /**
+         * UnRegister.
+         */
+        void unregisterWithAudioManager();
+
+        /**
+         * Just calls unregisterWithAudioManager().
+         */
+        void destroy() override;
+
+        void clearParentReference() { mParent = nullptr; }
+
+        android::status_t playerStart() override {
+            // mParent should NOT be null. So go ahead and crash if it is.
+            mResult = mParent->requestStart();
+            return AAudioConvert_aaudioToAndroidStatus(mResult);
+        }
+
+        android::status_t playerPause() override {
+            mResult = mParent->requestPause();
+            return AAudioConvert_aaudioToAndroidStatus(mResult);
+        }
+
+        android::status_t playerStop() override {
+            mResult = mParent->requestStop();
+            return AAudioConvert_aaudioToAndroidStatus(mResult);
+        }
+
+        android::status_t playerSetVolume() override {
+            // No pan and only left volume is taken into account from IPLayer interface
+            mParent->setDuckAndMuteVolume(mVolumeMultiplierL  /* * mPanMultiplierL */);
+            return android::NO_ERROR;
+        }
+
+#if AAUDIO_USE_VOLUME_SHAPER
+        ::android::binder::Status applyVolumeShaper(
+                const ::android::media::VolumeShaper::Configuration& configuration,
+                const ::android::media::VolumeShaper::Operation& operation) {
+            return mParent->applyVolumeShaper(configuration, operation);
+        }
+#endif
+
+        aaudio_result_t getResult() {
+            return mResult;
+        }
+
+    private:
+        AudioStream          *mParent;
+        aaudio_result_t       mResult = AAUDIO_OK;
+        bool                  mRegistered = false;
+    };
 
     /**
      * This should not be called after the open() call.
@@ -275,7 +407,9 @@
 
     std::mutex           mStreamMutex;
 
-    std::atomic<bool>    mCallbackEnabled;
+    std::atomic<bool>    mCallbackEnabled{false};
+
+    float                mDuckAndMuteVolume = 1.0f;
 
 protected:
 
@@ -288,6 +422,8 @@
     }
 
 private:
+    const android::sp<MyPlayerBase>   mPlayerBase;
+
     // These do not change after open().
     int32_t                mSamplesPerFrame = AAUDIO_UNSPECIFIED;
     int32_t                mSampleRate = AAUDIO_UNSPECIFIED;
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 43a1ef1..09ebb3e 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -184,16 +184,6 @@
         return result;
     }
 
-    switch (mDirection) {
-        case AAUDIO_DIRECTION_INPUT:
-        case AAUDIO_DIRECTION_OUTPUT:
-            break; // valid
-        default:
-            ALOGE("AudioStreamBuilder: direction not valid = %d", mDirection);
-            return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
-            // break;
-    }
-
     switch (mPerformanceMode) {
         case AAUDIO_PERFORMANCE_MODE_NONE:
         case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index 6e548b1..a43cfa8 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -35,15 +35,6 @@
 
     ~AudioStreamBuilder();
 
-    aaudio_direction_t getDirection() const {
-        return mDirection;
-    }
-
-    AudioStreamBuilder* setDirection(aaudio_direction_t direction) {
-        mDirection = direction;
-        return this;
-    }
-
     bool isSharingModeMatchRequired() const {
         return mSharingModeMatchRequired;
     }
@@ -113,7 +104,6 @@
 
 private:
     bool                       mSharingModeMatchRequired = false; // must match sharing mode requested
-    aaudio_direction_t         mDirection = AAUDIO_DIRECTION_OUTPUT;
     aaudio_performance_mode_t  mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
 
     AAudioStream_dataCallback  mDataCallbackProc = nullptr;  // external callback functions
diff --git a/media/libaaudio/src/fifo/FifoBuffer.cpp b/media/libaaudio/src/fifo/FifoBuffer.cpp
index 8d2c62d..a869886 100644
--- a/media/libaaudio/src/fifo/FifoBuffer.cpp
+++ b/media/libaaudio/src/fifo/FifoBuffer.cpp
@@ -210,3 +210,9 @@
     return mFifo->getCapacity();
 }
 
+void FifoBuffer::eraseMemory() {
+    int32_t numBytes = convertFramesToBytes(getBufferCapacityInFrames());
+    if (numBytes > 0) {
+        memset(mStorage, 0, (size_t) numBytes);
+    }
+}
diff --git a/media/libaaudio/src/fifo/FifoBuffer.h b/media/libaaudio/src/fifo/FifoBuffer.h
index a94e9b0..f5a9e27 100644
--- a/media/libaaudio/src/fifo/FifoBuffer.h
+++ b/media/libaaudio/src/fifo/FifoBuffer.h
@@ -111,6 +111,11 @@
         mFifo->setWriteCounter(n);
     }
 
+    /*
+     * This is generally only called before or after the buffer is used.
+     */
+    void eraseMemory();
+
 private:
 
     void fillWrappingBuffer(WrappingBuffer *wrappingBuffer,
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index dd5e3c0..ee2504d 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -21,6 +21,7 @@
 #include <stdint.h>
 #include <utils/String16.h>
 #include <media/AudioTrack.h>
+#include <media/AudioTimestamp.h>
 #include <aaudio/AAudio.h>
 
 #include "core/AudioStream.h"
@@ -30,7 +31,8 @@
 using namespace aaudio;
 
 AudioStreamLegacy::AudioStreamLegacy()
-        : AudioStream(), mDeviceCallback(new StreamDeviceCallback(this)) {
+        : AudioStream()
+        , mDeviceCallback(new StreamDeviceCallback(this)) {
 }
 
 AudioStreamLegacy::~AudioStreamLegacy() {
@@ -46,33 +48,51 @@
     return AudioStreamLegacy_callback;
 }
 
-// Implement FixedBlockProcessor
-int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
-    int32_t frameCount = numBytes / getBytesPerFrame();
+int32_t AudioStreamLegacy::callDataCallbackFrames(uint8_t *buffer, int32_t numFrames) {
+    if (getDirection() == AAUDIO_DIRECTION_INPUT) {
+        // Increment before because we already got the data from the device.
+        incrementFramesRead(numFrames);
+    }
+
     // Call using the AAudio callback interface.
     AAudioStream_dataCallback appCallback = getDataCallbackProc();
-    return (*appCallback)(
+    aaudio_data_callback_result_t callbackResult = (*appCallback)(
             (AAudioStream *) this,
             getDataCallbackUserData(),
             buffer,
-            frameCount);
+            numFrames);
+
+    if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE
+            && getDirection() == AAUDIO_DIRECTION_OUTPUT) {
+        // Increment after because we are going to write the data to the device.
+        incrementFramesWritten(numFrames);
+    }
+    return callbackResult;
+}
+
+// Implement FixedBlockProcessor
+int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
+    int32_t numFrames = numBytes / getBytesPerFrame();
+    return callDataCallbackFrames(buffer, numFrames);
 }
 
 void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
     aaudio_data_callback_result_t callbackResult;
 
-    if (!mCallbackEnabled.load()) {
-        return;
-    }
-
     switch (opcode) {
         case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
-            if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
-                // Note that this code assumes an AudioTrack::Buffer is the same as
-                // AudioRecord::Buffer
-                // TODO define our own AudioBuffer and pass it from the subclasses.
-                AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
-                if (audioBuffer->frameCount == 0) return;
+            checkForDisconnectRequest();
+
+            // Note that this code assumes an AudioTrack::Buffer is the same as
+            // AudioRecord::Buffer
+            // TODO define our own AudioBuffer and pass it from the subclasses.
+            AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
+            if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED || !mCallbackEnabled.load()) {
+                audioBuffer->size = 0; // silence the buffer
+            } else {
+                if (audioBuffer->frameCount == 0) {
+                    return;
+                }
 
                 // If the caller specified an exact size then use a block size adapter.
                 if (mBlockAdapter != nullptr) {
@@ -81,44 +101,59 @@
                             (uint8_t *) audioBuffer->raw, byteCount);
                 } else {
                     // Call using the AAudio callback interface.
-                    callbackResult = (*getDataCallbackProc())(
-                            (AAudioStream *) this,
-                            getDataCallbackUserData(),
-                            audioBuffer->raw,
-                            audioBuffer->frameCount
-                            );
+                    callbackResult = callDataCallbackFrames((uint8_t *)audioBuffer->raw,
+                                                            audioBuffer->frameCount);
                 }
                 if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
                     audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
-                    incrementClientFrameCounter(audioBuffer->frameCount);
                 } else {
                     audioBuffer->size = 0;
                 }
-                break;
-            }
-        }
-        /// FALL THROUGH
 
-            // Stream got rerouted so we disconnect.
-        case AAUDIO_CALLBACK_OPERATION_DISCONNECTED: {
-            setState(AAUDIO_STREAM_STATE_DISCONNECTED);
-            ALOGD("processCallbackCommon() stream disconnected");
-            if (getErrorCallbackProc() != nullptr) {
-                (*getErrorCallbackProc())(
-                        (AAudioStream *) this,
-                        getErrorCallbackUserData(),
-                        AAUDIO_ERROR_DISCONNECTED
-                        );
+                if (updateStateMachine() != AAUDIO_OK) {
+                    forceDisconnect();
+                    mCallbackEnabled.store(false);
+                }
             }
-            mCallbackEnabled.store(false);
         }
             break;
 
+        // Stream got rerouted so we disconnect.
+        case AAUDIO_CALLBACK_OPERATION_DISCONNECTED:
+            ALOGD("processCallbackCommon() stream disconnected");
+            forceDisconnect();
+            mCallbackEnabled.store(false);
+            break;
+
         default:
             break;
     }
 }
 
+
+
+void AudioStreamLegacy::checkForDisconnectRequest() {
+    if (mRequestDisconnect.isRequested()) {
+        ALOGD("checkForDisconnectRequest() mRequestDisconnect acknowledged");
+        forceDisconnect();
+        mRequestDisconnect.acknowledge();
+        mCallbackEnabled.store(false);
+    }
+}
+
+void AudioStreamLegacy::forceDisconnect() {
+    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
+        setState(AAUDIO_STREAM_STATE_DISCONNECTED);
+        if (getErrorCallbackProc() != nullptr) {
+            (*getErrorCallbackProc())(
+                    (AAudioStream *) this,
+                    getErrorCallbackUserData(),
+                    AAUDIO_ERROR_DISCONNECTED
+            );
+        }
+    }
+}
+
 aaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
                                                    int64_t *framePosition,
                                                    int64_t *timeNanoseconds,
@@ -136,8 +171,23 @@
             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             break;
     }
-    status_t status = extendedTimestamp->getBestTimestamp(framePosition, timeNanoseconds, timebase);
-    return AAudioConvert_androidToAAudioResult(status);
+    ExtendedTimestamp::Location location = ExtendedTimestamp::Location::LOCATION_INVALID;
+    int64_t localPosition;
+    status_t status = extendedTimestamp->getBestTimestamp(&localPosition, timeNanoseconds,
+                                                          timebase, &location);
+    // use MonotonicCounter to prevent retrograde motion.
+    mTimestampPosition.update32((int32_t)localPosition);
+    *framePosition = mTimestampPosition.get();
+
+//    ALOGD("getBestTimestamp() fposition: server = %6lld, kernel = %6lld, location = %d",
+//          (long long) extendedTimestamp->mPosition[ExtendedTimestamp::Location::LOCATION_SERVER],
+//          (long long) extendedTimestamp->mPosition[ExtendedTimestamp::Location::LOCATION_KERNEL],
+//          (int)location);
+    if (status == WOULD_BLOCK) {
+        return AAUDIO_ERROR_INVALID_STATE;
+    } else {
+        return AAudioConvert_androidToAAudioResult(status);
+    }
 }
 
 void AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
@@ -145,15 +195,18 @@
     ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
     if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
             getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
-        setState(AAUDIO_STREAM_STATE_DISCONNECTED);
-        // if we have a data callback and the stream is active, send the error callback from
-        // data callback thread when it sees the DISCONNECTED state
-        if (!isDataCallbackActive() && getErrorCallbackProc() != nullptr) {
-            (*getErrorCallbackProc())(
-                    (AAudioStream *) this,
-                    getErrorCallbackUserData(),
-                    AAUDIO_ERROR_DISCONNECTED
-                    );
+        // Note that isDataCallbackActive() is affected by state so call it before DISCONNECTING.
+        // If we have a data callback and the stream is active, then ask the data callback
+        // to DISCONNECT and call the error callback.
+        if (isDataCallbackActive()) {
+            ALOGD("onAudioDeviceUpdate() request DISCONNECT in data callback due to device change");
+            // If the stream is stopped before the data callback has a chance to handle the
+            // request then the requestStop() and requestPause() methods will handle it after
+            // the callback has stopped.
+            mRequestDisconnect.request();
+        } else {
+            ALOGD("onAudioDeviceUpdate() DISCONNECT the stream now");
+            forceDisconnect();
         }
     }
     setDeviceId(deviceId);
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index d2ef3c7..7e28579 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -24,6 +24,7 @@
 
 #include "AudioStream.h"
 #include "AAudioLegacy.h"
+#include "utility/AAudioUtilities.h"
 #include "utility/FixedBlockAdapter.h"
 
 namespace aaudio {
@@ -63,6 +64,8 @@
 
     aaudio_legacy_callback_t getLegacyCallback();
 
+    int32_t callDataCallbackFrames(uint8_t *buffer, int32_t numFrames);
+
     // This is public so it can be called from the C callback function.
     // This is called from the AudioTrack/AudioRecord client.
     virtual void processCallback(int event, void *info) = 0;
@@ -109,6 +112,10 @@
 
     void onAudioDeviceUpdate(audio_port_handle_t deviceId);
 
+    void checkForDisconnectRequest();
+
+    void forceDisconnect();
+
     void onStart() { mCallbackEnabled.store(true); }
     void onStop() { mCallbackEnabled.store(false); }
 
@@ -122,11 +129,14 @@
 
     MonotonicCounter           mFramesWritten;
     MonotonicCounter           mFramesRead;
+    MonotonicCounter           mTimestampPosition;
 
     FixedBlockAdapter         *mBlockAdapter = nullptr;
     aaudio_wrapping_frames_t   mPositionWhenStarting = 0;
     int32_t                    mCallbackBufferSize = 0;
     const android::sp<StreamDeviceCallback>   mDeviceCallback;
+
+    AtomicRequestor            mRequestDisconnect;
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 8e8070c..bc6e60c 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AAudio"
+#define LOG_TAG "AudioStreamRecord"
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
@@ -159,6 +159,9 @@
         actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
     }
     setPerformanceMode(actualPerformanceMode);
+
+    setSharingMode(AAUDIO_SHARING_MODE_SHARED); // EXCLUSIVE mode not supported in legacy
+
     // Log warning if we did not get what we asked for.
     ALOGW_IF(actualFlags != flags,
              "AudioStreamRecord::open() flags changed from 0x%08X to 0x%08X",
@@ -178,11 +181,12 @@
 {
     // TODO add close() or release() to AudioRecord API then call it from here
     if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
+        mAudioRecord->removeAudioDeviceCallback(mDeviceCallback);
         mAudioRecord.clear();
         setState(AAUDIO_STREAM_STATE_CLOSED);
     }
     mFixedBlockWriter.close();
-    return AAUDIO_OK;
+    return AudioStream::close();
 }
 
 void AudioStreamRecord::processCallback(int event, void *info) {
@@ -207,7 +211,7 @@
     if (mAudioRecord.get() == nullptr) {
         return AAUDIO_ERROR_INVALID_STATE;
     }
-    // Get current position so we can detect when the track is playing.
+    // Get current position so we can detect when the track is recording.
     status_t err = mAudioRecord->getPosition(&mPositionWhenStarting);
     if (err != OK) {
         return AAudioConvert_androidToAAudioResult(err);
@@ -230,12 +234,15 @@
     onStop();
     setState(AAUDIO_STREAM_STATE_STOPPING);
     incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review
+    mTimestampPosition.set(getFramesRead());
     mAudioRecord->stop();
     mFramesRead.reset32();
+    mTimestampPosition.reset32();
+    checkForDisconnectRequest();
     return AAUDIO_OK;
 }
 
-aaudio_result_t AudioStreamRecord::updateStateWhileWaiting()
+aaudio_result_t AudioStreamRecord::updateStateMachine()
 {
     aaudio_result_t result = AAUDIO_OK;
     aaudio_wrapping_frames_t position;
@@ -292,6 +299,12 @@
     }
     int32_t framesRead = (int32_t)(bytesRead / bytesPerFrame);
     incrementFramesRead(framesRead);
+
+    result = updateStateMachine();
+    if (result != AAUDIO_OK) {
+        return result;
+    }
+
     return (aaudio_result_t) framesRead;
 }
 
@@ -325,8 +338,28 @@
                                                int64_t *timeNanoseconds) {
     ExtendedTimestamp extendedTimestamp;
     status_t status = mAudioRecord->getTimestamp(&extendedTimestamp);
-    if (status != NO_ERROR) {
+    if (status == WOULD_BLOCK) {
+        return AAUDIO_ERROR_INVALID_STATE;
+    } else if (status != NO_ERROR) {
         return AAudioConvert_androidToAAudioResult(status);
     }
     return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp);
 }
+
+int64_t AudioStreamRecord::getFramesWritten() {
+    aaudio_wrapping_frames_t position;
+    status_t result;
+    switch (getState()) {
+        case AAUDIO_STREAM_STATE_STARTING:
+        case AAUDIO_STREAM_STATE_STARTED:
+        case AAUDIO_STREAM_STATE_STOPPING:
+            result = mAudioRecord->getPosition(&position);
+            if (result == OK) {
+                mFramesWritten.update32(position);
+            }
+            break;
+        default:
+            break;
+    }
+    return AudioStreamLegacy::getFramesWritten();
+}
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index 2c6a7eb..c1723ba 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -59,9 +59,11 @@
 
     int32_t getXRunCount() const override;
 
+    int64_t getFramesWritten() override;
+
     int32_t getFramesPerBurst() const override;
 
-    aaudio_result_t updateStateWhileWaiting() override;
+    aaudio_result_t updateStateMachine() override;
 
     aaudio_direction_t getDirection() const override {
         return AAUDIO_DIRECTION_INPUT;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 77f31e2..0e9aaef 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AAudio"
+#define LOG_TAG "AudioStreamTrack"
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
@@ -115,7 +115,7 @@
 
     ALOGD("AudioStreamTrack::open(), request notificationFrames = %d, frameCount = %u",
           notificationFrames, (uint)frameCount);
-    mAudioTrack = new AudioTrack();
+    mAudioTrack = new AudioTrack(); // TODO review
     if (getDeviceId() != AAUDIO_UNSPECIFIED) {
         mAudioTrack->setOutputDevice(getDeviceId());
     }
@@ -143,8 +143,7 @@
         return AAudioConvert_androidToAAudioResult(status);
     }
 
-    //TrackPlayerBase init
-    init(mAudioTrack.get(), PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
+    doSetVolume();
 
     // Get the actual values from the AudioTrack.
     setSamplesPerFrame(mAudioTrack->channelCount());
@@ -171,18 +170,20 @@
     setDeviceId(mAudioTrack->getRoutedDeviceId());
     mAudioTrack->addAudioDeviceCallback(mDeviceCallback);
 
-    // Update performance mode based on the actual stream.
+    // Update performance mode based on the actual stream flags.
     // For example, if the sample rate is not allowed then you won't get a FAST track.
     audio_output_flags_t actualFlags = mAudioTrack->getFlags();
     aaudio_performance_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
-    if ((actualFlags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW))
-        == (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW)) {
+    // We may not get the RAW flag. But as long as we get the FAST flag we can call it LOW_LATENCY.
+    if ((actualFlags & AUDIO_OUTPUT_FLAG_FAST) != 0) {
         actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
-
     } else if ((actualFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
         actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
     }
     setPerformanceMode(actualPerformanceMode);
+
+    setSharingMode(AAUDIO_SHARING_MODE_SHARED); // EXCLUSIVE mode not supported in legacy
+
     // Log warning if we did not get what we asked for.
     ALOGW_IF(actualFlags != flags,
              "AudioStreamTrack::open() flags changed from 0x%08X to 0x%08X",
@@ -197,7 +198,7 @@
 aaudio_result_t AudioStreamTrack::close()
 {
     if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
-        destroy();
+        mAudioTrack->removeAudioDeviceCallback(mDeviceCallback);
         setState(AAUDIO_STREAM_STATE_CLOSED);
     }
     mFixedBlockReader.close();
@@ -222,11 +223,11 @@
     return;
 }
 
-aaudio_result_t AudioStreamTrack::requestStart()
-{
+aaudio_result_t AudioStreamTrack::requestStart() {
     std::lock_guard<std::mutex> lock(mStreamMutex);
 
     if (mAudioTrack.get() == nullptr) {
+        ALOGE("AudioStreamTrack::requestStart() no AudioTrack");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     // Get current position so we can detect when the track is playing.
@@ -235,7 +236,7 @@
         return AAudioConvert_androidToAAudioResult(err);
     }
 
-    err = startWithStatus();
+    err = mAudioTrack->start();
     if (err != OK) {
         return AAudioConvert_androidToAAudioResult(err);
     } else {
@@ -245,11 +246,11 @@
     return AAUDIO_OK;
 }
 
-aaudio_result_t AudioStreamTrack::requestPause()
-{
+aaudio_result_t AudioStreamTrack::requestPause() {
     std::lock_guard<std::mutex> lock(mStreamMutex);
 
     if (mAudioTrack.get() == nullptr) {
+        ALOGE("requestPause() no AudioTrack");
         return AAUDIO_ERROR_INVALID_STATE;
     } else if (getState() != AAUDIO_STREAM_STATE_STARTING
             && getState() != AAUDIO_STREAM_STATE_STARTED) {
@@ -259,7 +260,8 @@
     }
     onStop();
     setState(AAUDIO_STREAM_STATE_PAUSING);
-    pause();
+    mAudioTrack->pause();
+    checkForDisconnectRequest();
     status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
     if (err != OK) {
         return AAudioConvert_androidToAAudioResult(err);
@@ -271,14 +273,17 @@
     std::lock_guard<std::mutex> lock(mStreamMutex);
 
     if (mAudioTrack.get() == nullptr) {
+        ALOGE("AudioStreamTrack::requestFlush() no AudioTrack");
         return AAUDIO_ERROR_INVALID_STATE;
     } else if (getState() != AAUDIO_STREAM_STATE_PAUSED) {
+        ALOGE("AudioStreamTrack::requestFlush() not paused");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     setState(AAUDIO_STREAM_STATE_FLUSHING);
     incrementFramesRead(getFramesWritten() - getFramesRead());
     mAudioTrack->flush();
     mFramesWritten.reset32();
+    mTimestampPosition.reset32();
     return AAUDIO_OK;
 }
 
@@ -286,17 +291,21 @@
     std::lock_guard<std::mutex> lock(mStreamMutex);
 
     if (mAudioTrack.get() == nullptr) {
+        ALOGE("AudioStreamTrack::requestStop() no AudioTrack");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     onStop();
     setState(AAUDIO_STREAM_STATE_STOPPING);
     incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review
-    stop();
+    mTimestampPosition.set(getFramesWritten());
     mFramesWritten.reset32();
+    mTimestampPosition.reset32();
+    mAudioTrack->stop();
+    checkForDisconnectRequest();
     return AAUDIO_OK;
 }
 
-aaudio_result_t AudioStreamTrack::updateStateWhileWaiting()
+aaudio_result_t AudioStreamTrack::updateStateMachine()
 {
     status_t err;
     aaudio_wrapping_frames_t position;
@@ -373,6 +382,12 @@
     }
     int32_t framesWritten = (int32_t)(bytesWritten / bytesPerFrame);
     incrementFramesWritten(framesWritten);
+
+    result = updateStateMachine();
+    if (result != AAUDIO_OK) {
+        return result;
+    }
+
     return framesWritten;
 }
 
@@ -431,8 +446,59 @@
                                      int64_t *timeNanoseconds) {
     ExtendedTimestamp extendedTimestamp;
     status_t status = mAudioTrack->getTimestamp(&extendedTimestamp);
-    if (status != NO_ERROR) {
+    if (status == WOULD_BLOCK) {
+        return AAUDIO_ERROR_INVALID_STATE;
+    } if (status != NO_ERROR) {
         return AAudioConvert_androidToAAudioResult(status);
     }
-    return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp);
+    int64_t position = 0;
+    int64_t nanoseconds = 0;
+    aaudio_result_t result = getBestTimestamp(clockId, &position,
+                                              &nanoseconds, &extendedTimestamp);
+    if (result == AAUDIO_OK) {
+        if (position < getFramesWritten()) {
+            *framePosition = position;
+            *timeNanoseconds = nanoseconds;
+            return result;
+        } else {
+            return AAUDIO_ERROR_INVALID_STATE; // TODO review, documented but not consistent
+        }
+    }
+    return result;
 }
+
+status_t AudioStreamTrack::doSetVolume() {
+    status_t status = NO_INIT;
+    if (mAudioTrack.get() != nullptr) {
+        float volume = getDuckAndMuteVolume();
+        mAudioTrack->setVolume(volume, volume);
+        status = NO_ERROR;
+    }
+    return status;
+}
+
+#if AAUDIO_USE_VOLUME_SHAPER
+
+using namespace android::media::VolumeShaper;
+
+binder::Status AudioStreamTrack::applyVolumeShaper(
+        const VolumeShaper::Configuration& configuration,
+        const VolumeShaper::Operation& operation) {
+
+    sp<VolumeShaper::Configuration> spConfiguration = new VolumeShaper::Configuration(configuration);
+    sp<VolumeShaper::Operation> spOperation = new VolumeShaper::Operation(operation);
+
+    if (mAudioTrack.get() != nullptr) {
+        ALOGD("applyVolumeShaper() from IPlayer");
+        binder::Status status = mAudioTrack->applyVolumeShaper(spConfiguration, spOperation);
+        if (status < 0) { // a non-negative value is the volume shaper id.
+            ALOGE("applyVolumeShaper() failed with status %d", status);
+        }
+        return binder::Status::fromStatusT(status);
+    } else {
+        ALOGD("applyVolumeShaper()"
+                      " no AudioTrack for volume control from IPlayer");
+        return binder::Status::ok();
+    }
+}
+#endif
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index ff429ea..a871db4 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -19,6 +19,7 @@
 
 #include <math.h>
 #include <media/TrackPlayerBase.h>
+#include <media/AudioTrack.h>
 #include <aaudio/AAudio.h>
 
 #include "AudioStreamBuilder.h"
@@ -32,7 +33,7 @@
 /**
  * Internal stream that uses the legacy AudioTrack path.
  */
-class AudioStreamTrack : public AudioStreamLegacy, public android::TrackPlayerBase {
+class AudioStreamTrack : public AudioStreamLegacy {
 public:
     AudioStreamTrack();
 
@@ -67,7 +68,7 @@
         return AAUDIO_DIRECTION_OUTPUT;
     }
 
-    aaudio_result_t updateStateWhileWaiting() override;
+    aaudio_result_t updateStateMachine() override;
 
     // This is public so it can be called from the C callback function.
     void processCallback(int event, void *info) override;
@@ -76,13 +77,22 @@
         return incrementFramesWritten(frames);
     }
 
+    android::status_t doSetVolume() override;
+
+#if AAUDIO_USE_VOLUME_SHAPER
+    virtual android::binder::Status applyVolumeShaper(
+            const android::media::VolumeShaper::Configuration& configuration,
+            const android::media::VolumeShaper::Operation& operation) override;
+#endif
+
 private:
 
+    android::sp<android::AudioTrack> mAudioTrack;
+
     // adapts between variable sized blocks and fixed size blocks
     FixedBlockReader                 mFixedBlockReader;
 
-    // TODO add 64-bit position reporting to AudioRecord and use it.
-    aaudio_wrapping_frames_t         mPositionWhenStarting = 0;
+    // TODO add 64-bit position reporting to AudioTrack and use it.
     aaudio_wrapping_frames_t         mPositionWhenPausing = 0;
 };
 
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index acd319b..3afa976 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -258,4 +258,112 @@
     }
 }
 
+
+/**
+ * Simple double buffer for a structure that can be written occasionally and read occasionally.
+ * This allows a SINGLE writer with multiple readers.
+ *
+ * It is OK if the FIFO overflows and we lose old values.
+ * It is also OK if we read an old value.
+ * Thread may return a non-atomic result if the other thread is rapidly writing
+ * new values on another core.
+ */
+template <class T>
+class SimpleDoubleBuffer {
+public:
+    SimpleDoubleBuffer()
+            : mValues() {}
+
+    __attribute__((no_sanitize("integer")))
+    void write(T value) {
+        int index = mCounter.load() & 1;
+        mValues[index] = value;
+        mCounter++; // Increment AFTER updating storage, OK if it wraps.
+    }
+
+    /**
+     * This should only be called by the same thread that calls write() or when
+     * no other thread is calling write.
+     */
+    void clear() {
+        mCounter.store(0);
+    }
+
+    T read() const {
+        T result;
+        int before;
+        int after;
+        int timeout = 3;
+        do {
+            // Check to see if a write occurred while were reading.
+            before = mCounter.load();
+            int index = (before & 1) ^ 1;
+            result = mValues[index];
+            after = mCounter.load();
+        } while ((after != before) && (after > 0) && (--timeout > 0));
+        return result;
+    }
+
+    /**
+     * @return true if at least one value has been written
+     */
+    bool isValid() const {
+        return mCounter.load() > 0;
+    }
+
+private:
+    T                    mValues[2];
+    std::atomic<int>     mCounter{0};
+};
+
+class Timestamp {
+public:
+    Timestamp()
+            : mPosition(0)
+            , mNanoseconds(0) {}
+    Timestamp(int64_t position, int64_t nanoseconds)
+            : mPosition(position)
+            , mNanoseconds(nanoseconds) {}
+
+    int64_t getPosition() const { return mPosition; }
+
+    int64_t getNanoseconds() const { return mNanoseconds; }
+
+private:
+    // These cannot be const because we need to implement the copy assignment operator.
+    int64_t mPosition;
+    int64_t mNanoseconds;
+};
+
+
+/**
+ * Pass a request to another thread.
+ * This is used when one thread, A, wants another thread, B, to do something.
+ * A naive approach would be for A to set a flag and for B to clear it when done.
+ * But that creates a race condition. This technique avoids the race condition.
+ *
+ * Assumes only one requester and one acknowledger.
+ */
+class AtomicRequestor {
+public:
+
+    __attribute__((no_sanitize("integer")))
+    void request() {
+        mRequested++;
+    }
+
+    __attribute__((no_sanitize("integer")))
+    bool isRequested() {
+        return (mRequested.load() - mAcknowledged.load()) > 0;
+    }
+
+    __attribute__((no_sanitize("integer")))
+    void acknowledge() {
+        mAcknowledged++;
+    }
+
+private:
+    std::atomic<int> mRequested{0};
+    std::atomic<int> mAcknowledged{0};
+};
 #endif //UTILITY_AAUDIO_UTILITIES_H
diff --git a/media/libaaudio/src/utility/HandleTracker.cpp b/media/libaaudio/src/utility/HandleTracker.cpp
deleted file mode 100644
index 35ce95a..0000000
--- a/media/libaaudio/src/utility/HandleTracker.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#define LOG_TAG "AAudio"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <assert.h>
-#include <functional>
-#include <iomanip>
-#include <new>
-#include <sstream>
-#include <stdint.h>
-#include <utils/Mutex.h>
-
-#include <aaudio/AAudio.h>
-#include "AAudioUtilities.h"
-#include "HandleTracker.h"
-
-using android::Mutex;
-
-// Handle format is: tgggiiii
-// where each letter is 4 bits, t=type, g=generation, i=index
-
-#define TYPE_SIZE           4
-#define GENERATION_SIZE    12
-#define INDEX_SIZE         16
-
-#define GENERATION_INVALID  0
-#define GENERATION_SHIFT    INDEX_SIZE
-
-#define TYPE_MASK           ((1 << TYPE_SIZE) - 1)
-#define GENERATION_MASK     ((1 << GENERATION_SIZE) - 1)
-#define INDEX_MASK          ((1 << INDEX_SIZE) - 1)
-
-#define SLOT_UNAVAILABLE    (-1)
-
-// Error if handle is negative so type is limited to bottom half.
-#define HANDLE_INVALID_TYPE TYPE_MASK
-
-static_assert(HANDLE_TRACKER_MAX_TYPES == (1 << (TYPE_SIZE - 1)),
-    "Mismatch between header and cpp.");
-static_assert(HANDLE_TRACKER_MAX_HANDLES == (1 << (INDEX_SIZE)),
-    "Mismatch between header and cpp.");
-
-HandleTracker::HandleTracker(uint32_t maxHandles)
-        : mMaxHandleCount(maxHandles)
-        , mHandleHeaders(nullptr)
-{
-    assert(maxHandles <= HANDLE_TRACKER_MAX_HANDLES);
-    // Allocate arrays to hold addresses and validation info.
-    mHandleAddresses = (handle_tracker_address_t *)
-            new(std::nothrow) handle_tracker_address_t[maxHandles];
-    if (mHandleAddresses != nullptr) {
-        mHandleHeaders = new(std::nothrow) handle_tracker_header_t[maxHandles];
-
-        if (mHandleHeaders != nullptr) {
-            handle_tracker_header_t initialHeader = buildHeader(0, 1);
-            // Initialize linked list of free nodes. nullptr terminated.
-            for (uint32_t i = 0; i < (maxHandles - 1); i++) {
-                mHandleAddresses[i] = &mHandleAddresses[i + 1]; // point to next node
-                mHandleHeaders[i] = initialHeader;
-            }
-            mNextFreeAddress = &mHandleAddresses[0];
-            mHandleAddresses[maxHandles - 1] = nullptr;
-            mHandleHeaders[maxHandles - 1] = 0;
-        } else {
-            delete[] mHandleAddresses; // so the class appears uninitialized
-            mHandleAddresses = nullptr;
-        }
-    }
-}
-
-HandleTracker::~HandleTracker()
-{
-    Mutex::Autolock _l(mLock);
-    delete[] mHandleAddresses;
-    delete[] mHandleHeaders;
-    mHandleAddresses = nullptr;
-}
-
-bool HandleTracker::isInitialized() const {
-    return mHandleAddresses != nullptr;
-}
-
-
-
-std::string HandleTracker::dump() const {
-    if (!isInitialized()) {
-        return "HandleTracker is not initialized\n";
-    }
-
-    std::stringstream result;
-    const bool isLocked = AAudio_tryUntilTrue(
-            [this]()->bool { return mLock.tryLock(); } /* f */,
-            50 /* times */,
-            20 /* sleepMs */);
-    if (!isLocked) {
-        result << "HandleTracker may be deadlocked\n";
-    }
-
-    result << "HandleTracker:\n";
-    result << "  HandleHeaders:\n";
-    // atLineStart() can be changed to support an arbitrary line breaking algorithm;
-    // it should return true when a new line starts.
-    // For simplicity, we will use a constant 16 items per line.
-    const auto atLineStart = [](int index) -> bool {
-        // Magic constant of 0xf used for mask to detect start every 16 items.
-        return (index & 0xf) == 0; };
-    const auto atLineEnd = [this, &atLineStart](int index) -> bool {
-        return atLineStart(index + 1) || index == mMaxHandleCount - 1; };
-
-    for (int i = 0; i < mMaxHandleCount; ++i) {
-        if (atLineStart(i)) {
-            result << "    ";
-        }
-        result << std::hex << std::setw(4) << std::setfill('0') << mHandleHeaders[i]
-               << (atLineEnd(i) ? "\n" : " ");
-    }
-
-    if (isLocked) {
-        mLock.unlock();
-    }
-    return result.str();
-}
-
-handle_tracker_slot_t HandleTracker::allocateSlot_l() {
-    void **allocated = mNextFreeAddress;
-    if (allocated == nullptr) {
-        return SLOT_UNAVAILABLE;
-    }
-    // Remove this slot from the head of the linked list.
-    mNextFreeAddress = (void **) *allocated;
-    return (allocated - mHandleAddresses);
-}
-
-handle_tracker_generation_t HandleTracker::nextGeneration_l(handle_tracker_slot_t index) {
-    handle_tracker_generation_t generation = (mHandleHeaders[index] + 1) & GENERATION_MASK;
-    // Avoid generation zero so that 0x0 is not a valid handle.
-    if (generation == GENERATION_INVALID) {
-        generation++;
-    }
-    return generation;
-}
-
-aaudio_handle_t HandleTracker::put(handle_tracker_type_t type, void *address)
-{
-    if (type < 0 || type >= HANDLE_TRACKER_MAX_TYPES) {
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_OUT_OF_RANGE);
-    }
-    if (!isInitialized()) {
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_NO_MEMORY);
-    }
-
-    Mutex::Autolock _l(mLock);
-
-    // Find an empty slot.
-    handle_tracker_slot_t index = allocateSlot_l();
-    if (index == SLOT_UNAVAILABLE) {
-        ALOGE("HandleTracker::put() no room for more handles");
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_NO_FREE_HANDLES);
-    }
-
-    // Cycle the generation counter so stale handles can be detected.
-    handle_tracker_generation_t generation = nextGeneration_l(index); // reads header table
-    handle_tracker_header_t inputHeader = buildHeader(type, generation);
-
-    // These two writes may need to be observed by other threads or cores during get().
-    mHandleHeaders[index] = inputHeader;
-    mHandleAddresses[index] = address;
-    // TODO use store release to enforce memory order with get()
-
-    // Generate a handle.
-    aaudio_handle_t handle = buildHandle(inputHeader, index);
-
-    ALOGV("HandleTracker::put(%p) returns 0x%08x", address, handle);
-    return handle;
-}
-
-handle_tracker_slot_t HandleTracker::handleToIndex(handle_tracker_type_t type,
-                                                   aaudio_handle_t handle) const
-{
-    // Validate the handle.
-    handle_tracker_slot_t index = extractIndex(handle);
-    if (index >= mMaxHandleCount) {
-        ALOGE("HandleTracker::handleToIndex() invalid handle = 0x%08X", handle);
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_INVALID_HANDLE);
-    }
-    handle_tracker_generation_t handleGeneration = extractGeneration(handle);
-    handle_tracker_header_t inputHeader = buildHeader(type, handleGeneration);
-    // We do not need to synchronize this access to mHandleHeaders because it is constant for
-    // the lifetime of the handle.
-    if (inputHeader != mHandleHeaders[index]) {
-        ALOGE("HandleTracker::handleToIndex() inputHeader = 0x%08x != mHandleHeaders[%d] = 0x%08x",
-             inputHeader, index, mHandleHeaders[index]);
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_INVALID_HANDLE);
-    }
-    return index;
-}
-
-handle_tracker_address_t HandleTracker::get(handle_tracker_type_t type, aaudio_handle_t handle) const
-{
-    if (!isInitialized()) {
-        return nullptr;
-    }
-    handle_tracker_slot_t index = handleToIndex(type, handle);
-    if (index >= 0) {
-        // We do not need to synchronize this access to mHandleHeaders because this slot
-        // is allocated and, therefore, not part of the linked list of free slots.
-        return mHandleAddresses[index];
-    } else {
-        return nullptr;
-    }
-}
-
-handle_tracker_address_t HandleTracker::remove(handle_tracker_type_t type, aaudio_handle_t handle) {
-    if (!isInitialized()) {
-        return nullptr;
-    }
-
-    Mutex::Autolock _l(mLock);
-
-    handle_tracker_slot_t index = handleToIndex(type,handle);
-    if (index >= 0) {
-        handle_tracker_address_t address = mHandleAddresses[index];
-
-        // Invalidate the header type but preserve the generation count.
-        handle_tracker_generation_t generation = mHandleHeaders[index] & GENERATION_MASK;
-        handle_tracker_header_t inputHeader = buildHeader(
-                (handle_tracker_type_t) HANDLE_INVALID_TYPE, generation);
-        mHandleHeaders[index] = inputHeader;
-
-        // Add this slot to the head of the linked list.
-        mHandleAddresses[index] = mNextFreeAddress;
-        mNextFreeAddress = (handle_tracker_address_t *) &mHandleAddresses[index];
-        return address;
-    } else {
-        return nullptr;
-    }
-}
-
-aaudio_handle_t HandleTracker::buildHandle(handle_tracker_header_t typeGeneration,
-                                         handle_tracker_slot_t index) {
-    return (aaudio_handle_t)((typeGeneration << GENERATION_SHIFT) | (index & INDEX_MASK));
-}
-
-handle_tracker_header_t HandleTracker::buildHeader(handle_tracker_type_t type,
-                                    handle_tracker_generation_t generation)
-{
-    return (handle_tracker_header_t) (((type & TYPE_MASK) << GENERATION_SIZE)
-        | (generation & GENERATION_MASK));
-}
-
-handle_tracker_slot_t HandleTracker::extractIndex(aaudio_handle_t handle)
-{
-    return handle & INDEX_MASK;
-}
-
-handle_tracker_generation_t HandleTracker::extractGeneration(aaudio_handle_t handle)
-{
-    return (handle >> GENERATION_SHIFT) & GENERATION_MASK;
-}
diff --git a/media/libaaudio/src/utility/HandleTracker.h b/media/libaaudio/src/utility/HandleTracker.h
deleted file mode 100644
index a4c51c0..0000000
--- a/media/libaaudio/src/utility/HandleTracker.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef UTILITY_HANDLE_TRACKER_H
-#define UTILITY_HANDLE_TRACKER_H
-
-#include <stdint.h>
-#include <string>
-#include <utils/Mutex.h>
-
-typedef int32_t  aaudio_handle_t;
-typedef int32_t  handle_tracker_type_t;       // what kind of handle
-typedef int32_t  handle_tracker_slot_t;       // index in allocation table
-typedef int32_t  handle_tracker_generation_t; // incremented when slot used
-typedef uint16_t handle_tracker_header_t;     // combines type and generation
-typedef void    *handle_tracker_address_t;    // address of something that is stored here
-
-#define HANDLE_TRACKER_MAX_TYPES    (1 << 3)
-#define HANDLE_TRACKER_MAX_HANDLES  (1 << 16)
-
-/**
- * Represent Objects using an integer handle that can be used with Java.
- * This also makes the 'C' ABI more robust.
- *
- * Note that this should only be called from a single thread.
- * If you call it from more than one thread then you need to use your own mutex.
- */
-class HandleTracker {
-
-public:
-    /**
-     * @param maxHandles cannot exceed HANDLE_TRACKER_MAX_HANDLES
-     */
-    HandleTracker(uint32_t maxHandles = 256);
-    virtual ~HandleTracker();
-
-    /**
-     * Don't use if this returns false;
-     * @return true if the internal allocation succeeded
-     */
-    bool isInitialized() const;
-
-    /**
-     * Returns HandleTracker information.
-     *
-     * Will attempt to get the object lock, but will proceed
-     * even if it cannot.
-     *
-     * Each line of information ends with a newline.
-     *
-     * @return a string representing the HandleTracker info.
-     */
-    std::string dump() const;
-
-    /**
-     * Store a pointer and return a handle that can be used to retrieve the pointer.
-     *
-     * It is safe to call put() or remove() from multiple threads.
-     *
-     * @param expectedType the type of the object to be tracked
-     * @param address pointer to be converted to a handle
-     * @return a valid handle or a negative error
-     */
-    aaudio_handle_t put(handle_tracker_type_t expectedType, handle_tracker_address_t address);
-
-    /**
-     * Get the original pointer associated with the handle.
-     * The handle will be validated to prevent stale handles from being reused.
-     * Note that the validation is designed to prevent common coding errors and not
-     * to prevent deliberate hacking.
-     *
-     * @param expectedType shouldmatch the type we passed to put()
-     * @param handle to be converted to a pointer
-     * @return address associated with handle or nullptr
-     */
-    handle_tracker_address_t get(handle_tracker_type_t expectedType, aaudio_handle_t handle) const;
-
-    /**
-     * Free up the storage associated with the handle.
-     * Subsequent attempts to use the handle will fail.
-     *
-     * Do NOT remove() a handle while get() is being called for the same handle from another thread.
-     *
-     * @param expectedType shouldmatch the type we passed to put()
-     * @param handle to be removed from tracking
-     * @return address associated with handle or nullptr if not found
-     */
-    handle_tracker_address_t remove(handle_tracker_type_t expectedType, aaudio_handle_t handle);
-
-private:
-    const int32_t               mMaxHandleCount;   // size of array
-    // This address is const after initialization.
-    handle_tracker_address_t  * mHandleAddresses;  // address of objects or a free linked list node
-    // This address is const after initialization.
-    handle_tracker_header_t   * mHandleHeaders;    // combination of type and generation
-    // head of the linked list of free nodes in mHandleAddresses
-    handle_tracker_address_t  * mNextFreeAddress;
-
-    // This Mutex protects the linked list of free nodes.
-    // The list is managed using mHandleAddresses and mNextFreeAddress.
-    // The data in mHandleHeaders is only changed by put() and remove().
-    mutable android::Mutex      mLock;
-
-    /**
-     * Pull slot off of a list of empty slots.
-     * @return index or a negative error
-     */
-    handle_tracker_slot_t allocateSlot_l();
-
-    /**
-     * Increment the generation for the slot, avoiding zero.
-     */
-    handle_tracker_generation_t nextGeneration_l(handle_tracker_slot_t index);
-
-    /**
-     * Validate the handle and return the corresponding index.
-     * @return slot index or a negative error
-     */
-    handle_tracker_slot_t handleToIndex(aaudio_handle_t handle, handle_tracker_type_t type) const;
-
-    /**
-     * Construct a handle from a header and an index.
-     * @param header combination of a type and a generation
-     * @param index slot index returned from allocateSlot
-     * @return handle or a negative error
-     */
-    static aaudio_handle_t buildHandle(handle_tracker_header_t header, handle_tracker_slot_t index);
-
-    /**
-     * Combine a type and a generation field into a header.
-     */
-    static handle_tracker_header_t buildHeader(handle_tracker_type_t type,
-                handle_tracker_generation_t generation);
-
-    /**
-     * Extract the index from a handle.
-     * Does not validate the handle.
-     * @return index associated with a handle
-     */
-    static handle_tracker_slot_t extractIndex(aaudio_handle_t handle);
-
-    /**
-     * Extract the generation from a handle.
-     * Does not validate the handle.
-     * @return generation associated with a handle
-     */
-    static handle_tracker_generation_t extractGeneration(aaudio_handle_t handle);
-
-};
-
-#endif //UTILITY_HANDLE_TRACKER_H
diff --git a/media/libaaudio/src/utility/MonotonicCounter.h b/media/libaaudio/src/utility/MonotonicCounter.h
index 81d7f89..13c92a2 100644
--- a/media/libaaudio/src/utility/MonotonicCounter.h
+++ b/media/libaaudio/src/utility/MonotonicCounter.h
@@ -41,6 +41,13 @@
     }
 
     /**
+     * set the current value of the counter
+     */
+    void set(int64_t counter) {
+        mCounter64 = counter;
+    }
+
+    /**
      * Advance the counter if delta is positive.
      * @return current value of the counter
      */
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 05135df..19c56d3 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -7,13 +7,6 @@
 }
 
 cc_test {
-    name: "test_handle_tracker",
-    defaults: ["libaaudio_tests_defaults"],
-    srcs: ["test_handle_tracker.cpp"],
-    shared_libs: ["libaaudio"],
-}
-
-cc_test {
     name: "test_aaudio_marshalling",
     defaults: ["libaaudio_tests_defaults"],
     srcs: ["test_marshalling.cpp"],
@@ -33,6 +26,13 @@
 }
 
 cc_test {
+    name: "test_timestamps",
+    srcs: ["test_timestamps.cpp"],
+    header_libs: ["libaaudio_example_utils"],
+    shared_libs: ["libaaudio"],
+}
+
+cc_test {
     name: "test_linear_ramp",
     defaults: ["libaaudio_tests_defaults"],
     srcs: ["test_linear_ramp.cpp"],
diff --git a/media/libaaudio/tests/test_handle_tracker.cpp b/media/libaaudio/tests/test_handle_tracker.cpp
deleted file mode 100644
index c4db47a..0000000
--- a/media/libaaudio/tests/test_handle_tracker.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// Unit tests for AAudio Handle Tracker
-
-#include <stdlib.h>
-#include <math.h>
-
-#include <gtest/gtest.h>
-
-#include <aaudio/AAudio.h>
-#include "utility/HandleTracker.h"
-
-// Test adding one address.
-TEST(test_handle_tracker, aaudio_handle_tracker) {
-    const int MAX_HANDLES = 4;
-    HandleTracker tracker(MAX_HANDLES);
-    handle_tracker_type_t type = 3; // arbitrary generic type
-    int data; // something that has an address we can use
-    handle_tracker_address_t found;
-
-    // repeat the test several times to see if it breaks
-    const int SEVERAL = 5; // arbitrary
-    for (int i = 0; i < SEVERAL; i++) {
-        // should fail to find a bogus handle
-        found = tracker.get(type, 0);  // bad handle
-        EXPECT_EQ(nullptr, found);
-
-        // create a valid handle and use it to lookup the object again
-        aaudio_handle_t dataHandle = tracker.put(type, &data);
-        ASSERT_TRUE(dataHandle > 0);
-        found = tracker.get(type, dataHandle);
-        EXPECT_EQ(&data, found);
-        found = tracker.get(type, 0); // bad handle
-        EXPECT_EQ(nullptr, found);
-
-        // wrong type
-        found = tracker.get(type+1, dataHandle);
-        EXPECT_EQ(nullptr, found);
-
-        // remove from storage
-        found = tracker.remove(type, dataHandle);
-        EXPECT_EQ(&data, found);
-        // should fail the second time
-        found = tracker.remove(type, dataHandle);
-        EXPECT_EQ(nullptr, found);
-    }
-}
-
-// Test filling the tracker.
-TEST(test_handle_tracker, aaudio_full_up) {
-    const int MAX_HANDLES = 5;
-    HandleTracker tracker(MAX_HANDLES);
-    handle_tracker_type_t type = 4; // arbitrary generic type
-    int data[MAX_HANDLES];
-    aaudio_handle_t handles[MAX_HANDLES];
-    handle_tracker_address_t found;
-
-    // repeat the test several times to see if it breaks
-    const int SEVERAL = 5; // arbitrary
-    for (int i = 0; i < SEVERAL; i++) {
-        for (int i = 0; i < MAX_HANDLES; i++) {
-            // add a handle
-            handles[i] = tracker.put(type, &data[i]);
-            ASSERT_TRUE(handles[i] > 0);
-            found = tracker.get(type, handles[i]);
-            EXPECT_EQ(&data[i], found);
-        }
-
-        // Now that it is full, try to add one more.
-        aaudio_handle_t handle = tracker.put(type, &data[0]);
-        EXPECT_TRUE(handle < 0);
-
-        for (int i = 0; i < MAX_HANDLES; i++) {
-            // look up each handle
-            found = tracker.get(type, handles[i]);
-            EXPECT_EQ(&data[i], found);
-        }
-
-        // remove one from storage
-        found = tracker.remove(type, handles[2]);
-        EXPECT_EQ(&data[2], found);
-        // now try to look up the same handle and fail
-        found = tracker.get(type, handles[2]);
-        EXPECT_EQ(nullptr, found);
-
-        // add that same one back
-        handle = tracker.put(type, &data[2]);
-        ASSERT_TRUE(handle > 0);
-        found = tracker.get(type, handle);
-        EXPECT_EQ(&data[2], found);
-        // now use a stale handle again with a valid index and fail
-        found = tracker.get(type, handles[2]);
-        EXPECT_EQ(nullptr, found);
-
-        // remove them all
-        handles[2] = handle;
-        for (int i = 0; i < MAX_HANDLES; i++) {
-            // look up each handle
-            found = tracker.remove(type, handles[i]);
-            EXPECT_EQ(&data[i], found);
-        }
-    }
-}
diff --git a/media/libaaudio/tests/test_timestamps.cpp b/media/libaaudio/tests/test_timestamps.cpp
new file mode 100644
index 0000000..b57f0a4
--- /dev/null
+++ b/media/libaaudio/tests/test_timestamps.cpp
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+// Play silence and recover from dead servers or disconnected devices.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+#include "utils/AAudioExampleUtils.h"
+#include "../examples/utils/AAudioExampleUtils.h"
+
+// Arbitrary period for glitches, once per second at 48000 Hz.
+#define FORCED_UNDERRUN_PERIOD_FRAMES    48000
+// How long to sleep in a callback to cause an intentional glitch. For testing.
+#define FORCED_UNDERRUN_SLEEP_MICROS     (10 * 1000)
+
+#define MAX_TIMESTAMPS          1000
+
+#define DEFAULT_TIMEOUT_NANOS   ((int64_t)1000000000)
+
+#define NUM_SECONDS             1
+#define NUM_LOOPS               4
+
+typedef struct TimestampInfo {
+    int64_t         framesTotal;
+    int64_t         appPosition; // frames
+    int64_t         appNanoseconds;
+    int64_t         timestampPosition;  // frames
+    int64_t         timestampNanos;
+    aaudio_result_t result;
+} TimestampInfo;
+
+typedef struct TimestampCallbackData_s {
+    TimestampInfo  timestamps[MAX_TIMESTAMPS];
+    int64_t        framesTotal = 0;
+    int64_t        nextFrameToGlitch = FORCED_UNDERRUN_PERIOD_FRAMES;
+    int32_t        timestampCount = 0; // in timestamps
+    bool           forceUnderruns = false;
+} TimestampCallbackData_t;
+
+// Callback function that fills the audio output buffer.
+aaudio_data_callback_result_t timestampDataCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        void *audioData __unused,
+        int32_t numFrames
+) {
+
+    // should not happen but just in case...
+    if (userData == nullptr) {
+        printf("ERROR - SimplePlayerDataCallbackProc needs userData\n");
+        return AAUDIO_CALLBACK_RESULT_STOP;
+    }
+    TimestampCallbackData_t *timestampData = (TimestampCallbackData_t *) userData;
+
+    aaudio_direction_t direction = AAudioStream_getDirection(stream);
+    if (direction == AAUDIO_DIRECTION_INPUT) {
+        timestampData->framesTotal += numFrames;
+    }
+
+    if (timestampData->forceUnderruns) {
+        if (timestampData->framesTotal > timestampData->nextFrameToGlitch) {
+            usleep(FORCED_UNDERRUN_SLEEP_MICROS);
+            printf("Simulate glitch at %lld\n", (long long) timestampData->framesTotal);
+            timestampData->nextFrameToGlitch += FORCED_UNDERRUN_PERIOD_FRAMES;
+        }
+    }
+
+    if (timestampData->timestampCount < MAX_TIMESTAMPS) {
+        TimestampInfo *timestamp = &timestampData->timestamps[timestampData->timestampCount];
+        timestamp->result = AAudioStream_getTimestamp(stream,
+                                                      CLOCK_MONOTONIC,
+                                                      &timestamp->timestampPosition,
+                                                      &timestamp->timestampNanos);
+        timestamp->framesTotal = timestampData->framesTotal;
+        timestamp->appPosition = (direction == AAUDIO_DIRECTION_OUTPUT)
+                ? AAudioStream_getFramesWritten(stream)
+                : AAudioStream_getFramesRead(stream);
+        timestamp->appNanoseconds = getNanoseconds();
+        timestampData->timestampCount++;
+    }
+
+    if (direction == AAUDIO_DIRECTION_OUTPUT) {
+        timestampData->framesTotal += numFrames;
+    }
+    return AAUDIO_CALLBACK_RESULT_CONTINUE;
+}
+
+static TimestampCallbackData_t sTimestampData;
+
+static aaudio_result_t testTimeStamps(aaudio_policy_t mmapPolicy,
+                           aaudio_sharing_mode_t sharingMode,
+                           aaudio_performance_mode_t performanceMode,
+                           aaudio_direction_t direction) {
+    aaudio_result_t result = AAUDIO_OK;
+
+    int32_t framesPerBurst = 0;
+    int32_t actualChannelCount = 0;
+    int32_t actualSampleRate = 0;
+    int32_t originalBufferSize = 0;
+    int32_t requestedBufferSize = 0;
+    int32_t finalBufferSize = 0;
+    aaudio_format_t actualDataFormat = AAUDIO_FORMAT_PCM_FLOAT;
+    aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
+    aaudio_sharing_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
+
+    AAudioStreamBuilder *aaudioBuilder = nullptr;
+    AAudioStream *aaudioStream = nullptr;
+
+    memset(&sTimestampData, 0, sizeof(sTimestampData));
+
+    printf("------------ testTimeStamps(policy = %d, sharing = %s, perf = %s, dir = %s) -----------\n",
+           mmapPolicy,
+           getSharingModeText(sharingMode),
+           getPerformanceModeText(performanceMode),
+           getDirectionText(direction));
+
+    AAudio_setMMapPolicy(mmapPolicy);
+
+    // Use an AAudioStreamBuilder to contain requested parameters.
+    result = AAudio_createStreamBuilder(&aaudioBuilder);
+    if (result != AAUDIO_OK) {
+        printf("AAudio_createStreamBuilder returned %s",
+               AAudio_convertResultToText(result));
+        goto finish;
+    }
+
+    // Request stream properties.
+    AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_I16);
+    AAudioStreamBuilder_setSharingMode(aaudioBuilder, sharingMode);
+    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, performanceMode);
+    AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
+    AAudioStreamBuilder_setDataCallback(aaudioBuilder, timestampDataCallbackProc, &sTimestampData);
+
+    // Create an AAudioStream using the Builder.
+    result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+    if (result != AAUDIO_OK) {
+        printf("AAudioStreamBuilder_openStream returned %s",
+               AAudio_convertResultToText(result));
+        goto finish;
+    }
+
+    // Check to see what kind of stream we actually got.
+    actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
+    actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
+    actualDataFormat = AAudioStream_getFormat(aaudioStream);
+
+    actualSharingMode = AAudioStream_getSharingMode(aaudioStream);
+    if (actualSharingMode != sharingMode) {
+        printf("did not get expected sharingMode, got %3d, skipping test\n",
+               actualSharingMode);
+        result = AAUDIO_OK;
+        goto finish;
+    }
+    actualPerformanceMode = AAudioStream_getPerformanceMode(aaudioStream);
+    if (actualPerformanceMode != performanceMode) {
+        printf("did not get expected performanceMode, got %3d, skipping test\n",
+               actualPerformanceMode);
+        result = AAUDIO_OK;
+        goto finish;
+    }
+
+    printf("    chans = %3d, rate = %6d format = %d\n",
+           actualChannelCount, actualSampleRate, actualDataFormat);
+    printf("    Is MMAP used? %s\n", AAudioStream_isMMapUsed(aaudioStream)
+                                     ? "yes" : "no");
+
+    // This is the number of frames that are read in one chunk by a DMA controller
+    // or a DSP or a mixer.
+    framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
+    printf("    framesPerBurst = %3d\n", framesPerBurst);
+
+    originalBufferSize = AAudioStream_getBufferSizeInFrames(aaudioStream);
+    requestedBufferSize = 4 * framesPerBurst;
+    finalBufferSize = AAudioStream_setBufferSizeInFrames(aaudioStream, requestedBufferSize);
+
+    printf("    BufferSize: original = %4d, requested = %4d, final = %4d\n",
+           originalBufferSize, requestedBufferSize, finalBufferSize);
+
+    {
+        int64_t position;
+        int64_t nanoseconds;
+        result = AAudioStream_getTimestamp(aaudioStream, CLOCK_MONOTONIC, &position, &nanoseconds);
+        printf("before start, AAudioStream_getTimestamp() returns %s\n",
+               AAudio_convertResultToText(result));
+    }
+
+    for (int runs = 0; runs < NUM_LOOPS; runs++) {
+        printf("------------------ loop #%d\n", runs);
+
+        int64_t temp = sTimestampData.framesTotal;
+        memset(&sTimestampData, 0, sizeof(sTimestampData));
+        sTimestampData.framesTotal = temp;
+
+        sTimestampData.forceUnderruns = false;
+
+        result = AAudioStream_requestStart(aaudioStream);
+        if (result != AAUDIO_OK) {
+            printf("AAudioStream_requestStart returned %s",
+                   AAudio_convertResultToText(result));
+            goto finish;
+        }
+
+        for (int second = 0; second < NUM_SECONDS; second++) {
+            // Give AAudio callback time to run in the background.
+            sleep(1);
+
+            // Periodically print the progress so we know it hasn't died.
+            printf("framesWritten = %d, XRuns = %d\n",
+                   (int) AAudioStream_getFramesWritten(aaudioStream),
+                   (int) AAudioStream_getXRunCount(aaudioStream)
+            );
+        }
+
+        result = AAudioStream_requestStop(aaudioStream);
+        if (result != AAUDIO_OK) {
+            printf("AAudioStream_requestStop returned %s\n",
+                   AAudio_convertResultToText(result));
+        }
+
+        printf("timestampCount = %d\n", sTimestampData.timestampCount);
+        int printed = 0;
+        for (int i = 0; i < sTimestampData.timestampCount; i++) {
+            TimestampInfo *timestamp = &sTimestampData.timestamps[i];
+            bool posChanged = (timestamp->timestampPosition != (timestamp - 1)->timestampPosition);
+            bool timeChanged = (timestamp->timestampNanos != (timestamp - 1)->timestampNanos);
+            if ((printed < 20) && ((i < 10) || posChanged || timeChanged)) {
+                printf("  %3d : frames %8lld, xferd %8lld", i,
+                       (long long) timestamp->framesTotal,
+                       (long long) timestamp->appPosition);
+                if (timestamp->result != AAUDIO_OK) {
+                    printf(", result = %s\n", AAudio_convertResultToText(timestamp->result));
+                } else {
+                    bool negative = timestamp->timestampPosition < 0;
+                    bool retro = (i > 0 && (timestamp->timestampPosition <
+                                            (timestamp - 1)->timestampPosition));
+                    const char *message = negative ? " <=NEGATIVE!"
+                                                   : (retro ? "  <= RETROGRADE!" : "");
+
+                    double latency = calculateLatencyMillis(timestamp->timestampPosition,
+                                             timestamp->timestampNanos,
+                                             timestamp->appPosition,
+                                             timestamp->appNanoseconds,
+                                             actualSampleRate);
+                    printf(", STAMP: pos = %8lld, nanos = %8lld, lat = %7.1f msec %s\n",
+                           (long long) timestamp->timestampPosition,
+                           (long long) timestamp->timestampNanos,
+                           latency,
+                           message);
+                }
+                printed++;
+            }
+        }
+
+        // Avoid race conditions in AudioFlinger.
+        // There is normally a delay between a real user stopping and restarting a stream.
+        sleep(1);
+    }
+
+finish:
+    if (aaudioStream != nullptr) {
+        AAudioStream_close(aaudioStream);
+    }
+    AAudioStreamBuilder_delete(aaudioBuilder);
+    printf("result = %d = %s\n", result, AAudio_convertResultToText(result));
+
+    return result;
+}
+
+int main(int argc, char **argv) {
+    (void) argc;
+    (void) argv;
+
+    aaudio_result_t result = AAUDIO_OK;
+
+    // Make printf print immediately so that debug info is not stuck
+    // in a buffer if we hang or crash.
+    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
+
+    printf("Test Timestamps V0.1.3\n");
+
+    // Legacy
+    aaudio_policy_t policy = AAUDIO_POLICY_NEVER;
+    result = testTimeStamps(policy,
+                            AAUDIO_SHARING_MODE_SHARED,
+                            AAUDIO_PERFORMANCE_MODE_NONE,
+                            AAUDIO_DIRECTION_INPUT);
+    result = testTimeStamps(policy,
+                            AAUDIO_SHARING_MODE_SHARED,
+                            AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                            AAUDIO_DIRECTION_INPUT);
+    result = testTimeStamps(policy,
+                            AAUDIO_SHARING_MODE_SHARED,
+                            AAUDIO_PERFORMANCE_MODE_NONE,
+                            AAUDIO_DIRECTION_OUTPUT);
+    result = testTimeStamps(policy,
+                            AAUDIO_SHARING_MODE_SHARED,
+                            AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                            AAUDIO_DIRECTION_OUTPUT);
+
+    // MMAP
+    policy = AAUDIO_POLICY_ALWAYS;
+    result = testTimeStamps(policy,
+                            AAUDIO_SHARING_MODE_EXCLUSIVE,
+                            AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                            AAUDIO_DIRECTION_INPUT);
+    result = testTimeStamps(policy,
+                            AAUDIO_SHARING_MODE_EXCLUSIVE,
+                            AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                            AAUDIO_DIRECTION_OUTPUT);
+    result = testTimeStamps(policy,
+                            AAUDIO_SHARING_MODE_SHARED,
+                            AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                            AAUDIO_DIRECTION_INPUT);
+    result = testTimeStamps(policy,
+                            AAUDIO_SHARING_MODE_SHARED,
+                            AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                            AAUDIO_DIRECTION_OUTPUT);
+
+    return (result == AAUDIO_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index a5f9ab6..b1cb0e7 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -135,7 +135,11 @@
             &mStatus, &mId, &enabled);
 
     if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
-        ALOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
+        char typeBuffer[64], uuidBuffer[64];
+        guidToString(type, typeBuffer, sizeof(typeBuffer));
+        guidToString(uuid, uuidBuffer, sizeof(uuidBuffer));
+        ALOGE("set(): AudioFlinger could not create effect %s / %s, status: %d",
+                typeBuffer, uuidBuffer, mStatus);
         if (iEffect == 0) {
             mStatus = NO_INIT;
         }
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 611cde7..ba4acc6 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -120,7 +120,7 @@
         }
         // No lock here: worst case we remove a NULL callback which will be a nop
         if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
-            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
+            AudioSystem::removeAudioDeviceCallback(this, mInput);
         }
         IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
         mAudioRecord.clear();
@@ -274,7 +274,7 @@
     mStatus = NO_ERROR;
     mUserData = user;
     // TODO: add audio hardware input latency here
-    mLatency = (1000 * mFrameCount) / mSampleRate;
+    mLatency = (1000LL * mFrameCount) / mSampleRate;
     mMarkerPosition = 0;
     mMarkerReached = false;
     mNewPosition = 0;
@@ -499,19 +499,26 @@
     return mSelectedDeviceId;
 }
 
+// must be called with mLock held
+void AudioRecord::updateRoutedDeviceId_l()
+{
+    // if the record is inactive, do not update actual device as the input stream maybe routed
+    // from a device not relevant to this client because of other active use cases.
+    if (!mActive) {
+        return;
+    }
+    if (mInput != AUDIO_IO_HANDLE_NONE) {
+        audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mInput);
+        if (deviceId != AUDIO_PORT_HANDLE_NONE) {
+            mRoutedDeviceId = deviceId;
+        }
+     }
+}
+
 audio_port_handle_t AudioRecord::getRoutedDeviceId() {
     AutoMutex lock(mLock);
-    if (mInput == AUDIO_IO_HANDLE_NONE) {
-        return AUDIO_PORT_HANDLE_NONE;
-    }
-    // if the input stream does not have an active audio patch, use either the device initially
-    // selected by audio policy manager or the last routed device
-    audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mInput);
-    if (deviceId == AUDIO_PORT_HANDLE_NONE) {
-        deviceId = mRoutedDeviceId;
-    }
-    mRoutedDeviceId = deviceId;
-    return deviceId;
+    updateRoutedDeviceId_l();
+    return mRoutedDeviceId;
 }
 
 // -------------------------------------------------------------------------
@@ -537,9 +544,6 @@
         return NO_INIT;
     }
 
-    if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
-        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
-    }
     audio_io_handle_t input;
 
     // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
@@ -744,6 +748,15 @@
     }
     mNotificationFramesAct = (uint32_t) notificationFrames;
 
+
+    //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation
+    if (mDeviceCallback != 0 && mInput != input) {
+        if (mInput != AUDIO_IO_HANDLE_NONE) {
+            AudioSystem::removeAudioDeviceCallback(this, mInput);
+        }
+        AudioSystem::addAudioDeviceCallback(this, input);
+    }
+
     // We retain a copy of the I/O handle, but don't own the reference
     mInput = input;
     mRefreshRemaining = true;
@@ -763,10 +776,6 @@
     mDeathNotifier = new DeathNotifier(this);
     IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);
 
-    if (mDeviceCallback != 0) {
-        AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput);
-    }
-
     return NO_ERROR;
 
     // End of retry loop.
@@ -1238,7 +1247,7 @@
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
-    if (mDeviceCallback == callback) {
+    if (mDeviceCallback.unsafe_get() == callback.get()) {
         ALOGW("%s adding same callback!", __FUNCTION__);
         return INVALID_OPERATION;
     }
@@ -1246,9 +1255,9 @@
     if (mInput != AUDIO_IO_HANDLE_NONE) {
         if (mDeviceCallback != 0) {
             ALOGW("%s callback already present!", __FUNCTION__);
-            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
+            AudioSystem::removeAudioDeviceCallback(this, mInput);
         }
-        status = AudioSystem::addAudioDeviceCallback(callback, mInput);
+        status = AudioSystem::addAudioDeviceCallback(this, mInput);
     }
     mDeviceCallback = callback;
     return status;
@@ -1262,17 +1271,38 @@
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
-    if (mDeviceCallback != callback) {
+    if (mDeviceCallback.unsafe_get() != callback.get()) {
         ALOGW("%s removing different callback!", __FUNCTION__);
         return INVALID_OPERATION;
     }
+    mDeviceCallback.clear();
     if (mInput != AUDIO_IO_HANDLE_NONE) {
-        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
+        AudioSystem::removeAudioDeviceCallback(this, mInput);
     }
-    mDeviceCallback = 0;
     return NO_ERROR;
 }
 
+void AudioRecord::onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                 audio_port_handle_t deviceId)
+{
+    sp<AudioSystem::AudioDeviceCallback> callback;
+    {
+        AutoMutex lock(mLock);
+        if (audioIo != mInput) {
+            return;
+        }
+        callback = mDeviceCallback.promote();
+        // only update device if the record is active as route changes due to other use cases are
+        // irrelevant for this client
+        if (mActive) {
+            mRoutedDeviceId = deviceId;
+        }
+    }
+    if (callback.get() != nullptr) {
+        callback->onAudioDeviceUpdate(mInput, mRoutedDeviceId);
+    }
+}
+
 // =========================================================================
 
 void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 2f710bd..cdc75ac 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -493,14 +493,16 @@
     if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return;
 
     audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
-    Vector < sp<AudioDeviceCallback> > callbacks;
+    Vector < wp<AudioDeviceCallback> > callbacks;
 
     {
         Mutex::Autolock _l(mLock);
 
         switch (event) {
         case AUDIO_OUTPUT_OPENED:
-        case AUDIO_INPUT_OPENED: {
+        case AUDIO_OUTPUT_REGISTERED:
+        case AUDIO_INPUT_OPENED:
+        case AUDIO_INPUT_REGISTERED: {
             sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle);
             if (oldDesc == 0) {
                 mIoDescriptors.add(ioDesc->mIoHandle, ioDesc);
@@ -511,13 +513,19 @@
 
             if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
                 deviceId = ioDesc->getDeviceId();
-                ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle);
-                if (ioIndex >= 0) {
-                    callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+                if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) {
+                    ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle);
+                    if (ioIndex >= 0) {
+                        callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+                    }
                 }
             }
-            ALOGV("ioConfigChanged() new %s opened %d samplingRate %u, format %#x channel mask %#x "
-                    "frameCount %zu deviceId %d", event == AUDIO_OUTPUT_OPENED ? "output" : "input",
+            ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x "
+                    "frameCount %zu deviceId %d",
+                    event == AUDIO_OUTPUT_OPENED || event == AUDIO_OUTPUT_REGISTERED ?
+                            "output" : "input",
+                            event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED ?
+                            "opened" : "registered",
                     ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask,
                     ioDesc->mFrameCount, ioDesc->getDeviceId());
             } break;
@@ -563,9 +571,23 @@
         } break;
         }
     }
+    bool callbackRemoved = false;
     // callbacks.size() != 0 =>  ioDesc->mIoHandle and deviceId are valid
-    for (size_t i = 0; i < callbacks.size(); i++) {
-        callbacks[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
+    for (size_t i = 0; i < callbacks.size(); ) {
+        sp<AudioDeviceCallback> callback = callbacks[i].promote();
+        if (callback.get() != nullptr) {
+            callback->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
+            i++;
+        } else {
+            callbacks.removeAt(i);
+            callbackRemoved = true;
+        }
+    }
+    // clean up callback list while we are here if some clients have disappeared without
+    // unregistering their callback
+    if (callbackRemoved) {
+        Mutex::Autolock _l(mLock);
+        mAudioDeviceCallbacks.replaceValueFor(ioDesc->mIoHandle, callbacks);
     }
 }
 
@@ -618,17 +640,17 @@
 }
 
 status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
-        const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
 {
     Mutex::Autolock _l(mLock);
-    Vector < sp<AudioDeviceCallback> > callbacks;
+    Vector < wp<AudioDeviceCallback> > callbacks;
     ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo);
     if (ioIndex >= 0) {
         callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
     }
 
     for (size_t cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) {
-        if (callbacks[cbIndex] == callback) {
+        if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) {
             return INVALID_OPERATION;
         }
     }
@@ -639,18 +661,18 @@
 }
 
 status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
-        const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
 {
     Mutex::Autolock _l(mLock);
     ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo);
     if (ioIndex < 0) {
         return INVALID_OPERATION;
     }
-    Vector < sp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+    Vector < wp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
 
     size_t cbIndex;
     for (cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) {
-        if (callbacks[cbIndex] == callback) {
+        if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) {
             break;
         }
     }
@@ -1128,7 +1150,7 @@
 }
 
 status_t AudioSystem::addAudioDeviceCallback(
-        const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
 {
     const sp<AudioFlingerClient> afc = getAudioFlingerClient();
     if (afc == 0) {
@@ -1145,7 +1167,7 @@
 }
 
 status_t AudioSystem::removeAudioDeviceCallback(
-        const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
 {
     const sp<AudioFlingerClient> afc = getAudioFlingerClient();
     if (afc == 0) {
@@ -1297,7 +1319,7 @@
 }
 
 void AudioSystem::AudioPolicyServiceClient::onRecordingConfigurationUpdate(
-        int event, audio_session_t session, audio_source_t source,
+        int event, const record_client_info_t *clientInfo,
         const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
         audio_patch_handle_t patchHandle) {
     record_config_callback cb = NULL;
@@ -1307,7 +1329,7 @@
     }
 
     if (cb != NULL) {
-        cb(event, session, source, clientConfig, deviceConfig, patchHandle);
+        cb(event, clientInfo, clientConfig, deviceConfig, patchHandle);
     }
 }
 
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index acf5a45..c6622cd 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -22,6 +22,7 @@
 #include <math.h>
 #include <sys/resource.h>
 
+#include <audio_utils/clock.h>
 #include <audio_utils/primitives.h>
 #include <binder/IPCThreadState.h>
 #include <media/AudioTrack.h>
@@ -62,9 +63,12 @@
     return tv.tv_sec * 1000000ll + tv.tv_nsec / 1000;
 }
 
-static inline nsecs_t convertTimespecToNs(const struct timespec &tv)
-{
-    return tv.tv_sec * (long long)NANOS_PER_SECOND + tv.tv_nsec;
+// TODO move to audio_utils.
+static inline struct timespec convertNsToTimespec(int64_t ns) {
+    struct timespec tv;
+    tv.tv_sec = static_cast<time_t>(ns / NANOS_PER_SECOND);
+    tv.tv_nsec = static_cast<long>(ns % NANOS_PER_SECOND);
+    return tv;
 }
 
 // current monotonic time in microseconds.
@@ -272,7 +276,7 @@
         }
         // No lock here: worst case we remove a NULL callback which will be a nop
         if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
-            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
+            AudioSystem::removeAudioDeviceCallback(this, mOutput);
         }
         IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
         mAudioTrack.clear();
@@ -543,7 +547,8 @@
     mUpdatePeriod = 0;
     mPosition = 0;
     mReleased = 0;
-    mStartUs = 0;
+    mStartNs = 0;
+    mStartFromZeroUs = 0;
     AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
     mSequence = 1;
     mObservedSequence = mSequence;
@@ -591,6 +596,7 @@
             mStartEts.clear();
         }
     }
+    mStartNs = systemTime(); // save this for timestamp adjustment after starting.
     if (previousState == STATE_STOPPED || previousState == STATE_FLUSHED) {
         // reset current position as seen by client to 0
         mPosition = 0;
@@ -609,7 +615,8 @@
                             + mStartEts.mPosition[ExtendedTimestamp::LOCATION_SERVER]),
                     (long long)mStartEts.mFlushed,
                     (long long)mFramesWritten);
-            mFramesWrittenServerOffset = -mStartEts.mPosition[ExtendedTimestamp::LOCATION_SERVER];
+            // mStartEts is already adjusted by mFramesWrittenServerOffset, so we delta adjust.
+            mFramesWrittenServerOffset -= mStartEts.mPosition[ExtendedTimestamp::LOCATION_SERVER];
         }
         mFramesWritten = 0;
         mProxy->clearTimestamp(); // need new server push for valid timestamp
@@ -619,7 +626,7 @@
         // since the flush is asynchronous and stop may not fully drain.
         // We save the time when the track is started to later verify whether
         // the counters are realistic (i.e. start from zero after this time).
-        mStartUs = getNowUs();
+        mStartFromZeroUs = mStartNs / 1000;
 
         // force refresh of remaining frames by processAudioBuffer() as last
         // write before stop could be partial.
@@ -1222,19 +1229,26 @@
     return mSelectedDeviceId;
 }
 
+// must be called with mLock held
+void AudioTrack::updateRoutedDeviceId_l()
+{
+    // if the track is inactive, do not update actual device as the output stream maybe routed
+    // to a device not relevant to this client because of other active use cases.
+    if (mState != STATE_ACTIVE) {
+        return;
+    }
+    if (mOutput != AUDIO_IO_HANDLE_NONE) {
+        audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mOutput);
+        if (deviceId != AUDIO_PORT_HANDLE_NONE) {
+            mRoutedDeviceId = deviceId;
+        }
+    }
+}
+
 audio_port_handle_t AudioTrack::getRoutedDeviceId() {
     AutoMutex lock(mLock);
-    if (mOutput == AUDIO_IO_HANDLE_NONE) {
-        return AUDIO_PORT_HANDLE_NONE;
-    }
-    // if the output stream does not have an active audio patch, use either the device initially
-    // selected by audio policy manager or the last routed device
-    audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mOutput);
-    if (deviceId == AUDIO_PORT_HANDLE_NONE) {
-        deviceId = mRoutedDeviceId;
-    }
-    mRoutedDeviceId = deviceId;
-    return deviceId;
+    updateRoutedDeviceId_l();
+    return mRoutedDeviceId;
 }
 
 status_t AudioTrack::attachAuxEffect(int effectId)
@@ -1272,7 +1286,7 @@
         ALOGW("getLatency(%d) failed status %d", mOutput, status);
     } else {
         // FIXME don't believe this lie
-        mLatency = mAfLatency + (1000 * mFrameCount) / mSampleRate;
+        mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
     }
 }
 
@@ -1298,12 +1312,10 @@
         return NO_INIT;
     }
 
-    if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
-        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
-    }
     audio_io_handle_t output;
     audio_stream_type_t streamType = mStreamType;
     audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
+    bool callbackAdded = false;
 
     // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
     // After fast request is denied, we will request again if IAudioTrack is re-created.
@@ -1508,12 +1520,14 @@
     sp<IMemory> iMem = track->getCblk();
     if (iMem == 0) {
         ALOGE("Could not get control block");
-        return NO_INIT;
+        status = NO_INIT;
+        goto release;
     }
     void *iMemPointer = iMem->pointer();
     if (iMemPointer == NULL) {
         ALOGE("Could not get control block pointer");
-        return NO_INIT;
+        status = NO_INIT;
+        goto release;
     }
     // invariant that mAudioTrack != 0 is true only after set() returns successfully
     if (mAudioTrack != 0) {
@@ -1584,6 +1598,15 @@
         }
     }
 
+    //mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation
+    if (mDeviceCallback != 0 && mOutput != output) {
+        if (mOutput != AUDIO_IO_HANDLE_NONE) {
+            AudioSystem::removeAudioDeviceCallback(this, mOutput);
+        }
+        AudioSystem::addAudioDeviceCallback(this, output);
+        callbackAdded = true;
+    }
+
     // We retain a copy of the I/O handle, but don't own the reference
     mOutput = output;
     mRefreshRemaining = true;
@@ -1599,7 +1622,8 @@
         buffers = mSharedBuffer->pointer();
         if (buffers == NULL) {
             ALOGE("Could not get buffer pointer");
-            return NO_INIT;
+            status = NO_INIT;
+            goto release;
         }
     }
 
@@ -1644,15 +1668,15 @@
     mDeathNotifier = new DeathNotifier(this);
     IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);
 
-    if (mDeviceCallback != 0) {
-        AudioSystem::addAudioDeviceCallback(mDeviceCallback, mOutput);
-    }
-
     return NO_ERROR;
     }
 
 release:
     AudioSystem::releaseOutput(output, streamType, mSessionId);
+    if (callbackAdded) {
+        // note: mOutput is always valid is callbackAdded is true
+        AudioSystem::removeAudioDeviceCallback(this, mOutput);
+    }
     if (status == NO_ERROR) {
         status = NO_INIT;
     }
@@ -2099,7 +2123,14 @@
     // Convert frame units to time units
     nsecs_t ns = NS_WHENEVER;
     if (minFrames != (uint32_t) ~0) {
-        ns = framesToNanoseconds(minFrames, sampleRate, speed) + kWaitPeriodNs;
+        // AudioFlinger consumption of client data may be irregular when coming out of device
+        // standby since the kernel buffers require filling. This is throttled to no more than 2x
+        // the expected rate in the MixerThread. Hence, we reduce the estimated time to wait by one
+        // half (but no more than half a second) to improve callback accuracy during these temporary
+        // data surges.
+        const nsecs_t estimatedNs = framesToNanoseconds(minFrames, sampleRate, speed);
+        constexpr nsecs_t maxThrottleCompensationNs = 500000000LL;
+        ns = estimatedNs - min(estimatedNs / 2, maxThrottleCompensationNs) + kWaitPeriodNs;
         ns -= (timeAfterCallbacks - timeBeforeCallbacks);  // account for callback time
         // TODO: Should we warn if the callback time is too long?
         if (ns < 0) ns = 0;
@@ -2572,7 +2603,7 @@
                 // We update the timestamp time even when paused.
                 if (mState == STATE_PAUSED /* not needed: STATE_PAUSED_STOPPING */) {
                     const int64_t now = systemTime();
-                    const int64_t at = convertTimespecToNs(timestamp.mTime);
+                    const int64_t at = audio_utils_ns_from_timespec(&timestamp.mTime);
                     const int64_t lag =
                             (ets.mTimeNs[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK] < 0 ||
                                 ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK] < 0)
@@ -2584,8 +2615,7 @@
                     if (at < limit) {
                         ALOGV("timestamp pause lag:%lld adjusting from %lld to %lld",
                                 (long long)lag, (long long)at, (long long)limit);
-                        timestamp.mTime.tv_sec = limit / NANOS_PER_SECOND;
-                        timestamp.mTime.tv_nsec = limit % NANOS_PER_SECOND; // compiler opt.
+                        timestamp.mTime = convertNsToTimespec(limit);
                     }
                 }
                 mPreviousLocation = location;
@@ -2628,18 +2658,18 @@
         // the previous song under gapless playback.
         // However, we sometimes see zero timestamps, then a glitch of
         // the previous song's position, and then correct timestamps afterwards.
-        if (mStartUs != 0 && mSampleRate != 0) {
+        if (mStartFromZeroUs != 0 && mSampleRate != 0) {
             static const int kTimeJitterUs = 100000; // 100 ms
             static const int k1SecUs = 1000000;
 
             const int64_t timeNow = getNowUs();
 
-            if (timeNow < mStartUs + k1SecUs) { // within first second of starting
+            if (timeNow < mStartFromZeroUs + k1SecUs) { // within first second of starting
                 const int64_t timestampTimeUs = convertTimespecToUs(timestamp.mTime);
-                if (timestampTimeUs < mStartUs) {
+                if (timestampTimeUs < mStartFromZeroUs) {
                     return WOULD_BLOCK;  // stale timestamp time, occurs before start.
                 }
-                const int64_t deltaTimeUs = timestampTimeUs - mStartUs;
+                const int64_t deltaTimeUs = timestampTimeUs - mStartFromZeroUs;
                 const int64_t deltaPositionByUs = (double)timestamp.mPosition * 1000000
                         / ((double)mSampleRate * mPlaybackRate.mSpeed);
 
@@ -2662,10 +2692,10 @@
                     return WOULD_BLOCK;
                 }
                 if (deltaPositionByUs != 0) {
-                    mStartUs = 0; // don't check again, we got valid nonzero position.
+                    mStartFromZeroUs = 0; // don't check again, we got valid nonzero position.
                 }
             } else {
-                mStartUs = 0; // don't check again, start time expired.
+                mStartFromZeroUs = 0; // don't check again, start time expired.
             }
             mTimestampStartupGlitchReported = false;
         }
@@ -2703,13 +2733,33 @@
     // Prevent retrograde motion in timestamp.
     // This is sometimes caused by erratic reports of the available space in the ALSA drivers.
     if (status == NO_ERROR) {
+        // previousTimestampValid is set to false when starting after a stop or flush.
         if (previousTimestampValid) {
-            const int64_t previousTimeNanos = convertTimespecToNs(mPreviousTimestamp.mTime);
-            const int64_t currentTimeNanos = convertTimespecToNs(timestamp.mTime);
+            const int64_t previousTimeNanos =
+                    audio_utils_ns_from_timespec(&mPreviousTimestamp.mTime);
+            int64_t currentTimeNanos = audio_utils_ns_from_timespec(&timestamp.mTime);
+
+            // Fix stale time when checking timestamp right after start().
+            //
+            // For offload compatibility, use a default lag value here.
+            // Any time discrepancy between this update and the pause timestamp is handled
+            // by the retrograde check afterwards.
+            const int64_t lagNs = int64_t(mAfLatency * 1000000LL);
+            const int64_t limitNs = mStartNs - lagNs;
+            if (currentTimeNanos < limitNs) {
+                ALOGD("correcting timestamp time for pause, "
+                        "currentTimeNanos: %lld < limitNs: %lld < mStartNs: %lld",
+                        (long long)currentTimeNanos, (long long)limitNs, (long long)mStartNs);
+                timestamp.mTime = convertNsToTimespec(limitNs);
+                currentTimeNanos = limitNs;
+            }
+
+            // retrograde check
             if (currentTimeNanos < previousTimeNanos) {
                 ALOGW("retrograde timestamp time corrected, %lld < %lld",
                         (long long)currentTimeNanos, (long long)previousTimeNanos);
                 timestamp.mTime = mPreviousTimestamp.mTime;
+                // currentTimeNanos not used below.
             }
 
             // Looking at signed delta will work even when the timestamps
@@ -2735,7 +2785,7 @@
 #if 0
             // Uncomment this to verify audio timestamp rate.
             const int64_t deltaTime =
-                    convertTimespecToNs(timestamp.mTime) - previousTimeNanos;
+                    audio_utils_ns_from_timespec(&timestamp.mTime) - previousTimeNanos;
             if (deltaTime != 0) {
                 const int64_t computedSampleRate =
                         deltaPosition * (long long)NANOS_PER_SECOND / deltaTime;
@@ -2827,7 +2877,7 @@
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
-    if (mDeviceCallback == callback) {
+    if (mDeviceCallback.unsafe_get() == callback.get()) {
         ALOGW("%s adding same callback!", __FUNCTION__);
         return INVALID_OPERATION;
     }
@@ -2835,9 +2885,9 @@
     if (mOutput != AUDIO_IO_HANDLE_NONE) {
         if (mDeviceCallback != 0) {
             ALOGW("%s callback already present!", __FUNCTION__);
-            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
+            AudioSystem::removeAudioDeviceCallback(this, mOutput);
         }
-        status = AudioSystem::addAudioDeviceCallback(callback, mOutput);
+        status = AudioSystem::addAudioDeviceCallback(this, mOutput);
     }
     mDeviceCallback = callback;
     return status;
@@ -2851,17 +2901,39 @@
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
-    if (mDeviceCallback != callback) {
+    if (mDeviceCallback.unsafe_get() != callback.get()) {
         ALOGW("%s removing different callback!", __FUNCTION__);
         return INVALID_OPERATION;
     }
+    mDeviceCallback.clear();
     if (mOutput != AUDIO_IO_HANDLE_NONE) {
-        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
+        AudioSystem::removeAudioDeviceCallback(this, mOutput);
     }
-    mDeviceCallback = 0;
     return NO_ERROR;
 }
 
+
+void AudioTrack::onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                 audio_port_handle_t deviceId)
+{
+    sp<AudioSystem::AudioDeviceCallback> callback;
+    {
+        AutoMutex lock(mLock);
+        if (audioIo != mOutput) {
+            return;
+        }
+        callback = mDeviceCallback.promote();
+        // only update device if the track is active as route changes due to other use cases are
+        // irrelevant for this client
+        if (mState == STATE_ACTIVE) {
+            mRoutedDeviceId = deviceId;
+        }
+    }
+    if (callback.get() != nullptr) {
+        callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId);
+    }
+}
+
 status_t AudioTrack::pendingDuration(int32_t *msec, ExtendedTimestamp::Location location)
 {
     if (msec == nullptr ||
@@ -2919,7 +2991,7 @@
     case STATE_STOPPED:
         if (isOffloadedOrDirect_l()) {
             // check if we have started in the past to return true.
-            return mStartUs > 0;
+            return mStartFromZeroUs > 0;
         }
         // A normal audio track may still be draining, so
         // check if stream has ended.  This covers fasttrack position
diff --git a/media/libaudioclient/AudioTrackShared.cpp b/media/libaudioclient/AudioTrackShared.cpp
index 08c37f8..7bf4f99 100644
--- a/media/libaudioclient/AudioTrackShared.cpp
+++ b/media/libaudioclient/AudioTrackShared.cpp
@@ -36,7 +36,7 @@
 // a value between "other" + 1 and "other" + INT32_MAX, the choice of
 // which needs to be the "least recently used" sequence value for "self".
 // In general, this means (new_self) returned is max(self, other) + 1.
-
+__attribute__((no_sanitize("integer")))
 static uint32_t incrementSequence(uint32_t self, uint32_t other) {
     int32_t diff = (int32_t) self - (int32_t) other;
     if (diff >= 0 && diff < INT32_MAX) {
@@ -393,6 +393,7 @@
 
 // ---------------------------------------------------------------------------
 
+__attribute__((no_sanitize("integer")))
 void AudioTrackClientProxy::flush()
 {
     // This works for mFrameCountP2 <= 2^30
@@ -840,6 +841,25 @@
     return filled;
 }
 
+__attribute__((no_sanitize("integer")))
+size_t AudioTrackServerProxy::framesReadySafe() const
+{
+    if (mIsShutdown) {
+        return 0;
+    }
+    const audio_track_cblk_t* cblk = mCblk;
+    const int32_t flush = android_atomic_acquire_load(&cblk->u.mStreaming.mFlush);
+    if (flush != mFlush) {
+        return mFrameCount;
+    }
+    const int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
+    const ssize_t filled = rear - cblk->u.mStreaming.mFront;
+    if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
+        return 0; // error condition, silently return 0.
+    }
+    return filled;
+}
+
 bool  AudioTrackServerProxy::setStreamEndDone() {
     audio_track_cblk_t* cblk = mCblk;
     bool old =
@@ -851,6 +871,7 @@
     return old;
 }
 
+__attribute__((no_sanitize("integer")))
 void AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount)
 {
     audio_track_cblk_t* cblk = mCblk;
@@ -908,6 +929,11 @@
     return mFramesReadySafe;
 }
 
+size_t StaticAudioTrackServerProxy::framesReadySafe() const
+{
+    return mFramesReadySafe;
+}
+
 status_t StaticAudioTrackServerProxy::updateStateWithLoop(
         StaticAudioTrackState *localState, const StaticAudioTrackState &update) const
 {
@@ -1001,6 +1027,7 @@
     return (ssize_t) mState.mPosition;
 }
 
+__attribute__((no_sanitize("integer")))
 status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
 {
     if (mIsShutdown) {
@@ -1047,6 +1074,7 @@
     return NO_ERROR;
 }
 
+__attribute__((no_sanitize("integer")))
 void StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer)
 {
     size_t stepCount = buffer->mFrameCount;
diff --git a/media/libaudioclient/IAudioPolicyServiceClient.cpp b/media/libaudioclient/IAudioPolicyServiceClient.cpp
index 98a0521..ad7f1de 100644
--- a/media/libaudioclient/IAudioPolicyServiceClient.cpp
+++ b/media/libaudioclient/IAudioPolicyServiceClient.cpp
@@ -48,6 +48,18 @@
     data.writeInt32((int32_t) config->format);
 }
 
+inline void readRecordClientInfoFromParcel(const Parcel& data, record_client_info_t *clientInfo) {
+    clientInfo->uid = (uid_t) data.readUint32();
+    clientInfo->session = (audio_session_t) data.readInt32();
+    clientInfo->source = (audio_source_t) data.readInt32();
+}
+
+inline void writeRecordClientInfoFromParcel(Parcel& data, const record_client_info_t *clientInfo) {
+    data.writeUint32((uint32_t) clientInfo->uid);
+    data.writeInt32((int32_t) clientInfo->session);
+    data.writeInt32((int32_t) clientInfo->source);
+}
+
 // ----------------------------------------------------------------------
 class BpAudioPolicyServiceClient : public BpInterface<IAudioPolicyServiceClient>
 {
@@ -80,14 +92,13 @@
         remote()->transact(MIX_STATE_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
     }
 
-    void onRecordingConfigurationUpdate(int event, audio_session_t session,
-            audio_source_t source, const audio_config_base_t *clientConfig,
+    void onRecordingConfigurationUpdate(int event, const record_client_info_t *clientInfo,
+            const audio_config_base_t *clientConfig,
             const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
         data.writeInt32(event);
-        data.writeInt32(session);
-        data.writeInt32(source);
+        writeRecordClientInfoFromParcel(data, clientInfo);
         writeAudioConfigBaseToParcel(data, clientConfig);
         writeAudioConfigBaseToParcel(data, deviceConfig);
         data.writeInt32(patchHandle);
@@ -123,14 +134,14 @@
     case RECORDING_CONFIGURATION_UPDATE: {
             CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
             int event = (int) data.readInt32();
-            audio_session_t session = (audio_session_t) data.readInt32();
-            audio_source_t source = (audio_source_t) data.readInt32();
+            record_client_info_t clientInfo;
             audio_config_base_t clientConfig;
             audio_config_base_t deviceConfig;
+            readRecordClientInfoFromParcel(data, &clientInfo);
             readAudioConfigBaseFromParcel(data, &clientConfig);
             readAudioConfigBaseFromParcel(data, &deviceConfig);
             audio_patch_handle_t patchHandle = (audio_patch_handle_t) data.readInt32();
-            onRecordingConfigurationUpdate(event, session, source, &clientConfig, &deviceConfig,
+            onRecordingConfigurationUpdate(event, &clientInfo, &clientConfig, &deviceConfig,
                     patchHandle);
             return NO_ERROR;
         } break;
diff --git a/media/libaudioclient/OWNERS b/media/libaudioclient/OWNERS
new file mode 100644
index 0000000..482b9fb
--- /dev/null
+++ b/media/libaudioclient/OWNERS
@@ -0,0 +1,3 @@
+gkasten@google.com
+jmtrivi@google.com
+mnaganov@google.com
diff --git a/media/libaudioclient/include/media/AudioIoDescriptor.h b/media/libaudioclient/include/media/AudioIoDescriptor.h
index fed86c9..859f1a9 100644
--- a/media/libaudioclient/include/media/AudioIoDescriptor.h
+++ b/media/libaudioclient/include/media/AudioIoDescriptor.h
@@ -20,9 +20,11 @@
 namespace android {
 
 enum audio_io_config_event {
+    AUDIO_OUTPUT_REGISTERED,
     AUDIO_OUTPUT_OPENED,
     AUDIO_OUTPUT_CLOSED,
     AUDIO_OUTPUT_CONFIG_CHANGED,
+    AUDIO_INPUT_REGISTERED,
     AUDIO_INPUT_OPENED,
     AUDIO_INPUT_CLOSED,
     AUDIO_INPUT_CONFIG_CHANGED,
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index e6a5efb..dd72170 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -33,7 +33,7 @@
 
 // ----------------------------------------------------------------------------
 
-class AudioRecord : public RefBase
+class AudioRecord : public AudioSystem::AudioDeviceCallback
 {
 public:
 
@@ -424,7 +424,12 @@
 
      /* Returns the ID of the audio device actually used by the input to which this AudioRecord
       * is attached.
-      * A value of AUDIO_PORT_HANDLE_NONE indicates the AudioRecord is not attached to any input.
+      * The device ID is relevant only if the AudioRecord is active.
+      * When the AudioRecord is inactive, the device ID returned can be either:
+      * - AUDIO_PORT_HANDLE_NONE if the AudioRecord is not attached to any output.
+      * - The device ID used before paused or stopped.
+      * - The device ID selected by audio policy manager of setOutputDevice() if the AudioRecord
+      * has not been started yet.
       *
       * Parameters:
       *  none.
@@ -454,6 +459,10 @@
             status_t removeAudioDeviceCallback(
                     const sp<AudioSystem::AudioDeviceCallback>& callback);
 
+            // AudioSystem::AudioDeviceCallback> virtuals
+            virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                             audio_port_handle_t deviceId);
+
 private:
     /* If nonContig is non-NULL, it is an output parameter that will be set to the number of
      * additional non-contiguous frames that are predicted to be available immediately,
@@ -561,6 +570,8 @@
             // FIXME enum is faster than strcmp() for parameter 'from'
             status_t restoreRecord_l(const char *from);
 
+            void     updateRoutedDeviceId_l();
+
     sp<AudioRecordThread>   mAudioRecordThread;
     mutable Mutex           mLock;
 
@@ -665,7 +676,7 @@
     audio_port_handle_t     mRoutedDeviceId;   // Device actually selected by audio policy manager:
                                               // May not match the app selection depending on other
                                               // activity and connected devices
-    sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
+    wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
     audio_port_handle_t    mPortId;  // unique ID allocated by audio policy
 
 };
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 2e39d23..5a81d83 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -33,7 +33,7 @@
 
 typedef void (*audio_error_callback)(status_t err);
 typedef void (*dynamic_policy_callback)(int event, String8 regId, int val);
-typedef void (*record_config_callback)(int event, audio_session_t session, int source,
+typedef void (*record_config_callback)(int event, const record_client_info_t *clientInfo,
                 const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
                 audio_patch_handle_t patchHandle);
 
@@ -370,9 +370,9 @@
                                          audio_port_handle_t deviceId) = 0;
     };
 
-    static status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+    static status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
                                            audio_io_handle_t audioIo);
-    static status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+    static status_t removeAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
                                               audio_io_handle_t audioIo);
 
     static audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
@@ -403,9 +403,9 @@
                                      const sp<AudioIoDescriptor>& ioDesc);
 
 
-        status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+        status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
                                                audio_io_handle_t audioIo);
-        status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+        status_t removeAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
                                            audio_io_handle_t audioIo);
 
         audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
@@ -413,7 +413,7 @@
     private:
         Mutex                               mLock;
         DefaultKeyedVector<audio_io_handle_t, sp<AudioIoDescriptor> >   mIoDescriptors;
-        DefaultKeyedVector<audio_io_handle_t, Vector < sp<AudioDeviceCallback> > >
+        DefaultKeyedVector<audio_io_handle_t, Vector < wp<AudioDeviceCallback> > >
                                                                         mAudioDeviceCallbacks;
         // cached values for recording getInputBufferSize() queries
         size_t                              mInBuffSize;    // zero indicates cache is invalid
@@ -440,8 +440,9 @@
         virtual void onAudioPortListUpdate();
         virtual void onAudioPatchListUpdate();
         virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
-        virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
-                        audio_source_t source, const audio_config_base_t *clientConfig,
+        virtual void onRecordingConfigurationUpdate(int event,
+                        const record_client_info_t *clientInfo,
+                        const audio_config_base_t *clientConfig,
                         const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
 
     private:
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index b168fc9..47d87e9 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -35,7 +35,7 @@
 
 // ----------------------------------------------------------------------------
 
-class AudioTrack : public RefBase
+class AudioTrack : public AudioSystem::AudioDeviceCallback
 {
 public:
 
@@ -605,7 +605,11 @@
 
      /* Returns the ID of the audio device actually used by the output to which this AudioTrack is
       * attached.
-      * A value of AUDIO_PORT_HANDLE_NONE indicates the audio track is not attached to any output.
+      * When the AudioTrack is inactive, the device ID returned can be either:
+      * - AUDIO_PORT_HANDLE_NONE if the AudioTrack is not attached to any output.
+      * - The device ID used before paused or stopped.
+      * - The device ID selected by audio policy manager of setOutputDevice() if the AudioTrack
+      * has not been started yet.
       *
       * Parameters:
       *  none.
@@ -845,6 +849,12 @@
             status_t removeAudioDeviceCallback(
                     const sp<AudioSystem::AudioDeviceCallback>& callback);
 
+            // AudioSystem::AudioDeviceCallback> virtuals
+            virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                             audio_port_handle_t deviceId);
+
+
+
     /* Obtain the pending duration in milliseconds for playback of pure PCM
      * (mixable without embedded timing) data remaining in AudioTrack.
      *
@@ -974,6 +984,8 @@
 
             void     restartIfDisabled();
 
+            void     updateRoutedDeviceId_l();
+
     // Next 4 fields may be changed if IAudioTrack is re-created, but always != 0
     sp<IAudioTrack>         mAudioTrack;
     sp<IMemory>             mCblkMemory;
@@ -1085,8 +1097,10 @@
                                                     // reset by stop() but continues monotonically
                                                     // after new IAudioTrack to restore mPosition,
                                                     // and could be easily widened to uint64_t
-    int64_t                 mStartUs;               // the start time after flush or stop.
+    int64_t                 mStartFromZeroUs;       // the start time after flush or stop,
+                                                    // when position should be 0.
                                                     // only used for offloaded and direct tracks.
+    int64_t                 mStartNs;               // the time when start() is called.
     ExtendedTimestamp       mStartEts;              // Extended timestamp at start for normal
                                                     // AudioTracks.
     AudioTimestamp          mStartTs;               // Timestamp at start for offloaded or direct
@@ -1163,7 +1177,7 @@
     uid_t                   mClientUid;
     pid_t                   mClientPid;
 
-    sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
+    wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
     audio_port_handle_t     mPortId;  // unique ID allocated by audio policy
 };
 
diff --git a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
index d94ad00..e0d2495 100644
--- a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
+++ b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
@@ -26,6 +26,16 @@
 
 // ----------------------------------------------------------------------------
 
+struct record_client_info {
+    uid_t uid;
+    audio_session_t session;
+    audio_source_t source;
+};
+
+typedef struct record_client_info record_client_info_t;
+
+// ----------------------------------------------------------------------------
+
 class IAudioPolicyServiceClient : public IInterface
 {
 public:
@@ -38,8 +48,8 @@
     // Notifies a change in the mixing state of a specific mix in a dynamic audio policy
     virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
     // Notifies a change of audio recording configuration
-    virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
-            audio_source_t source,
+    virtual void onRecordingConfigurationUpdate(int event,
+            const record_client_info_t *clientInfo,
             const audio_config_base_t *clientConfig,
             const audio_config_base_t *deviceConfig,
             audio_patch_handle_t patchHandle) = 0;
diff --git a/media/libaudiohal/Android.mk b/media/libaudiohal/Android.mk
index e592169..827908e 100644
--- a/media/libaudiohal/Android.mk
+++ b/media/libaudiohal/Android.mk
@@ -3,6 +3,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SHARED_LIBRARIES := \
+    libaudioutils \
     libcutils   \
     liblog      \
     libutils    \
diff --git a/media/libaudiohal/DeviceHalHidl.cpp b/media/libaudiohal/DeviceHalHidl.cpp
index 71fbd98..49ef991 100644
--- a/media/libaudiohal/DeviceHalHidl.cpp
+++ b/media/libaudiohal/DeviceHalHidl.cpp
@@ -98,7 +98,8 @@
 }  // namespace
 
 DeviceHalHidl::DeviceHalHidl(const sp<IDevice>& device)
-        : ConversionHelperHidl("Device"), mDevice(device) {
+        : ConversionHelperHidl("Device"), mDevice(device),
+          mPrimaryDevice(IPrimaryDevice::castFrom(device)) {
 }
 
 DeviceHalHidl::~DeviceHalHidl() {
@@ -120,24 +121,21 @@
 
 status_t DeviceHalHidl::setVoiceVolume(float volume) {
     if (mDevice == 0) return NO_INIT;
-    sp<IPrimaryDevice> primaryDev = IPrimaryDevice::castFrom(mDevice);
-    if (primaryDev == 0) return INVALID_OPERATION;
-    return processReturn("setVoiceVolume", primaryDev->setVoiceVolume(volume));
+    if (mPrimaryDevice == 0) return INVALID_OPERATION;
+    return processReturn("setVoiceVolume", mPrimaryDevice->setVoiceVolume(volume));
 }
 
 status_t DeviceHalHidl::setMasterVolume(float volume) {
     if (mDevice == 0) return NO_INIT;
-    sp<IPrimaryDevice> primaryDev = IPrimaryDevice::castFrom(mDevice);
-    if (primaryDev == 0) return INVALID_OPERATION;
-    return processReturn("setMasterVolume", primaryDev->setMasterVolume(volume));
+    if (mPrimaryDevice == 0) return INVALID_OPERATION;
+    return processReturn("setMasterVolume", mPrimaryDevice->setMasterVolume(volume));
 }
 
 status_t DeviceHalHidl::getMasterVolume(float *volume) {
     if (mDevice == 0) return NO_INIT;
-    sp<IPrimaryDevice> primaryDev = IPrimaryDevice::castFrom(mDevice);
-    if (primaryDev == 0) return INVALID_OPERATION;
+    if (mPrimaryDevice == 0) return INVALID_OPERATION;
     Result retval;
-    Return<void> ret = primaryDev->getMasterVolume(
+    Return<void> ret = mPrimaryDevice->getMasterVolume(
             [&](Result r, float v) {
                 retval = r;
                 if (retval == Result::OK) {
@@ -149,9 +147,8 @@
 
 status_t DeviceHalHidl::setMode(audio_mode_t mode) {
     if (mDevice == 0) return NO_INIT;
-    sp<IPrimaryDevice> primaryDev = IPrimaryDevice::castFrom(mDevice);
-    if (primaryDev == 0) return INVALID_OPERATION;
-    return processReturn("setMode", primaryDev->setMode(AudioMode(mode)));
+    if (mPrimaryDevice == 0) return INVALID_OPERATION;
+    return processReturn("setMode", mPrimaryDevice->setMode(AudioMode(mode)));
 }
 
 status_t DeviceHalHidl::setMicMute(bool state) {
diff --git a/media/libaudiohal/DeviceHalHidl.h b/media/libaudiohal/DeviceHalHidl.h
index 9da02a4..8651b51 100644
--- a/media/libaudiohal/DeviceHalHidl.h
+++ b/media/libaudiohal/DeviceHalHidl.h
@@ -18,11 +18,13 @@
 #define ANDROID_HARDWARE_DEVICE_HAL_HIDL_H
 
 #include <android/hardware/audio/2.0/IDevice.h>
+#include <android/hardware/audio/2.0/IPrimaryDevice.h>
 #include <media/audiohal/DeviceHalInterface.h>
 
 #include "ConversionHelperHidl.h"
 
 using ::android::hardware::audio::V2_0::IDevice;
+using ::android::hardware::audio::V2_0::IPrimaryDevice;
 using ::android::hardware::Return;
 
 namespace android {
@@ -110,6 +112,7 @@
   private:
     friend class DevicesFactoryHalHidl;
     sp<IDevice> mDevice;
+    sp<IPrimaryDevice> mPrimaryDevice;  // Null if it's not a primary device.
 
     // Can not be constructed directly by clients.
     explicit DeviceHalHidl(const sp<IDevice>& device);
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index b49b975..61fb6bab 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -40,7 +40,7 @@
 namespace android {
 
 EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
-        : mEffect(effect), mEffectId(effectId), mBuffersChanged(true) {
+        : mEffect(effect), mEffectId(effectId), mBuffersChanged(true), mEfGroup(nullptr) {
 }
 
 EffectHalHidl::~EffectHalHidl() {
@@ -49,6 +49,9 @@
         mEffect.clear();
         hardware::IPCThreadState::self()->flushCommands();
     }
+    if (mEfGroup) {
+        EventFlag::deleteEventFlag(&mEfGroup);
+    }
 }
 
 // static
diff --git a/media/libaudiohal/OWNERS b/media/libaudiohal/OWNERS
new file mode 100644
index 0000000..1456ab6
--- /dev/null
+++ b/media/libaudiohal/OWNERS
@@ -0,0 +1,2 @@
+krocard@google.com
+mnaganov@google.com
diff --git a/media/libaudiohal/StreamHalHidl.cpp b/media/libaudiohal/StreamHalHidl.cpp
index 42785d5..0cafa36 100644
--- a/media/libaudiohal/StreamHalHidl.cpp
+++ b/media/libaudiohal/StreamHalHidl.cpp
@@ -47,7 +47,20 @@
 StreamHalHidl::StreamHalHidl(IStream *stream)
         : ConversionHelperHidl("Stream"),
           mStream(stream),
-          mHalThreadPriority(HAL_THREAD_PRIORITY_DEFAULT) {
+          mHalThreadPriority(HAL_THREAD_PRIORITY_DEFAULT),
+          mCachedBufferSize(0){
+
+    // Instrument audio signal power logging.
+    // Note: This assumes channel mask, format, and sample rate do not change after creation.
+    if (mStream != nullptr && mStreamPowerLog.isUserDebugOrEngBuild()) {
+        // Obtain audio properties (see StreamHalHidl::getAudioProperties() below).
+        Return<void> ret = mStream->getAudioProperties(
+                [&](uint32_t sr, AudioChannelMask m, AudioFormat f) {
+                mStreamPowerLog.init(sr,
+                        static_cast<audio_channel_mask_t>(m),
+                        static_cast<audio_format_t>(f));
+            });
+    }
 }
 
 StreamHalHidl::~StreamHalHidl() {
@@ -61,7 +74,11 @@
 
 status_t StreamHalHidl::getBufferSize(size_t *size) {
     if (!mStream) return NO_INIT;
-    return processReturn("getBufferSize", mStream->getBufferSize(), size);
+    status_t status = processReturn("getBufferSize", mStream->getBufferSize(), size);
+    if (status == OK) {
+        mCachedBufferSize = *size;
+    }
+    return status;
 }
 
 status_t StreamHalHidl::getChannelMask(audio_channel_mask_t *mask) {
@@ -135,6 +152,7 @@
     hidlHandle->data[0] = fd;
     Return<void> ret = mStream->debugDump(hidlHandle);
     native_handle_delete(hidlHandle);
+    mStreamPowerLog.dump(fd);
     return processReturn("dump", ret);
 }
 
@@ -189,6 +207,14 @@
     return OK;
 }
 
+status_t StreamHalHidl::getCachedBufferSize(size_t *size) {
+    if (mCachedBufferSize != 0) {
+        *size = mCachedBufferSize;
+        return OK;
+    }
+    return getBufferSize(size);
+}
+
 bool StreamHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
     if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
         return true;
@@ -307,11 +333,22 @@
     }
 
     status_t status;
-    if (!mDataMQ && (status = prepareForWriting(bytes)) != OK) {
-        return status;
+    if (!mDataMQ) {
+        // In case if playback starts close to the end of a compressed track, the bytes
+        // that need to be written is less than the actual buffer size. Need to use
+        // full buffer size for the MQ since otherwise after seeking back to the middle
+        // data will be truncated.
+        size_t bufferSize;
+        if ((status = getCachedBufferSize(&bufferSize)) != OK) {
+            return status;
+        }
+        if (bytes > bufferSize) bufferSize = bytes;
+        if ((status = prepareForWriting(bufferSize)) != OK) {
+            return status;
+        }
     }
 
-    return callWriterThread(
+    status = callWriterThread(
             WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
             [&] (const WriteStatus& writeStatus) {
                 *written = writeStatus.reply.written;
@@ -320,6 +357,8 @@
                         "hal reports more bytes written than asked for: %lld > %lld",
                         (long long)*written, (long long)bytes);
             });
+    mStreamPowerLog.log(buffer, *written);
+    return status;
 }
 
 status_t StreamOutHalHidl::callWriterThread(
@@ -580,7 +619,7 @@
     ReadParameters params;
     params.command = ReadCommand::READ;
     params.params.read = bytes;
-    return callReaderThread(params, "read",
+    status = callReaderThread(params, "read",
             [&](const ReadStatus& readStatus) {
                 const size_t availToRead = mDataMQ->availableToRead();
                 if (!mDataMQ->read(static_cast<uint8_t*>(buffer), std::min(bytes, availToRead))) {
@@ -591,6 +630,8 @@
                         (int32_t)availToRead, (int32_t)readStatus.reply.read);
                 *read = readStatus.reply.read;
             });
+    mStreamPowerLog.log(buffer, *read);
+    return status;
 }
 
 status_t StreamInHalHidl::callReaderThread(
diff --git a/media/libaudiohal/StreamHalHidl.h b/media/libaudiohal/StreamHalHidl.h
index a7df276..d4ab943 100644
--- a/media/libaudiohal/StreamHalHidl.h
+++ b/media/libaudiohal/StreamHalHidl.h
@@ -27,6 +27,7 @@
 #include <media/audiohal/StreamHalInterface.h>
 
 #include "ConversionHelperHidl.h"
+#include "StreamPowerLog.h"
 
 using ::android::hardware::audio::V2_0::IStream;
 using ::android::hardware::audio::V2_0::IStreamIn;
@@ -101,12 +102,18 @@
     // The destructor automatically closes the stream.
     virtual ~StreamHalHidl();
 
+    status_t getCachedBufferSize(size_t *size);
+
     bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
 
+    // mStreamPowerLog is used for audio signal power logging.
+    StreamPowerLog mStreamPowerLog;
+
   private:
     const int HAL_THREAD_PRIORITY_DEFAULT = -1;
     IStream *mStream;
     int mHalThreadPriority;
+    size_t mCachedBufferSize;
 };
 
 class StreamOutHalHidl : public StreamOutHalInterface, public StreamHalHidl {
diff --git a/media/libaudiohal/StreamHalLocal.cpp b/media/libaudiohal/StreamHalLocal.cpp
index 05800a0..dc17f5c 100644
--- a/media/libaudiohal/StreamHalLocal.cpp
+++ b/media/libaudiohal/StreamHalLocal.cpp
@@ -27,7 +27,15 @@
 namespace android {
 
 StreamHalLocal::StreamHalLocal(audio_stream_t *stream, sp<DeviceHalLocal> device)
-        : mDevice(device), mStream(stream) {
+        : mDevice(device),
+          mStream(stream) {
+    // Instrument audio signal power logging.
+    // Note: This assumes channel mask, format, and sample rate do not change after creation.
+    if (mStream != nullptr && mStreamPowerLog.isUserDebugOrEngBuild()) {
+        mStreamPowerLog.init(mStream->get_sample_rate(mStream),
+                mStream->get_channels(mStream),
+                mStream->get_format(mStream));
+    }
 }
 
 StreamHalLocal::~StreamHalLocal() {
@@ -95,7 +103,9 @@
 }
 
 status_t StreamHalLocal::dump(int fd) {
-    return mStream->dump(mStream, fd);
+    status_t status = mStream->dump(mStream, fd);
+    mStreamPowerLog.dump(fd);
+    return status;
 }
 
 status_t StreamHalLocal::setHalThreadPriority(int) {
@@ -133,6 +143,7 @@
     ssize_t writeResult = mStream->write(mStream, buffer, bytes);
     if (writeResult > 0) {
         *written = writeResult;
+        mStreamPowerLog.log(buffer, *written);
         return OK;
     } else {
         *written = 0;
@@ -266,6 +277,7 @@
     ssize_t readResult = mStream->read(mStream, buffer, bytes);
     if (readResult > 0) {
         *read = readResult;
+        mStreamPowerLog.log( buffer, *read);
         return OK;
     } else {
         *read = 0;
diff --git a/media/libaudiohal/StreamHalLocal.h b/media/libaudiohal/StreamHalLocal.h
index 8c96c1f..c7136df 100644
--- a/media/libaudiohal/StreamHalLocal.h
+++ b/media/libaudiohal/StreamHalLocal.h
@@ -18,6 +18,7 @@
 #define ANDROID_HARDWARE_STREAM_HAL_LOCAL_H
 
 #include <media/audiohal/StreamHalInterface.h>
+#include "StreamPowerLog.h"
 
 namespace android {
 
@@ -83,6 +84,9 @@
 
     sp<DeviceHalLocal> mDevice;
 
+    // mStreamPowerLog is used for audio signal power logging.
+    StreamPowerLog mStreamPowerLog;
+
   private:
     audio_stream_t *mStream;
 };
diff --git a/media/libaudiohal/StreamPowerLog.h b/media/libaudiohal/StreamPowerLog.h
new file mode 100644
index 0000000..a78b1aa
--- /dev/null
+++ b/media/libaudiohal/StreamPowerLog.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_STREAM_POWER_LOG_H
+#define ANDROID_HARDWARE_STREAM_POWER_LOG_H
+
+#include <audio_utils/clock.h>
+#include <audio_utils/PowerLog.h>
+#include <cutils/properties.h>
+#include <system/audio.h>
+
+namespace android {
+
+class StreamPowerLog {
+public:
+    StreamPowerLog() :
+        mIsUserDebugOrEngBuild(is_userdebug_or_eng_build()),
+        mPowerLog(nullptr),
+        mFrameSize(0) {
+        // use init() to set up the power log.
+    }
+
+    ~StreamPowerLog() {
+        power_log_destroy(mPowerLog); // OK for null mPowerLog
+        mPowerLog = nullptr;
+    }
+
+    // A one-time initialization (do not call twice) before using StreamPowerLog.
+    void init(uint32_t sampleRate, audio_channel_mask_t channelMask, audio_format_t format) {
+        if (mPowerLog == nullptr) {
+            // Note: A way to get channel count for both input and output channel masks
+            // but does not check validity of the channel mask.
+            const uint32_t channelCount = popcount(audio_channel_mask_get_bits(channelMask));
+            mFrameSize = channelCount * audio_bytes_per_sample(format);
+            if (mFrameSize > 0) {
+                const size_t kPowerLogFramesPerEntry =
+                        (long long)sampleRate * kPowerLogSamplingIntervalMs / 1000;
+                mPowerLog = power_log_create(
+                        sampleRate,
+                        channelCount,
+                        format,
+                        kPowerLogEntries,
+                        kPowerLogFramesPerEntry);
+            }
+        }
+        // mPowerLog may be NULL (not the right build, format not accepted, etc.).
+    }
+
+    // Dump the power log to fd.
+    void dump(int fd) const {
+        // OK for null mPowerLog
+        (void)power_log_dump(
+                mPowerLog, fd, "      " /* prefix */, kPowerLogLines, 0 /* limit_ns */);
+    }
+
+    // Log the audio data contained in buffer.
+    void log(const void *buffer, size_t sizeInBytes) const {
+        if (mPowerLog != nullptr) { // mFrameSize is always nonzero if mPowerLog exists.
+            power_log_log(
+                    mPowerLog, buffer, sizeInBytes / mFrameSize, audio_utils_get_real_time_ns());
+        }
+    }
+
+    bool isUserDebugOrEngBuild() const {
+        return mIsUserDebugOrEngBuild;
+    }
+
+private:
+
+    static inline bool is_userdebug_or_eng_build() {
+        char value[PROPERTY_VALUE_MAX];
+        (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
+        return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
+    }
+
+    // Audio signal power log configuration.
+    static const size_t kPowerLogLines = 40;
+    static const size_t kPowerLogSamplingIntervalMs = 50;
+    static const size_t kPowerLogEntries = (1 /* minutes */ * 60 /* seconds */ * 1000 /* msec */
+            / kPowerLogSamplingIntervalMs);
+
+    const bool mIsUserDebugOrEngBuild;
+    power_log_t *mPowerLog;
+    size_t mFrameSize;
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_STREAM_POWER_LOG_H
diff --git a/media/libaudiohal/include/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
similarity index 100%
rename from media/libaudiohal/include/DeviceHalInterface.h
rename to media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
diff --git a/media/libaudiohal/include/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
similarity index 100%
rename from media/libaudiohal/include/DevicesFactoryHalInterface.h
rename to media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
diff --git a/media/libaudiohal/include/EffectBufferHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
similarity index 100%
rename from media/libaudiohal/include/EffectBufferHalInterface.h
rename to media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
diff --git a/media/libaudiohal/include/EffectHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectHalInterface.h
similarity index 100%
rename from media/libaudiohal/include/EffectHalInterface.h
rename to media/libaudiohal/include/media/audiohal/EffectHalInterface.h
diff --git a/media/libaudiohal/include/EffectsFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
similarity index 100%
rename from media/libaudiohal/include/EffectsFactoryHalInterface.h
rename to media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
diff --git a/media/libaudiohal/include/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
similarity index 100%
rename from media/libaudiohal/include/StreamHalInterface.h
rename to media/libaudiohal/include/media/audiohal/StreamHalInterface.h
diff --git a/media/libaudiohal/include/hidl/HalDeathHandler.h b/media/libaudiohal/include/media/audiohal/hidl/HalDeathHandler.h
similarity index 100%
rename from media/libaudiohal/include/hidl/HalDeathHandler.h
rename to media/libaudiohal/include/media/audiohal/hidl/HalDeathHandler.h
diff --git a/media/libaudioprocessing/include/AudioResampler.h b/media/libaudioprocessing/include/media/AudioResampler.h
similarity index 100%
rename from media/libaudioprocessing/include/AudioResampler.h
rename to media/libaudioprocessing/include/media/AudioResampler.h
diff --git a/media/libaudioprocessing/include/AudioResamplerPublic.h b/media/libaudioprocessing/include/media/AudioResamplerPublic.h
similarity index 100%
rename from media/libaudioprocessing/include/AudioResamplerPublic.h
rename to media/libaudioprocessing/include/media/AudioResamplerPublic.h
diff --git a/media/libeffects/Android.bp b/media/libeffects/Android.bp
index ccaa2b4..0dd3f17 100644
--- a/media/libeffects/Android.bp
+++ b/media/libeffects/Android.bp
@@ -1 +1 @@
-subdirs = ["factory"]
+subdirs = ["factory", "config"]
diff --git a/media/libeffects/OWNERS b/media/libeffects/OWNERS
new file mode 100644
index 0000000..7e3de13
--- /dev/null
+++ b/media/libeffects/OWNERS
@@ -0,0 +1,3 @@
+krocard@google.com
+mnaganov@google.com
+rago@google.com
diff --git a/media/libeffects/config/Android.bp b/media/libeffects/config/Android.bp
new file mode 100644
index 0000000..4398a91
--- /dev/null
+++ b/media/libeffects/config/Android.bp
@@ -0,0 +1,17 @@
+// Effect configuration
+cc_library_shared {
+    name: "libeffectsconfig",
+    vendor_available: true,
+
+    srcs: ["src/EffectsConfig.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libtinyxml2",
+    ],
+
+    header_libs: ["libaudio_system_headers"],
+    export_header_lib_headers: ["libaudio_system_headers"],
+
+    export_include_dirs: ["include"],
+}
diff --git a/media/libeffects/config/include/media/EffectsConfig.h b/media/libeffects/config/include/media/EffectsConfig.h
new file mode 100644
index 0000000..811730c
--- /dev/null
+++ b/media/libeffects/config/include/media/EffectsConfig.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_MEDIA_EFFECTSCONFIG_H
+#define ANDROID_MEDIA_EFFECTSCONFIG_H
+
+/** @file Parses audio effects configuration file to C and C++ structure.
+ * @see audio_effects_conf_V2_0.xsd for documentation on each structure
+ */
+
+#include <system/audio_effect.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace effectsConfig {
+
+/** Default path of effect configuration file. */
+constexpr char DEFAULT_PATH[] = "/vendor/etc/audio_effects.xml";
+
+/** Directories where the effect libraries will be search for. */
+constexpr const char* LD_EFFECT_LIBRARY_PATH[] =
+#ifdef __LP64__
+        {"/odm/lib64/soundfx", "/vendor/lib64/soundfx", "/system/lib64/soundfx"};
+#else
+        {"/odm/lib/soundfx", "/vendor/lib/soundfx", "/system/lib/soundfx"};
+#endif
+
+struct Library {
+    std::string name;
+    std::string path;
+};
+using Libraries = std::vector<Library>;
+
+struct EffectImpl {
+    Library* library; //< Only valid as long as the associated library vector is unmodified
+    effect_uuid_t uuid;
+};
+
+struct Effect : public EffectImpl {
+    std::string name;
+    bool isProxy;
+    EffectImpl libSw; //< Only valid if isProxy
+    EffectImpl libHw; //< Only valid if isProxy
+};
+
+using Effects = std::vector<Effect>;
+
+template <class Type>
+struct Stream {
+    Type type;
+    std::vector<std::reference_wrapper<Effect>> effects;
+};
+using OutputStream = Stream<audio_stream_type_t>;
+using InputStream = Stream<audio_source_t>;
+
+/** Parsed configuration.
+ * Intended to be a transient structure only used for deserialization.
+ * Note: Everything is copied in the configuration from the xml dom.
+ *       If copies needed to be avoided due to performance issue,
+ *       consider keeping a private handle on the xml dom and replace all strings by dom pointers.
+ *       Or even better, use SAX parsing to avoid the allocations all together.
+ */
+struct Config {
+    float version;
+    Libraries libraries;
+    Effects effects;
+    std::vector<OutputStream> postprocess;
+    std::vector<InputStream> preprocess;
+};
+
+/** Result of `parse(const char*)` */
+struct ParsingResult {
+    /** Parsed config, nullptr if the xml lib could not load the file */
+    std::unique_ptr<Config> parsedConfig;
+    size_t nbSkippedElement; //< Number of skipped invalid library, effect or processing chain
+};
+
+/** Parses the provided effect configuration.
+ * Parsing do not stop of first invalid element, but continues to the next.
+ * @see ParsingResult::nbSkippedElement
+ */
+ParsingResult parse(const char* path = DEFAULT_PATH);
+
+} // namespace effectsConfig
+} // namespace android
+#endif  // ANDROID_MEDIA_EFFECTSCONFIG_H
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
new file mode 100644
index 0000000..97462f8
--- /dev/null
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsConfig"
+
+#include <algorithm>
+#include <cstdint>
+#include <functional>
+#include <string>
+
+#include <tinyxml2.h>
+#include <log/log.h>
+
+#include <media/EffectsConfig.h>
+
+using namespace tinyxml2;
+
+namespace android {
+namespace effectsConfig {
+
+/** All functions except `parse(const char*)` are static. */
+namespace {
+
+/** @return all `node`s children that are elements and match the tag if provided. */
+std::vector<std::reference_wrapper<const XMLElement>> getChildren(const XMLNode& node,
+                                                                  const char* childTag = nullptr) {
+    std::vector<std::reference_wrapper<const XMLElement>> children;
+    for (auto* child = node.FirstChildElement(childTag); child != nullptr;
+            child = child->NextSiblingElement(childTag)) {
+        children.emplace_back(*child);
+    }
+    return children;
+}
+
+/** @return xml dump of the provided element.
+ * By not providing a printer, it is implicitly created in the caller context.
+ * In such case the return pointer has the same lifetime as the expression containing dump().
+ */
+const char* dump(const XMLElement& element, XMLPrinter&& printer = {}) {
+    element.Accept(&printer);
+    return printer.CStr();
+}
+
+
+bool stringToUuid(const char *str, effect_uuid_t *uuid)
+{
+    uint32_t tmp[10];
+
+    if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+            tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
+        return false;
+    }
+    uuid->timeLow = (uint32_t)tmp[0];
+    uuid->timeMid = (uint16_t)tmp[1];
+    uuid->timeHiAndVersion = (uint16_t)tmp[2];
+    uuid->clockSeq = (uint16_t)tmp[3];
+    uuid->node[0] = (uint8_t)tmp[4];
+    uuid->node[1] = (uint8_t)tmp[5];
+    uuid->node[2] = (uint8_t)tmp[6];
+    uuid->node[3] = (uint8_t)tmp[7];
+    uuid->node[4] = (uint8_t)tmp[8];
+    uuid->node[5] = (uint8_t)tmp[9];
+
+    return true;
+}
+
+/** Map the enum and string representation of a string type.
+ *  Intended to be specialized for each enum to deserialize.
+ *  The general template is disabled.
+ */
+template <class Enum>
+constexpr std::enable_if<false, Enum> STREAM_NAME_MAP;
+
+/** All output stream types which support effects.
+ * This need to be kept in sink with the xsd streamOutputType.
+ */
+template <>
+constexpr std::pair<audio_stream_type_t, const char*> STREAM_NAME_MAP<audio_stream_type_t>[] = {
+        {AUDIO_STREAM_VOICE_CALL, "voice_call"},
+        {AUDIO_STREAM_SYSTEM, "system"},
+        {AUDIO_STREAM_RING, "ring"},
+        {AUDIO_STREAM_MUSIC, "music"},
+        {AUDIO_STREAM_ALARM, "alarm"},
+        {AUDIO_STREAM_NOTIFICATION, "notification"},
+        {AUDIO_STREAM_BLUETOOTH_SCO, "bluetooth_sco"},
+        {AUDIO_STREAM_ENFORCED_AUDIBLE, "enforced_audible"},
+        {AUDIO_STREAM_DTMF, "dtmf"},
+        {AUDIO_STREAM_TTS, "tts"},
+};
+
+/** All input stream types which support effects.
+ * This need to be kept in sink with the xsd streamOutputType.
+ */
+template <>
+constexpr std::pair<audio_source_t, const char*> STREAM_NAME_MAP<audio_source_t>[] = {
+        {AUDIO_SOURCE_MIC, "mic"},
+        {AUDIO_SOURCE_VOICE_UPLINK, "voice_uplink"},
+        {AUDIO_SOURCE_VOICE_DOWNLINK, "voice_downlink"},
+        {AUDIO_SOURCE_VOICE_CALL, "voice_call"},
+        {AUDIO_SOURCE_CAMCORDER, "camcorder"},
+        {AUDIO_SOURCE_VOICE_RECOGNITION, "voice_recognition"},
+        {AUDIO_SOURCE_VOICE_COMMUNICATION, "voice_communication"},
+        {AUDIO_SOURCE_UNPROCESSED, "unprocessed"},
+};
+
+/** Find the stream type enum corresponding to the stream type name or return false */
+template <class Type>
+bool stringToStreamType(const char *streamName, Type* type)
+{
+    for (auto& streamNamePair : STREAM_NAME_MAP<Type>) {
+        if (strcmp(streamNamePair.second, streamName) == 0) {
+            *type = streamNamePair.first;
+            return true;
+        }
+    }
+    return false;
+}
+
+/** Parse a library xml note and push the result in libraries or return false on failure. */
+bool parseLibrary(const XMLElement& xmlLibrary, Libraries* libraries) {
+    const char* name = xmlLibrary.Attribute("name");
+    const char* path = xmlLibrary.Attribute("path");
+    if (name == nullptr || path == nullptr) {
+        ALOGE("library must have a name and a path: %s", dump(xmlLibrary));
+        return false;
+    }
+    libraries->push_back({name, path});
+    return true;
+}
+
+/** Find an element in a collection by its name.
+ * @return nullptr if not found, the ellements address if found.
+ */
+template <class T>
+T* findByName(const char* name, std::vector<T>& collection) {
+    auto it = find_if(begin(collection), end(collection),
+                         [name] (auto& item) { return item.name == name; });
+    return it != end(collection) ? &*it : nullptr;
+}
+
+/** Parse an effect from an xml element describing it.
+ * @return true and pushes the effect in effects on success,
+ *         false on failure. */
+bool parseEffect(const XMLElement& xmlEffect, Libraries& libraries, Effects* effects) {
+    Effect effect{};
+
+    const char* name = xmlEffect.Attribute("name");
+    if (name == nullptr) {
+        ALOGE("%s must have a name: %s", xmlEffect.Value(), dump(xmlEffect));
+        return false;
+    }
+    effect.name = name;
+
+    // Function to parse effect.library and effect.uuid from xml
+    auto parseImpl = [&libraries](const XMLElement& xmlImpl, EffectImpl& effect) {
+        // Retrieve library name and uuid from xml
+        const char* libraryName = xmlImpl.Attribute("library");
+        const char* uuid = xmlImpl.Attribute("uuid");
+        if (libraryName == nullptr || uuid == nullptr) {
+            ALOGE("effect must have a library name and a uuid: %s", dump(xmlImpl));
+            return false;
+        }
+
+        // Convert library name to a pointer to the previously loaded library
+        auto* library = findByName(libraryName, libraries);
+        if (library == nullptr) {
+            ALOGE("Could not find library referenced in: %s", dump(xmlImpl));
+            return false;
+        }
+        effect.library = library;
+
+        if (!stringToUuid(uuid, &effect.uuid)) {
+            ALOGE("Invalid uuid in: %s", dump(xmlImpl));
+            return false;
+        }
+        return true;
+    };
+
+    if (!parseImpl(xmlEffect, effect)) {
+        return false;
+    }
+
+    // Handle proxy effects
+    effect.isProxy = false;
+    if (std::strcmp(xmlEffect.Name(), "effectProxy") == 0) {
+        effect.isProxy = true;
+
+        // Function to parse libhw and libsw
+        auto parseProxy = [&xmlEffect, &parseImpl](const char* tag, EffectImpl& proxyLib) {
+            auto* xmlProxyLib = xmlEffect.FirstChildElement(tag);
+            if (xmlProxyLib == nullptr) {
+                ALOGE("effectProxy must contain a <%s>: %s", tag, dump(*xmlProxyLib));
+                return false;
+            }
+            return parseImpl(*xmlProxyLib, proxyLib);
+        };
+        if (!parseProxy("libhw", effect.libHw) || !parseProxy("libsw", effect.libSw)) {
+            return false;
+        }
+    }
+
+    effects->push_back(std::move(effect));
+    return true;
+}
+
+/** Parse an stream from an xml element describing it.
+ * @return true and pushes the stream in streams on success,
+ *         false on failure. */
+template <class Stream>
+bool parseStream(const XMLElement& xmlStream, Effects& effects, std::vector<Stream>* streams) {
+    const char* streamType = xmlStream.Attribute("type");
+    if (streamType == nullptr) {
+        ALOGE("stream must have a type: %s", dump(xmlStream));
+        return false;
+    }
+    Stream stream;
+    if (!stringToStreamType(streamType, &stream.type)) {
+        ALOGE("Invalid stream type %s: %s", streamType, dump(xmlStream));
+        return false;
+    }
+
+    for (auto& xmlApply : getChildren(xmlStream, "apply")) {
+        const char* effectName = xmlApply.get().Attribute("effect");
+        if (effectName == nullptr) {
+            ALOGE("stream/apply must have reference an effect: %s", dump(xmlApply));
+            return false;
+        }
+        auto* effect = findByName(effectName, effects);
+        if (effect == nullptr) {
+            ALOGE("Could not find effect referenced in: %s", dump(xmlApply));
+            return false;
+        }
+        stream.effects.emplace_back(*effect);
+    }
+    streams->push_back(std::move(stream));
+    return true;
+}
+
+}; // namespace
+
+ParsingResult parse(const char* path) {
+    XMLDocument doc;
+    doc.LoadFile(path);
+    if (doc.Error()) {
+        ALOGE("Failed to parse %s: Tinyxml2 error (%d): %s %s", path,
+              doc.ErrorID(), doc.GetErrorStr1(), doc.GetErrorStr2());
+        return {nullptr, 0};
+    }
+
+    auto config = std::make_unique<Config>();
+    size_t nbSkippedElements = 0;
+    auto registerFailure = [&nbSkippedElements](bool result) {
+        nbSkippedElements += result ? 0 : 1;
+    };
+    for (auto& xmlConfig : getChildren(doc, "audio_effects_conf")) {
+
+        // Parse library
+        for (auto& xmlLibraries : getChildren(xmlConfig, "libraries")) {
+            for (auto& xmlLibrary : getChildren(xmlLibraries, "library")) {
+                registerFailure(parseLibrary(xmlLibrary, &config->libraries));
+            }
+        }
+
+        // Parse effects
+        for (auto& xmlEffects : getChildren(xmlConfig, "effects")) {
+            for (auto& xmlEffect : getChildren(xmlEffects)) {
+                registerFailure(parseEffect(xmlEffect, config->libraries, &config->effects));
+            }
+        }
+
+        // Parse pre processing chains
+        for (auto& xmlPreprocess : getChildren(xmlConfig, "preprocess")) {
+            for (auto& xmlStream : getChildren(xmlPreprocess, "stream")) {
+                registerFailure(parseStream(xmlStream, config->effects, &config->preprocess));
+            }
+        }
+
+        // Parse post processing chains
+        for (auto& xmlPostprocess : getChildren(xmlConfig, "postprocess")) {
+            for (auto& xmlStream : getChildren(xmlPostprocess, "stream")) {
+                registerFailure(parseStream(xmlStream, config->effects, &config->postprocess));
+            }
+        }
+    }
+    return {std::move(config), nbSkippedElements};
+}
+
+} // namespace effectsConfig
+} // namespace android
diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk
index 73f6ef5..a5fbf14 100644
--- a/media/libeffects/downmix/Android.mk
+++ b/media/libeffects/downmix/Android.mk
@@ -20,6 +20,7 @@
 	$(call include-path-for, audio-effects) \
 	$(call include-path-for, audio-utils)
 
+#-DBUILD_FLOAT
 LOCAL_CFLAGS += -fvisibility=hidden
 LOCAL_CFLAGS += -Wall -Werror
 
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index 7c685ec..b4a1d77 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -33,6 +33,10 @@
 
 #define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
 
+#ifdef BUILD_FLOAT
+#define MINUS_3_DB_IN_FLOAT 0.70710678f // -3dB = 0.70710678f
+#endif
+
 // subset of possible audio_channel_mask_t values, and AUDIO_CHANNEL_OUT_* renamed to CHANNEL_MASK_*
 typedef enum {
     CHANNEL_MASK_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD_BACK,
@@ -82,8 +86,19 @@
 
 // number of effects in this library
 const int kNbEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
-
-
+#ifdef BUILD_FLOAT
+static LVM_FLOAT clamp_float(LVM_FLOAT a) {
+    if (a > 1.0f) {
+        return 1.0f;
+    }
+    else if (a < -1.0f) {
+        return -1.0f;
+    }
+    else {
+        return a;
+    }
+}
+#endif
 /*----------------------------------------------------------------------------
  * Test code
  *--------------------------------------------------------------------------*/
@@ -286,7 +301,7 @@
     return -EINVAL;
 }
 
-
+#ifndef BUILD_FLOAT
 /*--- Effect Control Interface Implementation ---*/
 
 static int Downmix_Process(effect_handle_t self,
@@ -385,7 +400,108 @@
 
     return 0;
 }
+#else /*BUILD_FLOAT*/
+/*--- Effect Control Interface Implementation ---*/
 
+static int Downmix_Process(effect_handle_t self,
+        audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+
+    downmix_object_t *pDownmixer;
+    LVM_FLOAT *pSrc, *pDst;
+    downmix_module_t *pDwmModule = (downmix_module_t *)self;
+
+    if (pDwmModule == NULL) {
+        return -EINVAL;
+    }
+
+    if (inBuffer == NULL || inBuffer->raw == NULL ||
+        outBuffer == NULL || outBuffer->raw == NULL ||
+        inBuffer->frameCount != outBuffer->frameCount) {
+        return -EINVAL;
+    }
+
+    pDownmixer = (downmix_object_t*) &pDwmModule->context;
+
+    if (pDownmixer->state == DOWNMIX_STATE_UNINITIALIZED) {
+        ALOGE("Downmix_Process error: trying to use an uninitialized downmixer");
+        return -EINVAL;
+    } else if (pDownmixer->state == DOWNMIX_STATE_INITIALIZED) {
+        ALOGE("Downmix_Process error: trying to use a non-configured downmixer");
+        return -ENODATA;
+    }
+
+    pSrc = (LVM_FLOAT *) inBuffer->s16;
+    pDst = (LVM_FLOAT *) outBuffer->s16;
+    size_t numFrames = outBuffer->frameCount;
+
+    const bool accumulate =
+            (pDwmModule->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+    const uint32_t downmixInputChannelMask = pDwmModule->config.inputCfg.channels;
+
+    switch(pDownmixer->type) {
+
+      case DOWNMIX_TYPE_STRIP:
+          if (accumulate) {
+              while (numFrames) {
+                  pDst[0] = clamp_float(pDst[0] + pSrc[0]);
+                  pDst[1] = clamp_float(pDst[1] + pSrc[1]);
+                  pSrc += pDownmixer->input_channel_count;
+                  pDst += 2;
+                  numFrames--;
+              }
+          } else {
+              while (numFrames) {
+                  pDst[0] = pSrc[0];
+                  pDst[1] = pSrc[1];
+                  pSrc += pDownmixer->input_channel_count;
+                  pDst += 2;
+                  numFrames--;
+              }
+          }
+          break;
+
+      case DOWNMIX_TYPE_FOLD:
+#ifdef DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER
+          // bypass the optimized downmix routines for the common formats
+          if (!Downmix_foldGeneric(
+                  downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) {
+              ALOGE("Multichannel configuration 0x%" PRIx32 " is not supported",
+                    downmixInputChannelMask);
+              return -EINVAL;
+          }
+          break;
+#endif
+        // optimize for the common formats
+        switch((downmix_input_channel_mask_t)downmixInputChannelMask) {
+        case CHANNEL_MASK_QUAD_BACK:
+        case CHANNEL_MASK_QUAD_SIDE:
+            Downmix_foldFromQuad(pSrc, pDst, numFrames, accumulate);
+            break;
+        case CHANNEL_MASK_5POINT1_BACK:
+        case CHANNEL_MASK_5POINT1_SIDE:
+            Downmix_foldFrom5Point1(pSrc, pDst, numFrames, accumulate);
+            break;
+        case CHANNEL_MASK_7POINT1:
+            Downmix_foldFrom7Point1(pSrc, pDst, numFrames, accumulate);
+            break;
+        default:
+            if (!Downmix_foldGeneric(
+                    downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) {
+                ALOGE("Multichannel configuration 0x%" PRIx32 " is not supported",
+                      downmixInputChannelMask);
+                return -EINVAL;
+            }
+            break;
+        }
+        break;
+
+      default:
+        return -EINVAL;
+    }
+
+    return 0;
+}
+#endif
 
 static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
         void *pCmdData, uint32_t *replySize, void *pReplyData) {
@@ -822,6 +938,7 @@
  *
  *----------------------------------------------------------------------------
  */
+#ifndef BUILD_FLOAT
 void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
     // sample at index 0 is FL
     // sample at index 1 is FR
@@ -849,7 +966,35 @@
         }
     }
 }
-
+#else
+void Downmix_foldFromQuad(LVM_FLOAT *pSrc, LVM_FLOAT *pDst, size_t numFrames, bool accumulate) {
+    // sample at index 0 is FL
+    // sample at index 1 is FR
+    // sample at index 2 is RL
+    // sample at index 3 is RR
+    if (accumulate) {
+        while (numFrames) {
+            // FL + RL
+            pDst[0] = clamp_float(pDst[0] + ((pSrc[0] + pSrc[2]) / 2.0f));
+            // FR + RR
+            pDst[1] = clamp_float(pDst[1] + ((pSrc[1] + pSrc[3]) / 2.0f));
+            pSrc += 4;
+            pDst += 2;
+            numFrames--;
+        }
+    } else { // same code as above but without adding and clamping pDst[i] to itself
+        while (numFrames) {
+            // FL + RL
+            pDst[0] = clamp_float((pSrc[0] + pSrc[2]) / 2.0f);
+            // FR + RR
+            pDst[1] = clamp_float((pSrc[1] + pSrc[3]) / 2.0f);
+            pSrc += 4;
+            pDst += 2;
+            numFrames--;
+        }
+    }
+}
+#endif
 
 /*----------------------------------------------------------------------------
  * Downmix_foldFrom5Point1()
@@ -868,6 +1013,7 @@
  *
  *----------------------------------------------------------------------------
  */
+#ifndef BUILD_FLOAT
 void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
     int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
     // sample at index 0 is FL
@@ -912,7 +1058,52 @@
         }
     }
 }
-
+#else
+void Downmix_foldFrom5Point1(LVM_FLOAT *pSrc, LVM_FLOAT *pDst, size_t numFrames, bool accumulate) {
+    LVM_FLOAT lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
+    // sample at index 0 is FL
+    // sample at index 1 is FR
+    // sample at index 2 is FC
+    // sample at index 3 is LFE
+    // sample at index 4 is RL
+    // sample at index 5 is RR
+    // code is mostly duplicated between the two values of accumulate to avoid repeating the test
+    // for every sample
+    if (accumulate) {
+        while (numFrames) {
+            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_FLOAT)
+                    + (pSrc[3] * MINUS_3_DB_IN_FLOAT);
+            // FL + centerPlusLfeContrib + RL
+            lt = pSrc[0] + centerPlusLfeContrib + pSrc[4];
+            // FR + centerPlusLfeContrib + RR
+            rt = pSrc[1] + centerPlusLfeContrib + pSrc[5];
+            // accumulate in destination
+            pDst[0] = clamp_float(pDst[0] + (lt / 2.0f));
+            pDst[1] = clamp_float(pDst[1] + (rt / 2.0f));
+            pSrc += 6;
+            pDst += 2;
+            numFrames--;
+        }
+    } else { // same code as above but without adding and clamping pDst[i] to itself
+        while (numFrames) {
+            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_FLOAT)
+                    + (pSrc[3] * MINUS_3_DB_IN_FLOAT);
+            // FL + centerPlusLfeContrib + RL
+            lt = pSrc[0] + centerPlusLfeContrib + pSrc[4];
+            // FR + centerPlusLfeContrib + RR
+            rt = pSrc[1] + centerPlusLfeContrib + pSrc[5];
+            // store in destination
+            pDst[0] = clamp_float(lt / 2.0f); // differs from when accumulate is true above
+            pDst[1] = clamp_float(rt / 2.0f); // differs from when accumulate is true above
+            pSrc += 6;
+            pDst += 2;
+            numFrames--;
+        }
+    }
+}
+#endif
 
 /*----------------------------------------------------------------------------
  * Downmix_foldFrom7Point1()
@@ -931,6 +1122,7 @@
  *
  *----------------------------------------------------------------------------
  */
+#ifndef BUILD_FLOAT
 void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
     int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
     // sample at index 0 is FL
@@ -977,8 +1169,54 @@
         }
     }
 }
-
-
+#else
+void Downmix_foldFrom7Point1(LVM_FLOAT *pSrc, LVM_FLOAT *pDst, size_t numFrames, bool accumulate) {
+    LVM_FLOAT lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
+    // sample at index 0 is FL
+    // sample at index 1 is FR
+    // sample at index 2 is FC
+    // sample at index 3 is LFE
+    // sample at index 4 is RL
+    // sample at index 5 is RR
+    // sample at index 6 is SL
+    // sample at index 7 is SR
+    // code is mostly duplicated between the two values of accumulate to avoid repeating the test
+    // for every sample
+    if (accumulate) {
+        while (numFrames) {
+            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
+                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+            // FL + centerPlusLfeContrib + SL + RL
+            lt = pSrc[0] + centerPlusLfeContrib + pSrc[6] + pSrc[4];
+            // FR + centerPlusLfeContrib + SR + RR
+            rt = pSrc[1] + centerPlusLfeContrib + pSrc[7] + pSrc[5];
+            //accumulate in destination
+            pDst[0] = clamp_float(pDst[0] + (lt / 2.0f));
+            pDst[1] = clamp_float(pDst[1] + (rt / 2.0f));
+            pSrc += 8;
+            pDst += 2;
+            numFrames--;
+        }
+    } else { // same code as above but without adding and clamping pDst[i] to itself
+        while (numFrames) {
+            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_FLOAT)
+                    + (pSrc[3] * MINUS_3_DB_IN_FLOAT);
+            // FL + centerPlusLfeContrib + SL + RL
+            lt = pSrc[0] + centerPlusLfeContrib + pSrc[6] + pSrc[4];
+            // FR + centerPlusLfeContrib + SR + RR
+            rt = pSrc[1] + centerPlusLfeContrib + pSrc[7] + pSrc[5];
+            // store in destination
+            pDst[0] = clamp_float(lt / 2.0f); // differs from when accumulate is true above
+            pDst[1] = clamp_float(rt / 2.0f); // differs from when accumulate is true above
+            pSrc += 8;
+            pDst += 2;
+            numFrames--;
+        }
+    }
+}
+#endif
 /*----------------------------------------------------------------------------
  * Downmix_foldGeneric()
  *----------------------------------------------------------------------------
@@ -1005,6 +1243,7 @@
  *
  *----------------------------------------------------------------------------
  */
+#ifndef BUILD_FLOAT
 bool Downmix_foldGeneric(
         uint32_t mask, int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
 
@@ -1096,3 +1335,96 @@
     }
     return true;
 }
+#else
+bool Downmix_foldGeneric(
+        uint32_t mask, LVM_FLOAT *pSrc, LVM_FLOAT *pDst, size_t numFrames, bool accumulate) {
+
+    if (!Downmix_validChannelMask(mask)) {
+        return false;
+    }
+
+    const bool hasSides = (mask & kSides) != 0;
+    const bool hasBacks = (mask & kBacks) != 0;
+
+    const int numChan = audio_channel_count_from_out_mask(mask);
+    const bool hasFC = ((mask & AUDIO_CHANNEL_OUT_FRONT_CENTER) == AUDIO_CHANNEL_OUT_FRONT_CENTER);
+    const bool hasLFE =
+            ((mask & AUDIO_CHANNEL_OUT_LOW_FREQUENCY) == AUDIO_CHANNEL_OUT_LOW_FREQUENCY);
+    const bool hasBC = ((mask & AUDIO_CHANNEL_OUT_BACK_CENTER) == AUDIO_CHANNEL_OUT_BACK_CENTER);
+    // compute at what index each channel is: samples will be in the following order:
+    //   FL FR FC LFE BL BR BC SL SR
+    // when a channel is not present, its index is set to the same as the index of the preceding
+    // channel
+    const int indexFC  = hasFC    ? 2            : 1;        // front center
+    const int indexLFE = hasLFE   ? indexFC + 1  : indexFC;  // low frequency
+    const int indexBL  = hasBacks ? indexLFE + 1 : indexLFE; // back left
+    const int indexBR  = hasBacks ? indexBL + 1  : indexBL;  // back right
+    const int indexBC  = hasBC    ? indexBR + 1  : indexBR;  // back center
+    const int indexSL  = hasSides ? indexBC + 1  : indexBC;  // side left
+    const int indexSR  = hasSides ? indexSL + 1  : indexSL;  // side right
+
+    LVM_FLOAT lt, rt, centersLfeContrib;
+    // code is mostly duplicated between the two values of accumulate to avoid repeating the test
+    // for every sample
+    if (accumulate) {
+        while (numFrames) {
+            // compute contribution of FC, BC and LFE
+            centersLfeContrib = 0;
+            if (hasFC)  { centersLfeContrib += pSrc[indexFC]; }
+            if (hasLFE) { centersLfeContrib += pSrc[indexLFE]; }
+            if (hasBC)  { centersLfeContrib += pSrc[indexBC]; }
+            centersLfeContrib *= MINUS_3_DB_IN_FLOAT;
+            // always has FL/FR
+            lt = pSrc[0];
+            rt = pSrc[1];
+            // mix in sides and backs
+            if (hasSides) {
+                lt += pSrc[indexSL];
+                rt += pSrc[indexSR];
+            }
+            if (hasBacks) {
+                lt += pSrc[indexBL];
+                rt += pSrc[indexBR];
+            }
+            lt += centersLfeContrib;
+            rt += centersLfeContrib;
+            // accumulate in destination
+            pDst[0] = clamp_float(pDst[0] + (lt / 2.0f));
+            pDst[1] = clamp_float(pDst[1] + (rt / 2.0f));
+            pSrc += numChan;
+            pDst += 2;
+            numFrames--;
+        }
+    } else {
+        while (numFrames) {
+            // compute contribution of FC, BC and LFE
+            centersLfeContrib = 0;
+            if (hasFC)  { centersLfeContrib += pSrc[indexFC]; }
+            if (hasLFE) { centersLfeContrib += pSrc[indexLFE]; }
+            if (hasBC)  { centersLfeContrib += pSrc[indexBC]; }
+            centersLfeContrib *= MINUS_3_DB_IN_FLOAT;
+            // always has FL/FR
+            lt = pSrc[0];
+            rt = pSrc[1];
+            // mix in sides and backs
+            if (hasSides) {
+                lt += pSrc[indexSL];
+                rt += pSrc[indexSR];
+            }
+            if (hasBacks) {
+                lt += pSrc[indexBL];
+                rt += pSrc[indexBR];
+            }
+            lt += centersLfeContrib;
+            rt += centersLfeContrib;
+            // store in destination
+            pDst[0] = clamp_float(lt / 2.0f); // differs from when accumulate is true above
+            pDst[1] = clamp_float(rt / 2.0f); // differs from when accumulate is true above
+            pSrc += numChan;
+            pDst += 2;
+            numFrames--;
+        }
+    }
+    return true;
+}
+#endif
\ No newline at end of file
diff --git a/media/libeffects/downmix/EffectDownmix.h b/media/libeffects/downmix/EffectDownmix.h
index 2399abd..c1be0f2 100644
--- a/media/libeffects/downmix/EffectDownmix.h
+++ b/media/libeffects/downmix/EffectDownmix.h
@@ -27,7 +27,9 @@
 */
 
 #define DOWNMIX_OUTPUT_CHANNELS AUDIO_CHANNEL_OUT_STEREO
-
+#ifdef BUILD_FLOAT
+#define LVM_FLOAT float
+#endif
 typedef enum {
     DOWNMIX_STATE_UNINITIALIZED,
     DOWNMIX_STATE_INITIALIZED,
@@ -95,11 +97,18 @@
 int Downmix_Reset(downmix_object_t *pDownmixer, bool init);
 int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue);
 int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t *pSize, void *pValue);
-
+#ifdef BUILD_FLOAT
+void Downmix_foldFromQuad(LVM_FLOAT *pSrc, LVM_FLOAT *pDst, size_t numFrames, bool accumulate);
+void Downmix_foldFrom5Point1(LVM_FLOAT *pSrc, LVM_FLOAT *pDst, size_t numFrames, bool accumulate);
+void Downmix_foldFrom7Point1(LVM_FLOAT *pSrc, LVM_FLOAT *pDst, size_t numFrames, bool accumulate);
+bool Downmix_foldGeneric(
+        uint32_t mask, LVM_FLOAT *pSrc, LVM_FLOAT *pDst, size_t numFrames, bool accumulate);
+#else
 void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
 void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
 void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
 bool Downmix_foldGeneric(
         uint32_t mask, int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+#endif
 
 #endif /*ANDROID_EFFECTDOWNMIX_H_*/
diff --git a/media/libeffects/factory/Android.bp b/media/libeffects/factory/Android.bp
index 16680bd..ddbfdd8 100644
--- a/media/libeffects/factory/Android.bp
+++ b/media/libeffects/factory/Android.bp
@@ -10,18 +10,47 @@
 cc_library_shared {
     name: "libeffects",
     vendor: true,
-    srcs: ["EffectsFactory.c"],
+    srcs: [
+         "EffectsFactory.c",
+         "EffectsConfigLoader.c",
+         "EffectsFactoryState.c",
+         "EffectsXmlConfigLoader.cpp",
+    ],
 
     shared_libs: [
         "libcutils",
         "liblog",
         "libdl",
+        "libeffectsconfig",
     ],
-
-    include_dirs: ["system/media/audio_effects/include"],
+    cflags: ["-fvisibility=hidden"],
 
     local_include_dirs:["include/media"],
 
-    header_libs: ["libeffects_headers"],
+    header_libs: [
+        "libaudioeffects",
+        "libeffects_headers",
+    ],
     export_header_lib_headers: ["libeffects_headers"],
 }
+
+cc_binary {
+    name: "dumpEffectConfigFile",
+    vendor: true,
+    srcs: ["test/DumpConfig.cpp"],
+
+    compile_multilib: "32",
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+
+
+    shared_libs: [
+        "libeffectsconfig",
+        "libeffects",
+    ],
+    local_include_dirs:[".", "include"],
+}
diff --git a/media/libeffects/factory/EffectsConfigLoader.c b/media/libeffects/factory/EffectsConfigLoader.c
new file mode 100644
index 0000000..fcef36f
--- /dev/null
+++ b/media/libeffects/factory/EffectsConfigLoader.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsFactoryConfigLoader"
+//#define LOG_NDEBUG 0
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <cutils/config_utils.h>
+#include <cutils/misc.h>
+#include <log/log.h>
+
+#include <system/audio_effects/audio_effects_conf.h>
+
+#include "EffectsConfigLoader.h"
+#include "EffectsFactoryState.h"
+
+/////////////////////////////////////////////////
+//      Local functions prototypes
+/////////////////////////////////////////////////
+
+static int loadEffectConfigFile(const char *path);
+static int loadLibraries(cnode *root);
+static int loadLibrary(cnode *root, const char *name);
+static int loadEffects(cnode *root);
+static int loadEffect(cnode *node);
+// To get and add the effect pointed by the passed node to the gSubEffectList
+static int addSubEffect(cnode *root);
+static lib_entry_t *getLibrary(const char *path);
+
+static lib_entry_t *gCachedLibrary;  // last library accessed by getLibrary()
+
+int EffectLoadEffectConfig()
+{
+    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
+        return loadEffectConfigFile(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
+        return loadEffectConfigFile(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+    }
+    return 0;
+}
+
+int loadEffectConfigFile(const char *path)
+{
+    cnode *root;
+    char *data;
+
+    data = load_file(path, NULL);
+    if (data == NULL) {
+        return -ENODEV;
+    }
+    root = config_node("", "");
+    config_load(root, data);
+    loadLibraries(root);
+    loadEffects(root);
+    config_free(root);
+    free(root);
+    free(data);
+
+    return 0;
+}
+
+int loadLibraries(cnode *root)
+{
+    cnode *node;
+
+    node = config_find(root, LIBRARIES_TAG);
+    if (node == NULL) {
+        return -ENOENT;
+    }
+    node = node->first_child;
+    while (node) {
+        loadLibrary(node, node->name);
+        node = node->next;
+    }
+    return 0;
+}
+
+#ifdef __LP64__
+// audio_effects.conf always specifies 32 bit lib path: convert to 64 bit path if needed
+static const char *kLibraryPathRoot[] =
+        {"/odm/lib64/soundfx", "/vendor/lib64/soundfx", "/system/lib64/soundfx"};
+#else
+static const char *kLibraryPathRoot[] =
+        {"/odm/lib/soundfx", "/vendor/lib/soundfx", "/system/lib/soundfx"};
+#endif
+
+static const int kLibraryPathRootSize =
+        (sizeof(kLibraryPathRoot) / sizeof(kLibraryPathRoot[0]));
+
+// Checks if the library path passed as lib_path_in can be opened and if not
+// tries in standard effect library directories with just the library name and returns correct path
+// in lib_path_out
+int checkLibraryPath(const char *lib_path_in, char *lib_path_out) {
+    char *str;
+    const char *lib_name;
+    size_t len;
+
+    if (lib_path_in == NULL || lib_path_out == NULL) {
+        return -EINVAL;
+    }
+
+    strlcpy(lib_path_out, lib_path_in, PATH_MAX);
+
+    // Try exact path first
+    str = strstr(lib_path_out, "/lib/soundfx/");
+    if (str == NULL) {
+        return -EINVAL;
+    }
+
+    // Extract library name from input path
+    len = str - lib_path_out;
+    lib_name = lib_path_in + len + strlen("/lib/soundfx/");
+
+    // Then try with library name and standard path names in order of preference
+    for (int i = 0; i < kLibraryPathRootSize; i++) {
+        char path[PATH_MAX];
+
+        snprintf(path,
+                 PATH_MAX,
+                 "%s/%s",
+                 kLibraryPathRoot[i],
+                 lib_name);
+        if (F_OK == access(path, 0)) {
+            strcpy(lib_path_out, path);
+            ALOGW_IF(strncmp(lib_path_out, lib_path_in, PATH_MAX) != 0,
+                "checkLibraryPath() corrected library path %s to %s", lib_path_in, lib_path_out);
+            return 0;
+        }
+    }
+    return -EINVAL;
+}
+
+
+
+int loadLibrary(cnode *root, const char *name)
+{
+    cnode *node;
+    void *hdl = NULL;
+    audio_effect_library_t *desc;
+    list_elem_t *e;
+    lib_entry_t *l;
+    char path[PATH_MAX];
+
+    node = config_find(root, PATH_TAG);
+    if (node == NULL) {
+        return -EINVAL;
+    }
+
+    if (checkLibraryPath((const char *)node->value, path) != 0) {
+        ALOGW("loadLibrary() could not find library %s", path);
+        goto error;
+    }
+
+    hdl = dlopen(path, RTLD_NOW);
+    if (hdl == NULL) {
+        ALOGW("loadLibrary() failed to open %s", path);
+        goto error;
+    }
+
+    desc = (audio_effect_library_t *)dlsym(hdl, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+    if (desc == NULL) {
+        ALOGW("loadLibrary() could not find symbol %s", AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+        goto error;
+    }
+
+    if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) {
+        ALOGW("getLibrary() bad tag %08x in lib info struct", desc->tag);
+        goto error;
+    }
+
+    if (EFFECT_API_VERSION_MAJOR(desc->version) !=
+            EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) {
+        ALOGW("loadLibrary() bad lib version %08x", desc->version);
+        goto error;
+    }
+
+    // add entry for library in gLibraryList
+    l = malloc(sizeof(lib_entry_t));
+    l->name = strndup(name, PATH_MAX);
+    l->path = strndup(path, PATH_MAX);
+    l->handle = hdl;
+    l->desc = desc;
+    l->effects = NULL;
+    pthread_mutex_init(&l->lock, NULL);
+
+    e = malloc(sizeof(list_elem_t));
+    e->object = l;
+    pthread_mutex_lock(&gLibLock);
+    e->next = gLibraryList;
+    gLibraryList = e;
+    pthread_mutex_unlock(&gLibLock);
+    ALOGV("getLibrary() linked library %p for path %s", l, path);
+
+    return 0;
+
+error:
+    if (hdl != NULL) {
+        dlclose(hdl);
+    }
+    //add entry for library errors in gLibraryFailedList
+    lib_failed_entry_t *fl = malloc(sizeof(lib_failed_entry_t));
+    fl->name = strndup(name, PATH_MAX);
+    fl->path = strndup(path, PATH_MAX);
+
+    list_elem_t *fe = malloc(sizeof(list_elem_t));
+    fe->object = fl;
+    fe->next = gLibraryFailedList;
+    gLibraryFailedList = fe;
+    ALOGV("getLibrary() linked error in library %p for path %s", fl, path);
+
+    return -EINVAL;
+}
+
+// This will find the library and UUID tags of the sub effect pointed by the
+// node, gets the effect descriptor and lib_entry_t and adds the subeffect -
+// sub_entry_t to the gSubEffectList
+int addSubEffect(cnode *root)
+{
+    ALOGV("addSubEffect");
+    cnode *node;
+    effect_uuid_t uuid;
+    effect_descriptor_t *d;
+    lib_entry_t *l;
+    list_elem_t *e;
+    node = config_find(root, LIBRARY_TAG);
+    if (node == NULL) {
+        return -EINVAL;
+    }
+    l = getLibrary(node->value);
+    if (l == NULL) {
+        ALOGW("addSubEffect() could not get library %s", node->value);
+        return -EINVAL;
+    }
+    node = config_find(root, UUID_TAG);
+    if (node == NULL) {
+        return -EINVAL;
+    }
+    if (stringToUuid(node->value, &uuid) != 0) {
+        ALOGW("addSubEffect() invalid uuid %s", node->value);
+        return -EINVAL;
+    }
+    d = malloc(sizeof(effect_descriptor_t));
+    if (l->desc->get_descriptor(&uuid, d) != 0) {
+        char s[40];
+        uuidToString(&uuid, s, 40);
+        ALOGW("Error querying effect %s on lib %s", s, l->name);
+        free(d);
+        return -EINVAL;
+    }
+#if (LOG_NDEBUG==0)
+    char s[512];
+    dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
+    ALOGV("addSubEffect() read descriptor %p:%s",d, s);
+#endif
+    if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
+            EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
+        ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
+        free(d);
+        return -EINVAL;
+    }
+    sub_effect_entry_t *sub_effect = malloc(sizeof(sub_effect_entry_t));
+    sub_effect->object = d;
+    // lib_entry_t is stored since the sub effects are not linked to the library
+    sub_effect->lib = l;
+    e = malloc(sizeof(list_elem_t));
+    e->object = sub_effect;
+    e->next = gSubEffectList->sub_elem;
+    gSubEffectList->sub_elem = e;
+    ALOGV("addSubEffect end");
+    return 0;
+}
+
+int loadEffects(cnode *root)
+{
+    cnode *node;
+
+    node = config_find(root, EFFECTS_TAG);
+    if (node == NULL) {
+        return -ENOENT;
+    }
+    node = node->first_child;
+    while (node) {
+        loadEffect(node);
+        node = node->next;
+    }
+    return 0;
+}
+
+int loadEffect(cnode *root)
+{
+    cnode *node;
+    effect_uuid_t uuid;
+    lib_entry_t *l;
+    effect_descriptor_t *d;
+    list_elem_t *e;
+
+    node = config_find(root, LIBRARY_TAG);
+    if (node == NULL) {
+        return -EINVAL;
+    }
+
+    l = getLibrary(node->value);
+    if (l == NULL) {
+        ALOGW("loadEffect() could not get library %s", node->value);
+        return -EINVAL;
+    }
+
+    node = config_find(root, UUID_TAG);
+    if (node == NULL) {
+        return -EINVAL;
+    }
+    if (stringToUuid(node->value, &uuid) != 0) {
+        ALOGW("loadEffect() invalid uuid %s", node->value);
+        return -EINVAL;
+    }
+    lib_entry_t *tmp;
+    bool skip = false;
+    if (findEffect(NULL, &uuid, &tmp, NULL) == 0) {
+        ALOGW("skipping duplicate uuid %s %s", node->value,
+                node->next ? "and its sub-effects" : "");
+        skip = true;
+    }
+
+    d = malloc(sizeof(effect_descriptor_t));
+    if (l->desc->get_descriptor(&uuid, d) != 0) {
+        char s[40];
+        uuidToString(&uuid, s, 40);
+        ALOGW("Error querying effect %s on lib %s", s, l->name);
+        free(d);
+        return -EINVAL;
+    }
+#if (LOG_NDEBUG==0)
+    char s[512];
+    dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
+    ALOGV("loadEffect() read descriptor %p:%s",d, s);
+#endif
+    if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
+            EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
+        ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
+        free(d);
+        return -EINVAL;
+    }
+    e = malloc(sizeof(list_elem_t));
+    e->object = d;
+    if (skip) {
+        e->next = gSkippedEffects;
+        gSkippedEffects = e;
+        return -EINVAL;
+    } else {
+        e->next = l->effects;
+        l->effects = e;
+    }
+
+    // After the UUID node in the config_tree, if node->next is valid,
+    // that would be sub effect node.
+    // Find the sub effects and add them to the gSubEffectList
+    node = node->next;
+    int count = 2;
+    bool hwSubefx = false, swSubefx = false;
+    list_sub_elem_t *sube = NULL;
+    if (node != NULL) {
+        ALOGV("Adding the effect to gEffectSubList as there are sub effects");
+        sube = malloc(sizeof(list_sub_elem_t));
+        sube->object = d;
+        sube->sub_elem = NULL;
+        sube->next = gSubEffectList;
+        gSubEffectList = sube;
+    }
+    while (node != NULL && count) {
+       if (addSubEffect(node)) {
+           ALOGW("loadEffect() could not add subEffect %s", node->value);
+           // Change the gSubEffectList to point to older list;
+           gSubEffectList = sube->next;
+           free(sube->sub_elem);// Free an already added sub effect
+           sube->sub_elem = NULL;
+           free(sube);
+           return -ENOENT;
+       }
+       sub_effect_entry_t *subEntry = (sub_effect_entry_t*)gSubEffectList->sub_elem->object;
+       effect_descriptor_t *subEffectDesc = (effect_descriptor_t*)(subEntry->object);
+       // Since we return a dummy descriptor for the proxy during
+       // get_descriptor call,we replace it with the correspoding
+       // sw effect descriptor, but with Proxy UUID
+       // check for Sw desc
+        if (!((subEffectDesc->flags & EFFECT_FLAG_HW_ACC_MASK) ==
+                                           EFFECT_FLAG_HW_ACC_TUNNEL)) {
+             swSubefx = true;
+             *d = *subEffectDesc;
+             d->uuid = uuid;
+             ALOGV("loadEffect() Changed the Proxy desc");
+       } else
+           hwSubefx = true;
+       count--;
+       node = node->next;
+    }
+    // 1 HW and 1 SW sub effect found. Set the offload flag in the Proxy desc
+    if (hwSubefx && swSubefx) {
+        d->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
+    }
+    return 0;
+}
+
+lib_entry_t *getLibrary(const char *name)
+{
+    list_elem_t *e;
+
+    if (gCachedLibrary &&
+            !strncmp(gCachedLibrary->name, name, PATH_MAX)) {
+        return gCachedLibrary;
+    }
+
+    e = gLibraryList;
+    while (e) {
+        lib_entry_t *l = (lib_entry_t *)e->object;
+        if (!strcmp(l->name, name)) {
+            gCachedLibrary = l;
+            return l;
+        }
+        e = e->next;
+    }
+
+    return NULL;
+}
diff --git a/media/libeffects/factory/EffectsConfigLoader.h b/media/libeffects/factory/EffectsConfigLoader.h
new file mode 100644
index 0000000..3f82609
--- /dev/null
+++ b/media/libeffects/factory/EffectsConfigLoader.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECTSCONFIGLOADER_H
+#define ANDROID_EFFECTSCONFIGLOADER_H
+
+#include <cutils/compiler.h>
+#include "EffectsFactoryState.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+
+/** Parses the platform effect configuration
+ * and stores its content in the global EffectFactoryState. */
+ANDROID_API
+int EffectLoadEffectConfig();
+
+
+#ifdef  __cplusplus
+} // extern "C"
+#endif
+
+#endif  // ANDROID_EFFECTSCONFIGLOADER_H
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index 37c0bb7..cd0e765 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -17,65 +17,46 @@
 #define LOG_TAG "EffectsFactory"
 //#define LOG_NDEBUG 0
 
-#include "EffectsFactory.h"
-
-#include <dlfcn.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#include <cutils/config_utils.h>
-#include <cutils/misc.h>
 #include <cutils/properties.h>
 #include <log/log.h>
 
-#include <system/audio_effects/audio_effects_conf.h>
+#include <media/EffectsFactoryApi.h>
+
+#include "EffectsConfigLoader.h"
+#include "EffectsFactoryState.h"
+#include "EffectsXmlConfigLoader.h"
+
+#include "EffectsFactory.h"
 
 static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
-static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
-static list_elem_t *gSkippedEffects; // list of effects skipped because of duplicate uuid
-// list of effect_descriptor and list of sub effects : all currently loaded
-// It does not contain effects without sub effects.
-static list_sub_elem_t *gSubEffectList;
-static pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER; // controls access to gLibraryList
 static uint32_t gNumEffects;         // total number number of effects
 static list_elem_t *gCurLib;    // current library in enumeration process
 static list_elem_t *gCurEffect; // current effect in enumeration process
 static uint32_t gCurEffectIdx;       // current effect index in enumeration process
-static lib_entry_t *gCachedLibrary;  // last library accessed by getLibrary()
+/** Number of elements skipped during the effects configuration loading.
+ *  -1 if the config loader failed
+ *  -2 if config load was skipped
+ */
+static ssize_t gConfigNbElemSkipped = -2;
 
 static int gInitDone; // true is global initialization has been preformed
 static int gCanQueryEffect; // indicates that call to EffectQueryEffect() is valid, i.e. that the list of effects
                           // was not modified since last call to EffectQueryNumberEffects()
-
-static list_elem_t *gLibraryFailedList;  //list of lib_failed_entry_t: libraries failed to load
-
 /////////////////////////////////////////////////
 //      Local functions prototypes
 /////////////////////////////////////////////////
 
 static int init();
-static int loadEffectConfigFile(const char *path);
-static int loadLibraries(cnode *root);
-static int loadLibrary(cnode *root, const char *name);
-static int loadEffects(cnode *root);
-static int loadEffect(cnode *node);
-// To get and add the effect pointed by the passed node to the gSubEffectList
-static int addSubEffect(cnode *root);
-static lib_entry_t *getLibrary(const char *path);
 static void resetEffectEnumeration();
 static uint32_t updateNumEffects();
-static int findEffect(const effect_uuid_t *type,
-               const effect_uuid_t *uuid,
-               lib_entry_t **lib,
-               effect_descriptor_t **desc);
 // To search a subeffect in the gSubEffectList
 static int findSubEffect(const effect_uuid_t *uuid,
                lib_entry_t **lib,
                effect_descriptor_t **desc);
-static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len, int indent);
-static int stringToUuid(const char *str, effect_uuid_t *uuid);
-static int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen);
 
 /////////////////////////////////////////////////
 //      Effect Control Interface functions
@@ -461,10 +442,12 @@
     if (ignoreFxConfFiles) {
         ALOGI("Audio effects in configuration files will be ignored");
     } else {
-        if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
-            loadEffectConfigFile(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
-        } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
-            loadEffectConfigFile(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+        gConfigNbElemSkipped = EffectLoadXmlEffectConfig(NULL);
+        if (gConfigNbElemSkipped < 0) {
+            ALOGW("Failed to load XML effect configuration, fallback to .conf");
+            EffectLoadEffectConfig();
+        } else if (gConfigNbElemSkipped > 0) {
+            ALOGE("Effect config is partially invalid, skipped %zd elements", gConfigNbElemSkipped);
         }
     }
 
@@ -474,367 +457,6 @@
     return 0;
 }
 
-int loadEffectConfigFile(const char *path)
-{
-    cnode *root;
-    char *data;
-
-    data = load_file(path, NULL);
-    if (data == NULL) {
-        return -ENODEV;
-    }
-    root = config_node("", "");
-    config_load(root, data);
-    loadLibraries(root);
-    loadEffects(root);
-    config_free(root);
-    free(root);
-    free(data);
-
-    return 0;
-}
-
-int loadLibraries(cnode *root)
-{
-    cnode *node;
-
-    node = config_find(root, LIBRARIES_TAG);
-    if (node == NULL) {
-        return -ENOENT;
-    }
-    node = node->first_child;
-    while (node) {
-        loadLibrary(node, node->name);
-        node = node->next;
-    }
-    return 0;
-}
-
-#ifdef __LP64__
-// audio_effects.conf always specifies 32 bit lib path: convert to 64 bit path if needed
-static const char *kLibraryPathRoot[] =
-        {"/odm/lib64/soundfx", "/vendor/lib64/soundfx", "/system/lib64/soundfx"};
-#else
-static const char *kLibraryPathRoot[] =
-        {"/odm/lib/soundfx", "/vendor/lib/soundfx", "/system/lib/soundfx"};
-#endif
-
-static const int kLibraryPathRootSize =
-        (sizeof(kLibraryPathRoot) / sizeof(kLibraryPathRoot[0]));
-
-// Checks if the library path passed as lib_path_in can be opened and if not
-// tries in standard effect library directories with just the library name and returns correct path
-// in lib_path_out
-int checkLibraryPath(const char *lib_path_in, char *lib_path_out) {
-    char *str;
-    const char *lib_name;
-    size_t len;
-
-    if (lib_path_in == NULL || lib_path_out == NULL) {
-        return -EINVAL;
-    }
-
-    strlcpy(lib_path_out, lib_path_in, PATH_MAX);
-
-    // Try exact path first
-    str = strstr(lib_path_out, "/lib/soundfx/");
-    if (str == NULL) {
-        return -EINVAL;
-    }
-
-    // Extract library name from input path
-    len = str - lib_path_out;
-    lib_name = lib_path_in + len + strlen("/lib/soundfx/");
-
-    // Then try with library name and standard path names in order of preference
-    for (int i = 0; i < kLibraryPathRootSize; i++) {
-        char path[PATH_MAX];
-
-        snprintf(path,
-                 PATH_MAX,
-                 "%s/%s",
-                 kLibraryPathRoot[i],
-                 lib_name);
-        if (F_OK == access(path, 0)) {
-            strcpy(lib_path_out, path);
-            ALOGW_IF(strncmp(lib_path_out, lib_path_in, PATH_MAX) != 0,
-                "checkLibraryPath() corrected library path %s to %s", lib_path_in, lib_path_out);
-            return 0;
-        }
-    }
-    return -EINVAL;
-}
-
-
-
-int loadLibrary(cnode *root, const char *name)
-{
-    cnode *node;
-    void *hdl = NULL;
-    audio_effect_library_t *desc;
-    list_elem_t *e;
-    lib_entry_t *l;
-    char path[PATH_MAX];
-
-    node = config_find(root, PATH_TAG);
-    if (node == NULL) {
-        return -EINVAL;
-    }
-
-    if (checkLibraryPath((const char *)node->value, path) != 0) {
-        ALOGW("loadLibrary() could not find library %s", path);
-        goto error;
-    }
-
-    hdl = dlopen(path, RTLD_NOW);
-    if (hdl == NULL) {
-        ALOGW("loadLibrary() failed to open %s", path);
-        goto error;
-    }
-
-    desc = (audio_effect_library_t *)dlsym(hdl, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
-    if (desc == NULL) {
-        ALOGW("loadLibrary() could not find symbol %s", AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
-        goto error;
-    }
-
-    if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) {
-        ALOGW("getLibrary() bad tag %08x in lib info struct", desc->tag);
-        goto error;
-    }
-
-    if (EFFECT_API_VERSION_MAJOR(desc->version) !=
-            EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) {
-        ALOGW("loadLibrary() bad lib version %08x", desc->version);
-        goto error;
-    }
-
-    // add entry for library in gLibraryList
-    l = malloc(sizeof(lib_entry_t));
-    l->name = strndup(name, PATH_MAX);
-    l->path = strndup(path, PATH_MAX);
-    l->handle = hdl;
-    l->desc = desc;
-    l->effects = NULL;
-    pthread_mutex_init(&l->lock, NULL);
-
-    e = malloc(sizeof(list_elem_t));
-    e->object = l;
-    pthread_mutex_lock(&gLibLock);
-    e->next = gLibraryList;
-    gLibraryList = e;
-    pthread_mutex_unlock(&gLibLock);
-    ALOGV("getLibrary() linked library %p for path %s", l, path);
-
-    return 0;
-
-error:
-    if (hdl != NULL) {
-        dlclose(hdl);
-    }
-    //add entry for library errors in gLibraryFailedList
-    lib_failed_entry_t *fl = malloc(sizeof(lib_failed_entry_t));
-    fl->name = strndup(name, PATH_MAX);
-    fl->path = strndup(path, PATH_MAX);
-
-    list_elem_t *fe = malloc(sizeof(list_elem_t));
-    fe->object = fl;
-    fe->next = gLibraryFailedList;
-    gLibraryFailedList = fe;
-    ALOGV("getLibrary() linked error in library %p for path %s", fl, path);
-
-    return -EINVAL;
-}
-
-// This will find the library and UUID tags of the sub effect pointed by the
-// node, gets the effect descriptor and lib_entry_t and adds the subeffect -
-// sub_entry_t to the gSubEffectList
-int addSubEffect(cnode *root)
-{
-    ALOGV("addSubEffect");
-    cnode *node;
-    effect_uuid_t uuid;
-    effect_descriptor_t *d;
-    lib_entry_t *l;
-    list_elem_t *e;
-    node = config_find(root, LIBRARY_TAG);
-    if (node == NULL) {
-        return -EINVAL;
-    }
-    l = getLibrary(node->value);
-    if (l == NULL) {
-        ALOGW("addSubEffect() could not get library %s", node->value);
-        return -EINVAL;
-    }
-    node = config_find(root, UUID_TAG);
-    if (node == NULL) {
-        return -EINVAL;
-    }
-    if (stringToUuid(node->value, &uuid) != 0) {
-        ALOGW("addSubEffect() invalid uuid %s", node->value);
-        return -EINVAL;
-    }
-    d = malloc(sizeof(effect_descriptor_t));
-    if (l->desc->get_descriptor(&uuid, d) != 0) {
-        char s[40];
-        uuidToString(&uuid, s, 40);
-        ALOGW("Error querying effect %s on lib %s", s, l->name);
-        free(d);
-        return -EINVAL;
-    }
-#if (LOG_NDEBUG==0)
-    char s[512];
-    dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
-    ALOGV("addSubEffect() read descriptor %p:%s",d, s);
-#endif
-    if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
-            EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
-        ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
-        free(d);
-        return -EINVAL;
-    }
-    sub_effect_entry_t *sub_effect = malloc(sizeof(sub_effect_entry_t));
-    sub_effect->object = d;
-    // lib_entry_t is stored since the sub effects are not linked to the library
-    sub_effect->lib = l;
-    e = malloc(sizeof(list_elem_t));
-    e->object = sub_effect;
-    e->next = gSubEffectList->sub_elem;
-    gSubEffectList->sub_elem = e;
-    ALOGV("addSubEffect end");
-    return 0;
-}
-
-int loadEffects(cnode *root)
-{
-    cnode *node;
-
-    node = config_find(root, EFFECTS_TAG);
-    if (node == NULL) {
-        return -ENOENT;
-    }
-    node = node->first_child;
-    while (node) {
-        loadEffect(node);
-        node = node->next;
-    }
-    return 0;
-}
-
-int loadEffect(cnode *root)
-{
-    cnode *node;
-    effect_uuid_t uuid;
-    lib_entry_t *l;
-    effect_descriptor_t *d;
-    list_elem_t *e;
-
-    node = config_find(root, LIBRARY_TAG);
-    if (node == NULL) {
-        return -EINVAL;
-    }
-
-    l = getLibrary(node->value);
-    if (l == NULL) {
-        ALOGW("loadEffect() could not get library %s", node->value);
-        return -EINVAL;
-    }
-
-    node = config_find(root, UUID_TAG);
-    if (node == NULL) {
-        return -EINVAL;
-    }
-    if (stringToUuid(node->value, &uuid) != 0) {
-        ALOGW("loadEffect() invalid uuid %s", node->value);
-        return -EINVAL;
-    }
-    lib_entry_t *tmp;
-    bool skip = false;
-    if (findEffect(NULL, &uuid, &tmp, NULL) == 0) {
-        ALOGW("skipping duplicate uuid %s %s", node->value,
-                node->next ? "and its sub-effects" : "");
-        skip = true;
-    }
-
-    d = malloc(sizeof(effect_descriptor_t));
-    if (l->desc->get_descriptor(&uuid, d) != 0) {
-        char s[40];
-        uuidToString(&uuid, s, 40);
-        ALOGW("Error querying effect %s on lib %s", s, l->name);
-        free(d);
-        return -EINVAL;
-    }
-#if (LOG_NDEBUG==0)
-    char s[512];
-    dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
-    ALOGV("loadEffect() read descriptor %p:%s",d, s);
-#endif
-    if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
-            EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
-        ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
-        free(d);
-        return -EINVAL;
-    }
-    e = malloc(sizeof(list_elem_t));
-    e->object = d;
-    if (skip) {
-        e->next = gSkippedEffects;
-        gSkippedEffects = e;
-        return -EINVAL;
-    } else {
-        e->next = l->effects;
-        l->effects = e;
-    }
-
-    // After the UUID node in the config_tree, if node->next is valid,
-    // that would be sub effect node.
-    // Find the sub effects and add them to the gSubEffectList
-    node = node->next;
-    int count = 2;
-    bool hwSubefx = false, swSubefx = false;
-    list_sub_elem_t *sube = NULL;
-    if (node != NULL) {
-        ALOGV("Adding the effect to gEffectSubList as there are sub effects");
-        sube = malloc(sizeof(list_sub_elem_t));
-        sube->object = d;
-        sube->sub_elem = NULL;
-        sube->next = gSubEffectList;
-        gSubEffectList = sube;
-    }
-    while (node != NULL && count) {
-       if (addSubEffect(node)) {
-           ALOGW("loadEffect() could not add subEffect %s", node->value);
-           // Change the gSubEffectList to point to older list;
-           gSubEffectList = sube->next;
-           free(sube->sub_elem);// Free an already added sub effect
-           sube->sub_elem = NULL;
-           free(sube);
-           return -ENOENT;
-       }
-       sub_effect_entry_t *subEntry = (sub_effect_entry_t*)gSubEffectList->sub_elem->object;
-       effect_descriptor_t *subEffectDesc = (effect_descriptor_t*)(subEntry->object);
-       // Since we return a dummy descriptor for the proxy during
-       // get_descriptor call,we replace it with the correspoding
-       // sw effect descriptor, but with Proxy UUID
-       // check for Sw desc
-        if (!((subEffectDesc->flags & EFFECT_FLAG_HW_ACC_MASK) ==
-                                           EFFECT_FLAG_HW_ACC_TUNNEL)) {
-             swSubefx = true;
-             *d = *subEffectDesc;
-             d->uuid = uuid;
-             ALOGV("loadEffect() Changed the Proxy desc");
-       } else
-           hwSubefx = true;
-       count--;
-       node = node->next;
-    }
-    // 1 HW and 1 SW sub effect found. Set the offload flag in the Proxy desc
-    if (hwSubefx && swSubefx) {
-        d->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
-    }
-    return 0;
-}
-
 // Searches the sub effect matching to the specified uuid
 // in the gSubEffectList. It gets the lib_entry_t for
 // the matched sub_effect . Used in EffectCreate of sub effects
@@ -881,29 +503,6 @@
     return ret;
 }
 
-lib_entry_t *getLibrary(const char *name)
-{
-    list_elem_t *e;
-
-    if (gCachedLibrary &&
-            !strncmp(gCachedLibrary->name, name, PATH_MAX)) {
-        return gCachedLibrary;
-    }
-
-    e = gLibraryList;
-    while (e) {
-        lib_entry_t *l = (lib_entry_t *)e->object;
-        if (!strcmp(l->name, name)) {
-            gCachedLibrary = l;
-            return l;
-        }
-        e = e->next;
-    }
-
-    return NULL;
-}
-
-
 void resetEffectEnumeration()
 {
     gCurLib = gLibraryList;
@@ -935,114 +534,6 @@
     return cnt;
 }
 
-int findEffect(const effect_uuid_t *type,
-               const effect_uuid_t *uuid,
-               lib_entry_t **lib,
-               effect_descriptor_t **desc)
-{
-    list_elem_t *e = gLibraryList;
-    lib_entry_t *l = NULL;
-    effect_descriptor_t *d = NULL;
-    int found = 0;
-    int ret = 0;
-
-    while (e && !found) {
-        l = (lib_entry_t *)e->object;
-        list_elem_t *efx = l->effects;
-        while (efx) {
-            d = (effect_descriptor_t *)efx->object;
-            if (type != NULL && memcmp(&d->type, type, sizeof(effect_uuid_t)) == 0) {
-                found = 1;
-                break;
-            }
-            if (uuid != NULL && memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
-                found = 1;
-                break;
-            }
-            efx = efx->next;
-        }
-        e = e->next;
-    }
-    if (!found) {
-        ALOGV("findEffect() effect not found");
-        ret = -ENOENT;
-    } else {
-        ALOGV("findEffect() found effect: %s in lib %s", d->name, l->name);
-        *lib = l;
-        if (desc) {
-            *desc = d;
-        }
-    }
-
-    return ret;
-}
-
-void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len, int indent) {
-    char s[256];
-    char ss[256];
-    char idt[indent + 1];
-
-    memset(idt, ' ', indent);
-    idt[indent] = 0;
-
-    str[0] = 0;
-
-    snprintf(s, sizeof(s), "%s%s / %s\n", idt, desc->name, desc->implementor);
-    strlcat(str, s, len);
-
-    uuidToString(&desc->uuid, s, sizeof(s));
-    snprintf(ss, sizeof(ss), "%s  UUID: %s\n", idt, s);
-    strlcat(str, ss, len);
-
-    uuidToString(&desc->type, s, sizeof(s));
-    snprintf(ss, sizeof(ss), "%s  TYPE: %s\n", idt, s);
-    strlcat(str, ss, len);
-
-    sprintf(s, "%s  apiVersion: %08X\n%s  flags: %08X\n", idt,
-            desc->apiVersion, idt, desc->flags);
-    strlcat(str, s, len);
-}
-
-int stringToUuid(const char *str, effect_uuid_t *uuid)
-{
-    int tmp[10];
-
-    if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
-            tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
-        return -EINVAL;
-    }
-    uuid->timeLow = (uint32_t)tmp[0];
-    uuid->timeMid = (uint16_t)tmp[1];
-    uuid->timeHiAndVersion = (uint16_t)tmp[2];
-    uuid->clockSeq = (uint16_t)tmp[3];
-    uuid->node[0] = (uint8_t)tmp[4];
-    uuid->node[1] = (uint8_t)tmp[5];
-    uuid->node[2] = (uint8_t)tmp[6];
-    uuid->node[3] = (uint8_t)tmp[7];
-    uuid->node[4] = (uint8_t)tmp[8];
-    uuid->node[5] = (uint8_t)tmp[9];
-
-    return 0;
-}
-
-int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen)
-{
-
-    snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
-            uuid->timeLow,
-            uuid->timeMid,
-            uuid->timeHiAndVersion,
-            uuid->clockSeq,
-            uuid->node[0],
-            uuid->node[1],
-            uuid->node[2],
-            uuid->node[3],
-            uuid->node[4],
-            uuid->node[5]);
-
-    return 0;
-}
-
 int EffectDumpEffects(int fd) {
     char s[512];
 
@@ -1092,6 +583,20 @@
             e = e->next;
         }
     }
+    switch (gConfigNbElemSkipped) {
+    case -2:
+        dprintf(fd, "Effect configuration loading skipped.\n");
+        break;
+    case -1:
+        dprintf(fd, "XML effect configuration failed to load.\n");
+        break;
+    case 0:
+        dprintf(fd, "XML effect configuration loaded successfully.\n");
+        break;
+    default:
+        dprintf(fd, "XML effect configuration partially loaded, skipped %zd elements.\n",
+                gConfigNbElemSkipped);
+    }
     return ret;
 }
 
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
index 72e0931..29dbc9c 100644
--- a/media/libeffects/factory/EffectsFactory.h
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -20,7 +20,7 @@
 #include <dirent.h>
 #include <pthread.h>
 
-#include <android/log.h>
+#include <cutils/compiler.h>
 #include <hardware/audio_effect.h>
 
 #if __cplusplus
@@ -96,6 +96,7 @@
 //        *pDescriptor:     updated with the sub effect descriptors.
 //
 ////////////////////////////////////////////////////////////////////////////////
+ANDROID_API
 int EffectGetSubEffects(const effect_uuid_t *pEffectUuid,
                         sub_effect_entry_t **pSube,
                         size_t size);
diff --git a/media/libeffects/factory/EffectsFactoryState.c b/media/libeffects/factory/EffectsFactoryState.c
new file mode 100644
index 0000000..b364004
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactoryState.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsFactoryState"
+
+#include "EffectsFactoryState.h"
+
+#include "log/log.h"
+
+list_elem_t *gLibraryList;
+list_elem_t *gSkippedEffects;
+list_sub_elem_t *gSubEffectList;
+pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER;
+
+list_elem_t *gLibraryFailedList;  //list of lib_failed_entry_t: libraries failed to load
+
+
+int findEffect(const effect_uuid_t *type,
+               const effect_uuid_t *uuid,
+               lib_entry_t **lib,
+               effect_descriptor_t **desc)
+{
+    list_elem_t *e = gLibraryList;
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+    int found = 0;
+    int ret = 0;
+
+    while (e && !found) {
+        l = (lib_entry_t *)e->object;
+        list_elem_t *efx = l->effects;
+        while (efx) {
+            d = (effect_descriptor_t *)efx->object;
+            if (type != NULL && memcmp(&d->type, type, sizeof(effect_uuid_t)) == 0) {
+                found = 1;
+                break;
+            }
+            if (uuid != NULL && memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
+                found = 1;
+                break;
+            }
+            efx = efx->next;
+        }
+        e = e->next;
+    }
+    if (!found) {
+        ALOGV("findEffect() effect not found");
+        ret = -ENOENT;
+    } else {
+        ALOGV("findEffect() found effect: %s in lib %s", d->name, l->name);
+        *lib = l;
+        if (desc) {
+            *desc = d;
+        }
+    }
+
+    return ret;
+}
+
+int stringToUuid(const char *str, effect_uuid_t *uuid)
+{
+    int tmp[10];
+
+    if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+            tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
+        return -EINVAL;
+    }
+    uuid->timeLow = (uint32_t)tmp[0];
+    uuid->timeMid = (uint16_t)tmp[1];
+    uuid->timeHiAndVersion = (uint16_t)tmp[2];
+    uuid->clockSeq = (uint16_t)tmp[3];
+    uuid->node[0] = (uint8_t)tmp[4];
+    uuid->node[1] = (uint8_t)tmp[5];
+    uuid->node[2] = (uint8_t)tmp[6];
+    uuid->node[3] = (uint8_t)tmp[7];
+    uuid->node[4] = (uint8_t)tmp[8];
+    uuid->node[5] = (uint8_t)tmp[9];
+
+    return 0;
+}
+
+int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen)
+{
+
+    snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+            uuid->timeLow,
+            uuid->timeMid,
+            uuid->timeHiAndVersion,
+            uuid->clockSeq,
+            uuid->node[0],
+            uuid->node[1],
+            uuid->node[2],
+            uuid->node[3],
+            uuid->node[4],
+            uuid->node[5]);
+
+    return 0;
+}
+
+
+void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len, int indent) {
+    char s[256];
+    char ss[256];
+    char idt[indent + 1];
+
+    memset(idt, ' ', indent);
+    idt[indent] = 0;
+
+    str[0] = 0;
+
+    snprintf(s, sizeof(s), "%s%s / %s\n", idt, desc->name, desc->implementor);
+    strlcat(str, s, len);
+
+    uuidToString(&desc->uuid, s, sizeof(s));
+    snprintf(ss, sizeof(ss), "%s  UUID: %s\n", idt, s);
+    strlcat(str, ss, len);
+
+    uuidToString(&desc->type, s, sizeof(s));
+    snprintf(ss, sizeof(ss), "%s  TYPE: %s\n", idt, s);
+    strlcat(str, ss, len);
+
+    sprintf(s, "%s  apiVersion: %08X\n%s  flags: %08X\n", idt,
+            desc->apiVersion, idt, desc->flags);
+    strlcat(str, s, len);
+}
diff --git a/media/libeffects/factory/EffectsFactoryState.h b/media/libeffects/factory/EffectsFactoryState.h
new file mode 100644
index 0000000..aef945e
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactoryState.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECTSFACTORYSTATE_H_
+#define ANDROID_EFFECTSFACTORYSTATE_H_
+
+#include "EffectsFactory.h"
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/** @file Contains the state shared with configuration loader of the Effect factory.
+ *        This global state should probably be refactor in a structure
+ *        provided by the config loader on EffectsFactory init.
+ *        This header also contains some helper functions to work on the state.
+ */
+
+extern list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
+// list of effects skipped because of duplicate uuid or invalid version
+extern list_elem_t *gSkippedEffects;
+// list of effect_descriptor and list of sub effects : all currently loaded
+// It does not contain effects without sub effects.
+extern list_sub_elem_t *gSubEffectList;
+extern pthread_mutex_t gLibLock; // controls access to gLibraryList
+
+extern list_elem_t *gLibraryFailedList;  //list of lib_failed_entry_t: libraries failed to load
+
+
+
+int findEffect(const effect_uuid_t *type,
+               const effect_uuid_t *uuid,
+               lib_entry_t **lib,
+               effect_descriptor_t **desc);
+
+int stringToUuid(const char *str, effect_uuid_t *uuid);
+/** Used to log UUIDs */
+int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen);
+
+/** Used for debuging. */
+void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len, int indent);
+
+#if __cplusplus
+} // extern "C"
+#endif
+
+#endif // ANDROID_EFFECTSFACTORYSTATE_H_
diff --git a/media/libeffects/factory/EffectsXmlConfigLoader.cpp b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
new file mode 100644
index 0000000..438b787
--- /dev/null
+++ b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsFactoryConfigLoader"
+//#define LOG_NDEBUG 0
+
+#include <dlfcn.h>
+#include <set>
+#include <stdlib.h>
+#include <string>
+
+#include <log/log.h>
+
+#include <media/EffectsConfig.h>
+
+#include "EffectsConfigLoader.h"
+#include "EffectsFactoryState.h"
+#include "EffectsXmlConfigLoader.h"
+
+namespace android {
+
+using namespace effectsConfig;
+
+/////////////////////////////////////////////////
+//      Local functions
+/////////////////////////////////////////////////
+
+namespace {
+
+/** Similarly to dlopen, looks for the provided path in LD_EFFECT_LIBRARY_PATH.
+ * @return true if the library is found and set resolvedPath to its absolute path.
+ *         false if not found
+ */
+bool resolveLibrary(const std::string& path, std::string* resolvedPath) {
+    for (auto* libraryDirectory : LD_EFFECT_LIBRARY_PATH) {
+        std::string candidatePath = std::string(libraryDirectory) + '/' + path;
+        if (access(candidatePath.c_str(), R_OK) == 0) {
+            *resolvedPath = std::move(candidatePath);
+            return true;
+        }
+    }
+    return false;
+}
+
+/** Loads a library given its relative path and stores the result in libEntry.
+ * @return true on success with libEntry's path, handle and desc filled
+ *         false on success with libEntry's path filled with the path of the failed lib
+ * The caller MUST free the resources path (free) and handle (dlclose) if filled.
+ */
+bool loadLibrary(const char* relativePath, lib_entry_t* libEntry) noexcept {
+
+    std::string absolutePath;
+    if (!resolveLibrary(relativePath, &absolutePath)) {
+        ALOGE("Could not find library in effect directories: %s", relativePath);
+        libEntry->path = strdup(relativePath);
+        return false;
+    }
+    const char* path = absolutePath.c_str();
+    libEntry->path = strdup(path);
+
+    // Make sure the lib is closed on early return
+    std::unique_ptr<void, decltype(dlclose)*> libHandle(dlopen(path, RTLD_NOW),
+                                                       dlclose);
+    if (libHandle == nullptr) {
+        ALOGE("Could not dlopen library %s: %s", path, dlerror());
+        return false;
+    }
+
+    auto* description = static_cast<audio_effect_library_t*>(
+          dlsym(libHandle.get(), AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR));
+    if (description == nullptr) {
+        ALOGE("Invalid effect library, failed not find symbol '%s' in %s: %s",
+              AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR, path, dlerror());
+        return false;
+    }
+
+    if (description->tag != AUDIO_EFFECT_LIBRARY_TAG) {
+        ALOGE("Bad tag %#08x in description structure, expected %#08x for library %s",
+              description->tag, AUDIO_EFFECT_LIBRARY_TAG, path);
+        return false;
+    }
+
+    uint32_t majorVersion = EFFECT_API_VERSION_MAJOR(description->version);
+    uint32_t expectedMajorVersion = EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION);
+    if (majorVersion != expectedMajorVersion) {
+        ALOGE("Unsupported major version %#08x, expected %#08x for library %s",
+              majorVersion, expectedMajorVersion, path);
+        return false;
+    }
+
+    libEntry->handle = libHandle.release();
+    libEntry->desc = description;
+    return true;
+}
+
+/** Because the structures will be destroyed by c code, using new to allocate shared structure
+ * is not possible. Provide a equivalent of unique_ptr for malloc/freed structure to make sure
+ * they are not leaked in the c++ code.
+ @{ */
+struct FreeDeleter {
+    void operator()(void* p) {
+        free(p);
+    }
+};
+/** unique_ptr for object created with malloc. */
+template <class T>
+using UniqueCPtr = std::unique_ptr<T, FreeDeleter>;
+
+/** c version of std::make_unique. Uses malloc and free. */
+template <class T>
+UniqueCPtr<T> makeUniqueC() {
+    T* ptr = new (malloc(sizeof(T))) T{}; // Use placement new to initialize the structure
+    return UniqueCPtr<T>{ptr};
+}
+
+/** @} */
+
+/** Push an not owned element in a list_elem link list with an optional lock. */
+template <class T, class ListElem>
+void listPush(T* object, ListElem** list, pthread_mutex_t* mutex = nullptr) noexcept {
+    auto listElem = makeUniqueC<ListElem>();
+    listElem->object = object;
+    if (mutex != nullptr) {
+        pthread_mutex_lock(mutex);
+    }
+    listElem->next = *list;
+    *list = listElem.release();
+    if (mutex != nullptr) {
+        pthread_mutex_unlock(mutex);
+    }
+}
+
+/** Push an owned element in a list_elem link list with an optional lock. */
+template <class T, class ListElem>
+void listPush(UniqueCPtr<T>&& object, ListElem** list, pthread_mutex_t* mutex = nullptr) noexcept {
+    listPush(object.release(), list, mutex);
+}
+
+size_t loadLibraries(const effectsConfig::Libraries& libs,
+                     list_elem_t** libList, pthread_mutex_t* libListLock,
+                     list_elem_t** libFailedList)
+{
+    size_t nbSkippedElement = 0;
+    for (auto& library : libs) {
+
+        // Construct a lib entry
+        auto libEntry = makeUniqueC<lib_entry_t>();
+        libEntry->name = strdup(library.name.c_str());
+        libEntry->effects = nullptr;
+        pthread_mutex_init(&libEntry->lock, nullptr);
+
+        if (!loadLibrary(library.path.c_str(), libEntry.get())) {
+            // Register library load failure
+            listPush(std::move(libEntry), libFailedList);
+            ++nbSkippedElement;
+            continue;
+        }
+        listPush(std::move(libEntry), libList, libListLock);
+    }
+    return nbSkippedElement;
+}
+
+/** Find a library with the given name in the given list. */
+lib_entry_t* findLibrary(const char* name, list_elem_t* list) {
+
+    while (list != nullptr) {
+        auto* object = static_cast<lib_entry_t*>(list->object);
+        if (strcmp(object->name, name) == 0) {
+            return object;
+        }
+        list = list->next;
+    }
+    return nullptr;
+}
+
+struct UuidStr {
+    /** Length of an uuid represented as string. @TODO: use a constant instead of 40. */
+    char buff[40];
+};
+
+/** @return a string representing the provided uuid.
+ * By not providing an output buffer, it is implicitly created in the caller context.
+ * In such case the return pointer has the same lifetime as the expression containing uuidToString()
+ */
+char* uuidToString(const effect_uuid_t& uuid, UuidStr&& str = {}) {
+    uuidToString(&uuid, str.buff, sizeof(str.buff));
+    return str.buff;
+}
+
+struct LoadEffectResult {
+    /** true if the effect is usable (aka, existing lib, desc, right version, unique uuid) */
+    bool success = false;
+    /** Set if the effect lib was found*/
+    lib_entry_t* lib = nullptr;
+    //* Set if the description was successfuly retrieved from the lib */
+    UniqueCPtr<effect_descriptor_t> effectDesc;
+};
+
+LoadEffectResult loadEffect(const EffectImpl& effect, const std::string& name,
+                            list_elem_t* libList) {
+    LoadEffectResult result;
+
+    // Find the effect library
+    result.lib = findLibrary(effect.library->name.c_str(), libList);
+    if (result.lib == nullptr) {
+        ALOGE("Could not find library %s to load effect %s",
+              effect.library->name.c_str(), name.c_str());
+        return result;
+    }
+
+    result.effectDesc = makeUniqueC<effect_descriptor_t>();
+
+    // Get the effect descriptor
+    if (result.lib->desc->get_descriptor(&effect.uuid, result.effectDesc.get()) != 0) {
+        ALOGE("Error querying effect %s on lib %s",
+              uuidToString(effect.uuid), result.lib->name);
+        result.effectDesc.reset();
+        return result;
+    }
+
+    // Dump effect for debug
+#if (LOG_NDEBUG==0)
+    char s[512];
+    dumpEffectDescriptor(result.effectDesc.get(), s, sizeof(s), 0 /* indent */);
+    ALOGV("loadEffect() read descriptor %p:%s", result.effectDesc.get(), s);
+#endif
+
+    // Check effect is supported
+    uint32_t expectedMajorVersion = EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION);
+    if (EFFECT_API_VERSION_MAJOR(result.effectDesc->apiVersion) != expectedMajorVersion) {
+        ALOGE("Bad API version %#08x for effect %s in lib %s, expected major %#08x",
+              result.effectDesc->apiVersion, name.c_str(), result.lib->name, expectedMajorVersion);
+        return result;
+    }
+
+    lib_entry_t *_;
+    if (findEffect(nullptr, &effect.uuid, &_, nullptr) == 0) {
+        ALOGE("Effect %s uuid %s already exist", uuidToString(effect.uuid), name.c_str());
+        return result;
+    }
+
+    result.success = true;
+    return result;
+}
+
+size_t loadEffects(const Effects& effects, list_elem_t* libList, list_elem_t** skippedEffects,
+                   list_sub_elem_t** subEffectList) {
+    size_t nbSkippedElement = 0;
+
+    for (auto& effect : effects) {
+
+        auto effectLoadResult = loadEffect(effect, effect.name, libList);
+        if (!effectLoadResult.success) {
+            if (effectLoadResult.effectDesc != nullptr) {
+                listPush(std::move(effectLoadResult.effectDesc), skippedEffects);
+            }
+            ++nbSkippedElement;
+            continue;
+        }
+
+        if (effect.isProxy) {
+            auto swEffectLoadResult = loadEffect(effect.libSw, effect.name + " libsw", libList);
+            auto hwEffectLoadResult = loadEffect(effect.libHw, effect.name + " libhw", libList);
+            if (!swEffectLoadResult.success || !hwEffectLoadResult.success) {
+                // Push the main effect in the skipped list even if only a subeffect is invalid
+                // as the main effect is not usable without its subeffects.
+                listPush(std::move(effectLoadResult.effectDesc), skippedEffects);
+                ++nbSkippedElement;
+                continue;
+            }
+            listPush(effectLoadResult.effectDesc.get(), subEffectList);
+
+            // Since we return a dummy descriptor for the proxy during
+            // get_descriptor call, we replace it with the corresponding
+            // sw effect descriptor, but keep the Proxy UUID
+            *effectLoadResult.effectDesc = *swEffectLoadResult.effectDesc;
+            effectLoadResult.effectDesc->uuid = effect.uuid;
+
+            effectLoadResult.effectDesc->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
+
+            auto registerSubEffect = [subEffectList](auto&& result) {
+                auto entry = makeUniqueC<sub_effect_entry_t>();
+                entry->object = result.effectDesc.release();
+                // lib_entry_t is stored since the sub effects are not linked to the library
+                entry->lib = result.lib;
+                listPush(std::move(entry), &(*subEffectList)->sub_elem);
+            };
+            registerSubEffect(std::move(swEffectLoadResult));
+            registerSubEffect(std::move(hwEffectLoadResult));
+        }
+
+        listPush(std::move(effectLoadResult.effectDesc), &effectLoadResult.lib->effects);
+    }
+    return nbSkippedElement;
+}
+
+} // namespace
+
+/////////////////////////////////////////////////
+//      Interface function
+/////////////////////////////////////////////////
+
+extern "C" ssize_t EffectLoadXmlEffectConfig(const char* path)
+{
+    using effectsConfig::parse;
+    auto result = path ? parse(path) : parse();
+    if (result.parsedConfig == nullptr) {
+        ALOGE("Failed to parse XML configuration file");
+        return -1;
+    }
+    result.nbSkippedElement += loadLibraries(result.parsedConfig->libraries,
+                                             &gLibraryList, &gLibLock, &gLibraryFailedList) +
+                               loadEffects(result.parsedConfig->effects, gLibraryList,
+                                           &gSkippedEffects, &gSubEffectList);
+
+    ALOGE_IF(result.nbSkippedElement != 0, "%zu errors during loading of configuration: %s",
+             result.nbSkippedElement, path ?: effectsConfig::DEFAULT_PATH);
+
+    return result.nbSkippedElement;
+}
+
+} // namespace android
diff --git a/media/libeffects/factory/EffectsXmlConfigLoader.h b/media/libeffects/factory/EffectsXmlConfigLoader.h
new file mode 100644
index 0000000..a3fe9a3
--- /dev/null
+++ b/media/libeffects/factory/EffectsXmlConfigLoader.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECTSXMLCONFIGLOADER_H
+#define ANDROID_EFFECTSXMLCONFIGLOADER_H
+
+#include <unistd.h>
+
+#include <cutils/compiler.h>
+
+#include "EffectsFactoryState.h"
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/** Parses the platform effect xml configuration and stores its content in EffectFactoryState.
+ * @param[in] path of the configuration file or NULL to load the default one
+ * @return -1 on unrecoverable error (eg: no configuration file)
+ *         0 on success
+ *         the number of invalid elements (lib & effect) skipped if the config is partially invalid
+ * @note this function is exported for test purpose only. Do not call from outside this library.
+ */
+ANDROID_API
+ssize_t EffectLoadXmlEffectConfig(const char* path);
+
+#if __cplusplus
+} // extern "C"
+#endif
+
+#endif  // ANDROID_EFFECTSXMLCONFIGLOADER_H
diff --git a/media/libeffects/factory/include/media/EffectsFactoryApi.h b/media/libeffects/factory/include/media/EffectsFactoryApi.h
index 64a3212..a5a12eb 100644
--- a/media/libeffects/factory/include/media/EffectsFactoryApi.h
+++ b/media/libeffects/factory/include/media/EffectsFactoryApi.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_EFFECTSFACTORYAPI_H_
 #define ANDROID_EFFECTSFACTORYAPI_H_
 
+#include <cutils/compiler.h>
 #include <errno.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -52,6 +53,7 @@
 //        *pNumEffects:     updated with number of effects in factory
 //
 ////////////////////////////////////////////////////////////////////////////////
+ANDROID_API
 int EffectQueryNumberEffects(uint32_t *pNumEffects);
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -79,6 +81,7 @@
 //        *pDescriptor:     updated with the effect descriptor.
 //
 ////////////////////////////////////////////////////////////////////////////////
+ANDROID_API
 int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor);
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -110,6 +113,7 @@
 //        *pHandle:         updated with the effect handle.
 //
 ////////////////////////////////////////////////////////////////////////////////
+ANDROID_API
 int EffectCreate(const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t ioId,
         effect_handle_t *pHandle);
 
@@ -130,6 +134,7 @@
 //                          -EINVAL     invalid interface handle
 //
 ////////////////////////////////////////////////////////////////////////////////
+ANDROID_API
 int EffectRelease(effect_handle_t handle);
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -153,6 +158,7 @@
 //        *pDescriptor:     updated with the effect descriptor.
 //
 ////////////////////////////////////////////////////////////////////////////////
+ANDROID_API
 int EffectGetDescriptor(const effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptor);
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -169,8 +175,10 @@
 //                           1 if uuid is equal to EFFECT_UUID_NULL.
 //
 ////////////////////////////////////////////////////////////////////////////////
+ANDROID_API
 int EffectIsNullUuid(const effect_uuid_t *pEffectUuid);
 
+ANDROID_API
 int EffectDumpEffects(int fd);
 
 #if __cplusplus
diff --git a/media/libeffects/factory/test/DumpConfig.cpp b/media/libeffects/factory/test/DumpConfig.cpp
new file mode 100644
index 0000000..0a156b4
--- /dev/null
+++ b/media/libeffects/factory/test/DumpConfig.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/EffectsFactoryApi.h>
+#include <unistd.h>
+#include "EffectsXmlConfigLoader.h"
+#include "EffectsConfigLoader.h"
+
+int main(int argc, char* argv[]) {
+    const char* path = nullptr;
+    bool legacyFormat;
+
+    if (argc == 2 && strcmp(argv[1], "--legacy") == 0) {
+        legacyFormat = true;
+        fprintf(stderr, "Dumping legacy effect config file\n");
+    } else if ((argc == 2 || argc == 3) && strcmp(argv[1], "--xml") == 0) {
+        legacyFormat = false;
+        if (argc == 3) {
+            fprintf(stderr, "Dumping XML effect config file: %s\n", path);
+        } else {
+            fprintf(stderr, "Dumping default XML effect config file.\n");
+        }
+    } else {
+        fprintf(stderr, "Invalid arguments.\n"
+                        "Usage: %s [--legacy|--xml [FILE]]\n", argv[0]);
+        return 1;
+    }
+
+    if (!legacyFormat) {
+        ssize_t ret = EffectLoadXmlEffectConfig(path);
+        if (ret < 0) {
+            fprintf(stderr, "loadXmlEffectConfig failed, see logcat for detail.\n");
+            return 2;
+        }
+        if (ret > 0) {
+            fprintf(stderr, "Partially failed to load config. Skipped %zu elements, "
+                    "see logcat for detail.\n", (size_t)ret);
+        }
+    }
+
+    if (legacyFormat) {
+        auto ret = EffectLoadEffectConfig();
+        if (ret < 0) {
+            fprintf(stderr, "loadEffectConfig failed, see logcat for detail.\n");
+            return 3;
+        }
+        fprintf(stderr, "legacy loadEffectConfig has probably succeed, see logcat to make sure.\n");
+    }
+
+    if (EffectDumpEffects(STDOUT_FILENO) != 0) {
+        fprintf(stderr, "Effect dump failed, see logcat for detail.\n");
+        return 4;
+    }
+}
diff --git a/media/libeffects/lvm/lib/Android.mk b/media/libeffects/lvm/lib/Android.mk
index 83e8288..941eb3e 100644
--- a/media/libeffects/lvm/lib/Android.mk
+++ b/media/libeffects/lvm/lib/Android.mk
@@ -72,19 +72,25 @@
     Common/src/From2iToMono_16.c \
     Common/src/Copy_16.c \
     Common/src/MonoTo2I_16.c \
+    Common/src/MonoTo2I_32.c \
     Common/src/LoadConst_16.c \
+    Common/src/LoadConst_32.c \
     Common/src/dB_to_Lin32.c \
     Common/src/Shift_Sat_v16xv16.c \
+    Common/src/Shift_Sat_v32xv32.c \
     Common/src/Abs_32.c \
     Common/src/Int32RShiftToInt16_Sat_32x16.c \
     Common/src/From2iToMono_32.c \
     Common/src/mult3s_16x16.c \
+    Common/src/Mult3s_32x16.c \
     Common/src/NonLinComp_D16.c \
     Common/src/DelayMix_16x16.c \
     Common/src/MSTo2i_Sat_16x16.c \
     Common/src/From2iToMS_16x16.c \
     Common/src/Mac3s_Sat_16x16.c \
+    Common/src/Mac3s_Sat_32x16.c \
     Common/src/Add2_Sat_16x16.c \
+    Common/src/Add2_Sat_32x32.c \
     Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c \
     Common/src/LVC_MixSoft_1St_D16C31_SAT.c \
     Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c \
@@ -120,7 +126,7 @@
     $(LOCAL_PATH)/StereoWidening/src \
     $(LOCAL_PATH)/StereoWidening/lib
 
-LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -fvisibility=hidden -DBUILD_FLOAT -DHIGHER_FS
 LOCAL_CFLAGS += -Wall -Werror
 
 include $(BUILD_STATIC_LIBRARY)
@@ -179,6 +185,7 @@
     $(LOCAL_PATH)/Common/lib \
     $(LOCAL_PATH)/Common/src
 
-LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -fvisibility=hidden -DBUILD_FLOAT -DHIGHER_FS
 LOCAL_CFLAGS += -Wall -Werror
+
 include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
index 228977d..4c2b954 100644
--- a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
+++ b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
@@ -198,6 +198,10 @@
 #define LVDBE_CAP_FS_32000               64
 #define LVDBE_CAP_FS_44100               128
 #define LVDBE_CAP_FS_48000               256
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+#define LVDBE_CAP_FS_96000               512
+#define LVDBE_CAP_FS_192000              1024
+#endif
 
 typedef enum
 {
@@ -210,6 +214,10 @@
     LVDBE_FS_32000 = 6,
     LVDBE_FS_44100 = 7,
     LVDBE_FS_48000 = 8,
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+    LVDBE_FS_96000 = 9,
+    LVDBE_FS_192000 = 10,
+#endif
     LVDBE_FS_MAX   = LVM_MAXINT_32
 } LVDBE_Fs_en;
 
@@ -450,12 +458,17 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
-
+#ifdef BUILD_FLOAT
+LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t          hInstance,
+                                       const LVM_FLOAT      *pInData,
+                                       LVM_FLOAT            *pOutData,
+                                       LVM_UINT16           NumSamples);
+#else
 LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t          hInstance,
                                        const LVM_INT16      *pInData,
                                        LVM_INT16            *pOutData,
                                        LVM_UINT16           NumSamples);
-
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
index b1ebadf..f32ed30 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
@@ -19,6 +19,7 @@
 #define __LVDBE_COEFFS_H__
 
 
+#ifndef BUILD_FLOAT
 /************************************************************************************/
 /*                                                                                  */
 /* General                                                                          */
@@ -514,5 +515,632 @@
 #define MIX_TC_Fs44100                                  32097         /* Floating point value 0.979515 */
 #define MIX_TC_Fs48000                                  32150         /* Floating point value 0.981150 */
 
+#else /*BUILD_FLOAT*/
 
+/************************************************************************************/
+/*                                                                                  */
+/* General                                                                          */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVDBE_SCALESHIFT                                    10         /* As a power of 2 */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* High Pass Filter coefficients                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+ /* Coefficients for centre frequency 55Hz */
+#define HPF_Fs8000_Fc55_A0                        0.958849f
+#define HPF_Fs8000_Fc55_A1                        -1.917698f
+#define HPF_Fs8000_Fc55_A2                        0.958849f
+#define HPF_Fs8000_Fc55_B1                        -1.939001f
+#define HPF_Fs8000_Fc55_B2                        0.940807f
+#define HPF_Fs11025_Fc55_A0                       0.966909f
+#define HPF_Fs11025_Fc55_A1                       -1.933818f
+#define HPF_Fs11025_Fc55_A2                       0.966909f
+#define HPF_Fs11025_Fc55_B1                       -1.955732f
+#define HPF_Fs11025_Fc55_B2                       0.956690f
+#define HPF_Fs12000_Fc55_A0                       0.968650f
+#define HPF_Fs12000_Fc55_A1                       -1.937300f
+#define HPF_Fs12000_Fc55_A2                       0.968650f
+#define HPF_Fs12000_Fc55_B1                       -1.959327f
+#define HPF_Fs12000_Fc55_B2                       0.960138f
+#define HPF_Fs16000_Fc55_A0                       0.973588f
+#define HPF_Fs16000_Fc55_A1                       -1.947176f
+#define HPF_Fs16000_Fc55_A2                       0.973588f
+#define HPF_Fs16000_Fc55_B1                       -1.969494f
+#define HPF_Fs16000_Fc55_B2                       0.969952f
+#define HPF_Fs22050_Fc55_A0                       0.977671f
+#define HPF_Fs22050_Fc55_A1                       -1.955343f
+#define HPF_Fs22050_Fc55_A2                       0.977671f
+#define HPF_Fs22050_Fc55_B1                       -1.977863f
+#define HPF_Fs22050_Fc55_B2                       0.978105f
+#define HPF_Fs24000_Fc55_A0                       0.978551f
+#define HPF_Fs24000_Fc55_A1                       -1.957102f
+#define HPF_Fs24000_Fc55_A2                       0.978551f
+#define HPF_Fs24000_Fc55_B1                       -1.979662f
+#define HPF_Fs24000_Fc55_B2                       0.979866f
+#define HPF_Fs32000_Fc55_A0                       0.981042f
+#define HPF_Fs32000_Fc55_A1                       -1.962084f
+#define HPF_Fs32000_Fc55_A2                       0.981042f
+#define HPF_Fs32000_Fc55_B1                       -1.984746f
+#define HPF_Fs32000_Fc55_B2                       0.984861f
+#define HPF_Fs44100_Fc55_A0                       0.983097f
+#define HPF_Fs44100_Fc55_A1                       -1.966194f
+#define HPF_Fs44100_Fc55_A2                       0.983097f
+#define HPF_Fs44100_Fc55_B1                       -1.988931f
+#define HPF_Fs44100_Fc55_B2                       0.988992f
+#define HPF_Fs48000_Fc55_A0                       0.983539f
+#define HPF_Fs48000_Fc55_A1                       -1.967079f
+#define HPF_Fs48000_Fc55_A2                       0.983539f
+#define HPF_Fs48000_Fc55_B1                       -1.989831f
+#define HPF_Fs48000_Fc55_B2                       0.989882f
+
+#ifdef HIGHER_FS
+#define HPF_Fs96000_Fc55_A0                       0.986040f
+#define HPF_Fs96000_Fc55_A1                       -1.972080f
+#define HPF_Fs96000_Fc55_A2                       0.986040f
+#define HPF_Fs96000_Fc55_B1                       -1.994915f
+#define HPF_Fs96000_Fc55_B2                       0.994928f
+
+#define HPF_Fs192000_Fc55_A0                      0.987294f
+#define HPF_Fs192000_Fc55_A1                      -1.974588f
+#define HPF_Fs192000_Fc55_A2                      0.987294f
+#define HPF_Fs192000_Fc55_B1                      -1.997458f
+#define HPF_Fs192000_Fc55_B2                      0.997461f
 #endif
+
+
+ /* Coefficients for centre frequency 66Hz */
+#define HPF_Fs8000_Fc66_A0                        0.953016f
+#define HPF_Fs8000_Fc66_A1                        -1.906032f
+#define HPF_Fs8000_Fc66_A2                        0.953016f
+#define HPF_Fs8000_Fc66_B1                        -1.926810f
+#define HPF_Fs8000_Fc66_B2                        0.929396f
+#define HPF_Fs11025_Fc66_A0                       0.962638f
+#define HPF_Fs11025_Fc66_A1                       -1.925275f
+#define HPF_Fs11025_Fc66_A2                       0.962638f
+#define HPF_Fs11025_Fc66_B1                       -1.946881f
+#define HPF_Fs11025_Fc66_B2                       0.948256f
+#define HPF_Fs12000_Fc66_A0                       0.964718f
+#define HPF_Fs12000_Fc66_A1                       -1.929435f
+#define HPF_Fs12000_Fc66_A2                       0.964718f
+#define HPF_Fs12000_Fc66_B1                       -1.951196f
+#define HPF_Fs12000_Fc66_B2                       0.952359f
+#define HPF_Fs16000_Fc66_A0                       0.970622f
+#define HPF_Fs16000_Fc66_A1                       -1.941244f
+#define HPF_Fs16000_Fc66_A2                       0.970622f
+#define HPF_Fs16000_Fc66_B1                       -1.963394f
+#define HPF_Fs16000_Fc66_B2                       0.964052f
+#define HPF_Fs22050_Fc66_A0                       0.975509f
+#define HPF_Fs22050_Fc66_A1                       -1.951019f
+#define HPF_Fs22050_Fc66_A2                       0.975509f
+#define HPF_Fs22050_Fc66_B1                       -1.973436f
+#define HPF_Fs22050_Fc66_B2                       0.973784f
+#define HPF_Fs24000_Fc66_A0                       0.976563f
+#define HPF_Fs24000_Fc66_A1                       -1.953125f
+#define HPF_Fs24000_Fc66_A2                       0.976563f
+#define HPF_Fs24000_Fc66_B1                       -1.975594f
+#define HPF_Fs24000_Fc66_B2                       0.975889f
+#define HPF_Fs32000_Fc66_A0                       0.979547f
+#define HPF_Fs32000_Fc66_A1                       -1.959093f
+#define HPF_Fs32000_Fc66_A2                       0.979547f
+#define HPF_Fs32000_Fc66_B1                       -1.981695f
+#define HPF_Fs32000_Fc66_B2                       0.981861f
+#define HPF_Fs44100_Fc66_A0                       0.982010f
+#define HPF_Fs44100_Fc66_A1                       -1.964019f
+#define HPF_Fs44100_Fc66_A2                       0.982010f
+#define HPF_Fs44100_Fc66_B1                       -1.986718f
+#define HPF_Fs44100_Fc66_B2                       0.986805f
+#define HPF_Fs48000_Fc66_A0                       0.982540f
+#define HPF_Fs48000_Fc66_A1                       -1.965079f
+#define HPF_Fs48000_Fc66_A2                       0.982540f
+#define HPF_Fs48000_Fc66_B1                       -1.987797f
+#define HPF_Fs48000_Fc66_B2                       0.987871f
+
+#ifdef HIGHER_FS
+#define HPF_Fs96000_Fc66_A0                       0.985539f
+#define HPF_Fs96000_Fc66_A1                       -1.971077f
+#define HPF_Fs96000_Fc66_A2                       0.985539f
+#define HPF_Fs96000_Fc66_B1                       -1.993898f
+#define HPF_Fs96000_Fc66_B2                       0.993917f
+
+#define HPF_Fs192000_Fc66_A0                      0.987043f
+#define HPF_Fs192000_Fc66_A1                      -1.974086f
+#define HPF_Fs192000_Fc66_A2                      0.987043f
+#define HPF_Fs192000_Fc66_B1                      -1.996949f
+#define HPF_Fs192000_Fc66_B2                      0.996954f
+#endif
+
+/* Coefficients for centre frequency 78Hz */
+#define HPF_Fs8000_Fc78_A0                        0.946693f
+#define HPF_Fs8000_Fc78_A1                        -1.893387f
+#define HPF_Fs8000_Fc78_A2                        0.946693f
+#define HPF_Fs8000_Fc78_B1                        -1.913517f
+#define HPF_Fs8000_Fc78_B2                        0.917105f
+#define HPF_Fs11025_Fc78_A0                       0.957999f
+#define HPF_Fs11025_Fc78_A1                       -1.915998f
+#define HPF_Fs11025_Fc78_A2                       0.957999f
+#define HPF_Fs11025_Fc78_B1                       -1.937229f
+#define HPF_Fs11025_Fc78_B2                       0.939140f
+#define HPF_Fs12000_Fc78_A0                       0.960446f
+#define HPF_Fs12000_Fc78_A1                       -1.920892f
+#define HPF_Fs12000_Fc78_A2                       0.960446f
+#define HPF_Fs12000_Fc78_B1                       -1.942326f
+#define HPF_Fs12000_Fc78_B2                       0.943944f
+#define HPF_Fs16000_Fc78_A0                       0.967397f
+#define HPF_Fs16000_Fc78_A1                       -1.934794f
+#define HPF_Fs16000_Fc78_A2                       0.967397f
+#define HPF_Fs16000_Fc78_B1                       -1.956740f
+#define HPF_Fs16000_Fc78_B2                       0.957656f
+#define HPF_Fs22050_Fc78_A0                       0.973156f
+#define HPF_Fs22050_Fc78_A1                       -1.946313f
+#define HPF_Fs22050_Fc78_A2                       0.973156f
+#define HPF_Fs22050_Fc78_B1                       -1.968607f
+#define HPF_Fs22050_Fc78_B2                       0.969092f
+#define HPF_Fs24000_Fc78_A0                       0.974398f
+#define HPF_Fs24000_Fc78_A1                       -1.948797f
+#define HPF_Fs24000_Fc78_A2                       0.974398f
+#define HPF_Fs24000_Fc78_B1                       -1.971157f
+#define HPF_Fs24000_Fc78_B2                       0.971568f
+#define HPF_Fs32000_Fc78_A0                       0.977918f
+#define HPF_Fs32000_Fc78_A1                       -1.955836f
+#define HPF_Fs32000_Fc78_A2                       0.977918f
+#define HPF_Fs32000_Fc78_B1                       -1.978367f
+#define HPF_Fs32000_Fc78_B2                       0.978599f
+#define HPF_Fs44100_Fc78_A0                       0.980824f
+#define HPF_Fs44100_Fc78_A1                       -1.961649f
+#define HPF_Fs44100_Fc78_A2                       0.980824f
+#define HPF_Fs44100_Fc78_B1                       -1.984303f
+#define HPF_Fs44100_Fc78_B2                       0.984425f
+#define HPF_Fs48000_Fc78_A0                       0.981450f
+#define HPF_Fs48000_Fc78_A1                       -1.962900f
+#define HPF_Fs48000_Fc78_A2                       0.981450f
+#define HPF_Fs48000_Fc78_B1                       -1.985578f
+#define HPF_Fs48000_Fc78_B2                       0.985681f
+
+#ifdef HIGHER_FS
+#define HPF_Fs96000_Fc78_A0                       0.984992f
+#define HPF_Fs96000_Fc78_A1                       -1.969984f
+#define HPF_Fs96000_Fc78_A2                       0.984992f
+#define HPF_Fs96000_Fc78_B1                       -1.992789f
+#define HPF_Fs96000_Fc78_B2                       0.992815f
+
+#define HPF_Fs192000_Fc78_A0                      0.986769f
+#define HPF_Fs192000_Fc78_A1                      -1.973539f
+#define HPF_Fs192000_Fc78_A2                      0.986769f
+#define HPF_Fs192000_Fc78_B1                      -1.996394f
+#define HPF_Fs192000_Fc78_B2                      0.996401f
+#endif
+
+/* Coefficients for centre frequency 90Hz */
+#define HPF_Fs8000_Fc90_A0                       0.940412f
+#define HPF_Fs8000_Fc90_A1                       -1.880825f
+#define HPF_Fs8000_Fc90_A2                       0.940412f
+#define HPF_Fs8000_Fc90_B1                       -1.900231f
+#define HPF_Fs8000_Fc90_B2                       0.904977f
+#define HPF_Fs11025_Fc90_A0                      0.953383f
+#define HPF_Fs11025_Fc90_A1                      -1.906766f
+#define HPF_Fs11025_Fc90_A2                      0.953383f
+#define HPF_Fs11025_Fc90_B1                      -1.927579f
+#define HPF_Fs11025_Fc90_B2                      0.930111f
+#define HPF_Fs12000_Fc90_A0                      0.956193f
+#define HPF_Fs12000_Fc90_A1                      -1.912387f
+#define HPF_Fs12000_Fc90_A2                      0.956193f
+#define HPF_Fs12000_Fc90_B1                      -1.933459f
+#define HPF_Fs12000_Fc90_B2                      0.935603f
+#define HPF_Fs16000_Fc90_A0                      0.964183f
+#define HPF_Fs16000_Fc90_A1                      -1.928365f
+#define HPF_Fs16000_Fc90_A2                      0.964183f
+#define HPF_Fs16000_Fc90_B1                      -1.950087f
+#define HPF_Fs16000_Fc90_B2                      0.951303f
+#define HPF_Fs22050_Fc90_A0                      0.970809f
+#define HPF_Fs22050_Fc90_A1                      -1.941618f
+#define HPF_Fs22050_Fc90_A2                      0.970809f
+#define HPF_Fs22050_Fc90_B1                      -1.963778f
+#define HPF_Fs22050_Fc90_B2                      0.964423f
+#define HPF_Fs24000_Fc90_A0                      0.972239f
+#define HPF_Fs24000_Fc90_A1                      -1.944477f
+#define HPF_Fs24000_Fc90_A2                      0.972239f
+#define HPF_Fs24000_Fc90_B1                      -1.966721f
+#define HPF_Fs24000_Fc90_B2                      0.967266f
+#define HPF_Fs32000_Fc90_A0                      0.976292f
+#define HPF_Fs32000_Fc90_A1                      -1.952584f
+#define HPF_Fs32000_Fc90_A2                      0.976292f
+#define HPF_Fs32000_Fc90_B1                      -1.975040f
+#define HPF_Fs32000_Fc90_B2                      0.975347f
+#define HPF_Fs44100_Fc90_A0                      0.979641f
+#define HPF_Fs44100_Fc90_A1                      -1.959282f
+#define HPF_Fs44100_Fc90_A2                      0.979641f
+#define HPF_Fs44100_Fc90_B1                      -1.981888f
+#define HPF_Fs44100_Fc90_B2                      0.982050f
+#define HPF_Fs48000_Fc90_A0                      0.980362f
+#define HPF_Fs48000_Fc90_A1                      -1.960724f
+#define HPF_Fs48000_Fc90_A2                      0.980362f
+#define HPF_Fs48000_Fc90_B1                      -1.983359f
+#define HPF_Fs48000_Fc90_B2                      0.983497f
+
+#ifdef HIGHER_FS
+#define HPF_Fs96000_Fc90_A0                       0.984446f
+#define HPF_Fs96000_Fc90_A1                       -1.968892f
+#define HPF_Fs96000_Fc90_A2                       0.984446f
+#define HPF_Fs96000_Fc90_B1                       -1.991680f
+#define HPF_Fs96000_Fc90_B2                       0.991714f
+
+#define HPF_Fs192000_Fc90_A0                      0.986496f
+#define HPF_Fs192000_Fc90_A1                      -1.972992f
+#define HPF_Fs192000_Fc90_A2                      0.986496f
+#define HPF_Fs192000_Fc90_B1                      -1.995840f
+#define HPF_Fs192000_Fc90_B2                      0.995848f
+#endif
+
+/************************************************************************************/
+/*                                                                                  */
+/* Band Pass Filter coefficients                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Coefficients for centre frequency 55Hz */
+#define BPF_Fs8000_Fc55_A0                       0.009197f
+#define BPF_Fs8000_Fc55_A1                       0.000000f
+#define BPF_Fs8000_Fc55_A2                       -0.009197f
+#define BPF_Fs8000_Fc55_B1                       -1.979545f
+#define BPF_Fs8000_Fc55_B2                       0.981393f
+#define BPF_Fs11025_Fc55_A0                      0.006691f
+#define BPF_Fs11025_Fc55_A1                      0.000000f
+#define BPF_Fs11025_Fc55_A2                      -0.006691f
+#define BPF_Fs11025_Fc55_B1                      -1.985488f
+#define BPF_Fs11025_Fc55_B2                      0.986464f
+#define BPF_Fs12000_Fc55_A0                      0.006150f
+#define BPF_Fs12000_Fc55_A1                      0.000000f
+#define BPF_Fs12000_Fc55_A2                      -0.006150f
+#define BPF_Fs12000_Fc55_B1                      -1.986733f
+#define BPF_Fs12000_Fc55_B2                      0.987557f
+#define BPF_Fs16000_Fc55_A0                      0.004620f
+#define BPF_Fs16000_Fc55_A1                      0.000000f
+#define BPF_Fs16000_Fc55_A2                      -0.004620f
+#define BPF_Fs16000_Fc55_B1                      -1.990189f
+#define BPF_Fs16000_Fc55_B2                      0.990653f
+#define BPF_Fs22050_Fc55_A0                      0.003357f
+#define BPF_Fs22050_Fc55_A1                      0.000000f
+#define BPF_Fs22050_Fc55_A2                      -0.003357f
+#define BPF_Fs22050_Fc55_B1                      -1.992964f
+#define BPF_Fs22050_Fc55_B2                      0.993209f
+#define BPF_Fs24000_Fc55_A0                      0.003085f
+#define BPF_Fs24000_Fc55_A1                      0.000000f
+#define BPF_Fs24000_Fc55_A2                      -0.003085f
+#define BPF_Fs24000_Fc55_B1                      -1.993552f
+#define BPF_Fs24000_Fc55_B2                      0.993759f
+#define BPF_Fs32000_Fc55_A0                      0.002315f
+#define BPF_Fs32000_Fc55_A1                      0.000000f
+#define BPF_Fs32000_Fc55_A2                      -0.002315f
+#define BPF_Fs32000_Fc55_B1                      -1.995199f
+#define BPF_Fs32000_Fc55_B2                      0.995316f
+#define BPF_Fs44100_Fc55_A0                      0.001681f
+#define BPF_Fs44100_Fc55_A1                      0.000000f
+#define BPF_Fs44100_Fc55_A2                      -0.001681f
+#define BPF_Fs44100_Fc55_B1                      -1.996537f
+#define BPF_Fs44100_Fc55_B2                      0.996599f
+#define BPF_Fs48000_Fc55_A0                      0.001545f
+#define BPF_Fs48000_Fc55_A1                      0.000000f
+#define BPF_Fs48000_Fc55_A2                      -0.001545f
+#define BPF_Fs48000_Fc55_B1                      -1.996823f
+#define BPF_Fs48000_Fc55_B2                      0.996875f
+
+#ifdef HIGHER_FS
+#define BPF_Fs96000_Fc55_A0                      0.000762f
+#define BPF_Fs96000_Fc55_A1                      0.000000f
+#define BPF_Fs96000_Fc55_A2                      -0.000762f
+#define BPF_Fs96000_Fc55_B1                      -1.998461f
+#define BPF_Fs96000_Fc55_B2                      0.998477f
+
+#define BPF_Fs192000_Fc55_A0                     0.000381f
+#define BPF_Fs192000_Fc55_A1                     0.000000f
+#define BPF_Fs192000_Fc55_A2                     -0.000381f
+#define BPF_Fs192000_Fc55_B1                     -1.999234f
+#define BPF_Fs192000_Fc55_B2                     0.999238f
+#endif
+
+/* Coefficients for centre frequency 66Hz */
+#define BPF_Fs8000_Fc66_A0                      0.012648f
+#define BPF_Fs8000_Fc66_A1                      0.000000f
+#define BPF_Fs8000_Fc66_A2                      -0.012648f
+#define BPF_Fs8000_Fc66_B1                      -1.971760f
+#define BPF_Fs8000_Fc66_B2                      0.974412f
+#define BPF_Fs11025_Fc66_A0                     0.009209f
+#define BPF_Fs11025_Fc66_A1                     0.000000f
+#define BPF_Fs11025_Fc66_A2                     -0.009209f
+#define BPF_Fs11025_Fc66_B1                     -1.979966f
+#define BPF_Fs11025_Fc66_B2                     0.981368f
+#define BPF_Fs12000_Fc66_A0                     0.008468f
+#define BPF_Fs12000_Fc66_A1                     0.000000f
+#define BPF_Fs12000_Fc66_A2                     -0.008468f
+#define BPF_Fs12000_Fc66_B1                     -1.981685f
+#define BPF_Fs12000_Fc66_B2                     0.982869f
+#define BPF_Fs16000_Fc66_A0                     0.006364f
+#define BPF_Fs16000_Fc66_A1                     0.000000f
+#define BPF_Fs16000_Fc66_A2                     -0.006364f
+#define BPF_Fs16000_Fc66_B1                     -1.986457f
+#define BPF_Fs16000_Fc66_B2                     0.987124f
+#define BPF_Fs22050_Fc66_A0                     0.004626f
+#define BPF_Fs22050_Fc66_A1                     0.000000f
+#define BPF_Fs22050_Fc66_A2                     -0.004626f
+#define BPF_Fs22050_Fc66_B1                     -1.990288f
+#define BPF_Fs22050_Fc66_B2                     0.990641f
+#define BPF_Fs24000_Fc66_A0                     0.004252f
+#define BPF_Fs24000_Fc66_A1                     0.000000f
+#define BPF_Fs24000_Fc66_A2                     -0.004252f
+#define BPF_Fs24000_Fc66_B1                     -1.991100f
+#define BPF_Fs24000_Fc66_B2                     0.991398f
+#define BPF_Fs32000_Fc66_A0                     0.003192f
+#define BPF_Fs32000_Fc66_A1                     0.000000f
+#define BPF_Fs32000_Fc66_A2                     -0.003192f
+#define BPF_Fs32000_Fc66_B1                     -1.993374f
+#define BPF_Fs32000_Fc66_B2                     0.993541f
+#define BPF_Fs44100_Fc66_A0                     0.002318f
+#define BPF_Fs44100_Fc66_A1                     0.000000f
+#define BPF_Fs44100_Fc66_A2                     -0.002318f
+#define BPF_Fs44100_Fc66_B1                     -1.995221f
+#define BPF_Fs44100_Fc66_B2                     0.995309f
+#define BPF_Fs48000_Fc66_A0                     0.002131f
+#define BPF_Fs48000_Fc66_A1                     0.000000f
+#define BPF_Fs48000_Fc66_A2                     -0.002131f
+#define BPF_Fs48000_Fc66_B1                     -1.995615f
+#define BPF_Fs48000_Fc66_B2                     0.995690f
+
+#ifdef HIGHER_FS
+#define BPF_Fs96000_Fc66_A0                     0.001055f
+#define BPF_Fs96000_Fc66_A1                     0.000000f
+#define BPF_Fs96000_Fc66_A2                     -0.001055f
+#define BPF_Fs96000_Fc66_B1                     -1.997868f
+#define BPF_Fs96000_Fc66_B2                     0.997891f
+
+#define BPF_Fs192000_Fc66_A0                    0.000528f
+#define BPF_Fs192000_Fc66_A1                    0.000000f
+#define BPF_Fs192000_Fc66_A2                   -0.000528f
+#define BPF_Fs192000_Fc66_B1                   -1.998939f
+#define BPF_Fs192000_Fc66_B2                    0.998945f
+#endif
+
+/* Coefficients for centre frequency 78Hz */
+#define BPF_Fs8000_Fc78_A0                      0.018572f
+#define BPF_Fs8000_Fc78_A1                      0.000000f
+#define BPF_Fs8000_Fc78_A2                      -0.018572f
+#define BPF_Fs8000_Fc78_B1                      -1.958745f
+#define BPF_Fs8000_Fc78_B2                      0.962427f
+#define BPF_Fs11025_Fc78_A0                     0.013545f
+#define BPF_Fs11025_Fc78_A1                     0.000000f
+#define BPF_Fs11025_Fc78_A2                     -0.013545f
+#define BPF_Fs11025_Fc78_B1                     -1.970647f
+#define BPF_Fs11025_Fc78_B2                     0.972596f
+#define BPF_Fs12000_Fc78_A0                     0.012458f
+#define BPF_Fs12000_Fc78_A1                     0.000000f
+#define BPF_Fs12000_Fc78_A2                     -0.012458f
+#define BPF_Fs12000_Fc78_B1                     -1.973148f
+#define BPF_Fs12000_Fc78_B2                     0.974795f
+#define BPF_Fs16000_Fc78_A0                     0.009373f
+#define BPF_Fs16000_Fc78_A1                     0.000000f
+#define BPF_Fs16000_Fc78_A2                     -0.009373f
+#define BPF_Fs16000_Fc78_B1                     -1.980108f
+#define BPF_Fs16000_Fc78_B2                     0.981037f
+#define BPF_Fs22050_Fc78_A0                     0.006819f
+#define BPF_Fs22050_Fc78_A1                     0.000000f
+#define BPF_Fs22050_Fc78_A2                     -0.006819f
+#define BPF_Fs22050_Fc78_B1                     -1.985714f
+#define BPF_Fs22050_Fc78_B2                     0.986204f
+#define BPF_Fs24000_Fc78_A0                     0.006268f
+#define BPF_Fs24000_Fc78_A1                     0.000000f
+#define BPF_Fs24000_Fc78_A2                     -0.006268f
+#define BPF_Fs24000_Fc78_B1                     -1.986904f
+#define BPF_Fs24000_Fc78_B2                     0.987318f
+#define BPF_Fs32000_Fc78_A0                     0.004709f
+#define BPF_Fs32000_Fc78_A1                     0.000000f
+#define BPF_Fs32000_Fc78_A2                     -0.004709f
+#define BPF_Fs32000_Fc78_B1                     -1.990240f
+#define BPF_Fs32000_Fc78_B2                     0.990473f
+#define BPF_Fs44100_Fc78_A0                     0.003421f
+#define BPF_Fs44100_Fc78_A1                     0.000000f
+#define BPF_Fs44100_Fc78_A2                     -0.003421f
+#define BPF_Fs44100_Fc78_B1                     -1.992955f
+#define BPF_Fs44100_Fc78_B2                     0.993078f
+#define BPF_Fs48000_Fc78_A0                     0.003144f
+#define BPF_Fs48000_Fc78_A1                     0.000000f
+#define BPF_Fs48000_Fc78_A2                     -0.003144f
+#define BPF_Fs48000_Fc78_B1                     -1.993535f
+#define BPF_Fs48000_Fc78_B2                     0.993639f
+
+#ifdef HIGHER_FS
+#define BPF_Fs96000_Fc78_A0                     0.001555f
+#define BPF_Fs96000_Fc78_A1                     0.000000f
+#define BPF_Fs96000_Fc78_A2                    -0.0015555f
+#define BPF_Fs96000_Fc78_B1                    -1.996860f
+#define BPF_Fs96000_Fc78_B2                     0.996891f
+
+#define BPF_Fs192000_Fc78_A0                    0.000778f
+#define BPF_Fs192000_Fc78_A1                    0.000000f
+#define BPF_Fs192000_Fc78_A2                   -0.000778f
+#define BPF_Fs192000_Fc78_B1                   -1.998437f
+#define BPF_Fs192000_Fc78_B2                    0.998444f
+#endif
+
+/* Coefficients for centre frequency 90Hz */
+#define BPF_Fs8000_Fc90_A0                       0.022760f
+#define BPF_Fs8000_Fc90_A1                       0.000000f
+#define BPF_Fs8000_Fc90_A2                       -0.022760f
+#define BPF_Fs8000_Fc90_B1                       -1.949073f
+#define BPF_Fs8000_Fc90_B2                       0.953953f
+#define BPF_Fs11025_Fc90_A0                      0.016619f
+#define BPF_Fs11025_Fc90_A1                      0.000000f
+#define BPF_Fs11025_Fc90_A2                      -0.016619f
+#define BPF_Fs11025_Fc90_B1                      -1.963791f
+#define BPF_Fs11025_Fc90_B2                      0.966377f
+#define BPF_Fs12000_Fc90_A0                      0.015289f
+#define BPF_Fs12000_Fc90_A1                      0.000000f
+#define BPF_Fs12000_Fc90_A2                      -0.015289f
+#define BPF_Fs12000_Fc90_B1                      -1.966882f
+#define BPF_Fs12000_Fc90_B2                      0.969067f
+#define BPF_Fs16000_Fc90_A0                      0.011511f
+#define BPF_Fs16000_Fc90_A1                      0.000000f
+#define BPF_Fs16000_Fc90_A2                      -0.011511f
+#define BPF_Fs16000_Fc90_B1                      -1.975477f
+#define BPF_Fs16000_Fc90_B2                      0.976711f
+#define BPF_Fs22050_Fc90_A0                      0.008379f
+#define BPF_Fs22050_Fc90_A1                      0.000000f
+#define BPF_Fs22050_Fc90_A2                      -0.008379f
+#define BPF_Fs22050_Fc90_B1                      -1.982395f
+#define BPF_Fs22050_Fc90_B2                      0.983047f
+#define BPF_Fs24000_Fc90_A0                      0.007704f
+#define BPF_Fs24000_Fc90_A1                      0.000000f
+#define BPF_Fs24000_Fc90_A2                      -0.007704f
+#define BPF_Fs24000_Fc90_B1                      -1.983863f
+#define BPF_Fs24000_Fc90_B2                      0.984414f
+#define BPF_Fs32000_Fc90_A0                      0.005789f
+#define BPF_Fs32000_Fc90_A1                      0.000000f
+#define BPF_Fs32000_Fc90_A2                      -0.005789f
+#define BPF_Fs32000_Fc90_B1                      -1.987977f
+#define BPF_Fs32000_Fc90_B2                      0.988288f
+#define BPF_Fs44100_Fc90_A0                      0.004207f
+#define BPF_Fs44100_Fc90_A1                      0.000000f
+#define BPF_Fs44100_Fc90_A2                      -0.004207f
+#define BPF_Fs44100_Fc90_B1                      -1.991324f
+#define BPF_Fs44100_Fc90_B2                      0.991488f
+#define BPF_Fs48000_Fc90_A0                      0.003867f
+#define BPF_Fs48000_Fc90_A1                      0.000000f
+#define BPF_Fs48000_Fc90_A2                      -0.003867f
+#define BPF_Fs48000_Fc90_B1                      -1.992038f
+#define BPF_Fs48000_Fc90_B2                      0.992177f
+
+#ifdef HIGHER_FS
+#define BPF_Fs96000_Fc90_A0                      0.001913f
+#define BPF_Fs96000_Fc90_A1                      0.000000f
+#define BPF_Fs96000_Fc90_A2                     -0.001913f
+#define BPF_Fs96000_Fc90_B1                     -1.996134f
+#define BPF_Fs96000_Fc90_B2                      0.996174f
+
+#define BPF_Fs192000_Fc90_A0                     0.000958f
+#define BPF_Fs192000_Fc90_A1                     0.000000f
+#define BPF_Fs192000_Fc90_A2                    -0.000958f
+#define BPF_Fs192000_Fc90_B1                    -1.998075f
+#define BPF_Fs192000_Fc90_B2                     0.998085f
+#endif
+
+/************************************************************************************/
+/*                                                                                  */
+/* Automatic Gain Control time constants and gain settings                          */
+/*                                                                                  */
+/************************************************************************************/
+
+/* AGC Time constants */
+#define AGC_ATTACK_Fs8000                             0.841395f
+#define AGC_ATTACK_Fs11025                            0.882223f
+#define AGC_ATTACK_Fs12000                            0.891251f
+#define AGC_ATTACK_Fs16000                            0.917276f
+#define AGC_ATTACK_Fs22050                            0.939267f
+#define AGC_ATTACK_Fs24000                            0.944061f
+#define AGC_ATTACK_Fs32000                            0.957745f
+#define AGC_ATTACK_Fs44100                            0.969158f
+#define AGC_ATTACK_Fs48000                            0.971628f
+
+#ifdef HIGHER_FS
+#define AGC_ATTACK_Fs96000                             0.985712f
+#define AGC_ATTACK_Fs192000                            0.992830f
+#endif
+
+#define DECAY_SHIFT                                   10
+
+#define AGC_DECAY_Fs8000                              0.000042f
+#define AGC_DECAY_Fs11025                             0.000030f
+#define AGC_DECAY_Fs12000                             0.000028f
+#define AGC_DECAY_Fs16000                             0.000021f
+#define AGC_DECAY_Fs22050                             0.000015f
+#define AGC_DECAY_Fs24000                             0.000014f
+#define AGC_DECAY_Fs32000                             0.000010f
+#define AGC_DECAY_Fs44100                             0.000008f
+#define AGC_DECAY_Fs48000                             0.000007f
+
+#ifdef HIGHER_FS
+#define AGC_DECAY_FS96000                            0.0000035f
+#define AGC_DECAY_FS192000                          0.00000175f
+#endif
+
+/* AGC Gain settings */
+#define AGC_GAIN_SCALE                                        31         /* As a power of 2 */
+#define AGC_GAIN_SHIFT                                         4         /* As a power of 2 */
+#define AGC_TARGETLEVEL                            0.988553f
+#define AGC_HPFGAIN_0dB                            0.412538f
+#define AGC_GAIN_0dB                               0.000000f
+#define AGC_HPFGAIN_1dB                            0.584893f
+#define AGC_GAIN_1dB                               0.122018f
+#define AGC_HPFGAIN_2dB                            0.778279f
+#define AGC_GAIN_2dB                               0.258925f
+#define AGC_HPFGAIN_3dB                            0.995262f
+#define AGC_GAIN_3dB                               0.412538f
+#define AGC_HPFGAIN_4dB                            1.238721f
+#define AGC_GAIN_4dB                               0.584893f
+#define AGC_HPFGAIN_5dB                            1.511886f
+#define AGC_GAIN_5dB                               0.778279f
+#define AGC_HPFGAIN_6dB                            1.818383f
+#define AGC_GAIN_6dB                               0.995262f
+#define AGC_HPFGAIN_7dB                            2.162278f
+#define AGC_GAIN_7dB                               1.238721f
+#define AGC_HPFGAIN_8dB                            2.548134f
+#define AGC_GAIN_8dB                               1.511886f
+#define AGC_HPFGAIN_9dB                            2.981072f
+#define AGC_GAIN_9dB                               1.818383f
+#define AGC_HPFGAIN_10dB                           3.466836f
+#define AGC_GAIN_10dB                              2.162278f
+#define AGC_HPFGAIN_11dB                           4.011872f
+#define AGC_GAIN_11dB                              2.548134f
+#define AGC_HPFGAIN_12dB                           4.623413f
+#define AGC_GAIN_12dB                              2.981072f
+#define AGC_HPFGAIN_13dB                           5.309573f
+#define AGC_GAIN_13dB                              3.466836f
+#define AGC_HPFGAIN_14dB                           6.079458f
+#define AGC_GAIN_14dB                              4.011872f
+#define AGC_HPFGAIN_15dB                           6.943282f
+#define AGC_GAIN_15dB                              4.623413f
+
+/************************************************************************************/
+/*                                                                                  */
+/* Volume control                                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Volume control gain */
+#define VOLUME_MAX                                          0         /* In dBs */
+#define VOLUME_SHIFT                                        0         /* In dBs */
+
+/* Volume control time constants */
+#define VOL_TC_SHIFT                                       21         /* As a power of 2 */
+#define VOL_TC_Fs8000                                   0.024690f
+#define VOL_TC_Fs11025                                  0.017977f
+#define VOL_TC_Fs12000                                  0.016529f
+#define VOL_TC_Fs16000                                  0.012422f
+#define VOL_TC_Fs22050                                  0.009029f
+#define VOL_TC_Fs24000                                  0.008299f
+#define VOL_TC_Fs32000                                  0.006231f
+#define VOL_TC_Fs44100                                  0.004525f
+#define VOL_TC_Fs48000                                  0.004158f
+#ifdef HIGHER_FS
+#define VOL_TC_Fs96000                                  0.002079f
+#define VOL_TC_Fs192000                                 0.001039f
+#endif
+#define MIX_TC_Fs8000                                   29365         /* Floating point value 0.896151 */
+#define MIX_TC_Fs11025                                  30230         /* Floating point value 0.922548 */
+#define MIX_TC_Fs12000                                  30422         /* Floating point value 0.928415 */
+#define MIX_TC_Fs16000                                  30978         /* Floating point value 0.945387 */
+#define MIX_TC_Fs22050                                  31451         /* Floating point value 0.959804 */
+#define MIX_TC_Fs24000                                  31554         /* Floating point value 0.962956 */
+#define MIX_TC_Fs32000                                  31850         /* Floating point value 0.971973 */
+#define MIX_TC_Fs44100                                  32097         /* Floating point value 0.979515 */
+#define MIX_TC_Fs48000                                  32150         /* Floating point value 0.981150 */
+#ifdef HIGHER_FS
+#define MIX_TC_Fs96000                                  32456         /* Floating point value 0.990530 */
+#define MIX_TC_Fs192000                                 32611         /* Floating point value 0.992524 */
+#endif
+
+#endif /*BUILD_FLOAT*/
+#endif
\ No newline at end of file
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
index b6632a3..fd4016b 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
@@ -107,35 +107,68 @@
                          LVDBE_Params_t       *pParams)
 {
 
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
     /*
      * Calculate the table offsets
      */
-    LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000)));
-
+    LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
+                                    (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_192000)));
+#else
+    /*
+     * Calculate the table offsets
+     */
+    LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
+                                    (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000)));    
+#endif
 
     /*
      * Setup the high pass filter
      */
-    LoadConst_16(0,                                                 /* Clear the history, value 0 */
-                 (void *)&pInstance->pData->HPFTaps,                /* Destination Cast to void: \
-                                                                     no dereferencing in function*/
+#ifndef BUILD_FLOAT
+    LoadConst_16(0,                                              /* Clear the history, value 0 */
+                 (void *)&pInstance->pData->HPFTaps,             /* Destination Cast to void: \
+                                                                    no dereferencing in function*/
                  sizeof(pInstance->pData->HPFTaps)/sizeof(LVM_INT16));   /* Number of words */
-    BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,         /* Initialise the filter */
+#else
+    LoadConst_Float(0,                                          /* Clear the history, value 0 */
+                   (void *)&pInstance->pData->HPFTaps,          /* Destination Cast to void: \
+                                                                  no dereferencing in function*/
+                    sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
+#endif
+#ifndef BUILD_FLOAT
+    BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,    /* Initialise the filter */
                                     &pInstance->pData->HPFTaps,
                                     (BQ_C32_Coefs_t *)&LVDBE_HPF_Table[Offset]);
+#else
+    BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,    /* Initialise the filter */
+                                    &pInstance->pData->HPFTaps,
+                                    (BQ_FLOAT_Coefs_t *)&LVDBE_HPF_Table[Offset]);
+#endif
 
 
     /*
      * Setup the band pass filter
      */
+#ifndef BUILD_FLOAT
     LoadConst_16(0,                                                 /* Clear the history, value 0 */
-                 (void *)&pInstance->pData->BPFTaps,                /* Destination Cast to void:\
+                 (void *)&pInstance->pData->BPFTaps,                /* Destination Cast to void: \
                                                                      no dereferencing in function*/
                  sizeof(pInstance->pData->BPFTaps)/sizeof(LVM_INT16));   /* Number of words */
+#else
+    LoadConst_Float(0,                                           /* Clear the history, value 0 */
+                 (void *)&pInstance->pData->BPFTaps,             /* Destination Cast to void: \
+                                                                    no dereferencing in function*/
+                 sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT));   /* Number of words */
+#endif
+#ifndef BUILD_FLOAT
     BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,         /* Initialise the filter */
                                     &pInstance->pData->BPFTaps,
                                     (BP_C32_Coefs_t *)&LVDBE_BPF_Table[Offset]);
-
+#else
+    BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,    /* Initialise the filter */
+                                    &pInstance->pData->BPFTaps,
+                                    (BP_FLOAT_Coefs_t *)&LVDBE_BPF_Table[Offset]);
+#endif
 }
 
 
@@ -175,7 +208,9 @@
     {
         pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel];     /* High pass filter off */
     }
+#ifndef BUILD_FLOAT
     pInstance->pData->AGCInstance.AGC_GainShift = AGC_GAIN_SHIFT;
+#endif
     pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL;
 
 }
@@ -212,6 +247,9 @@
     LVM_UINT16      dBOffset;                                   /* Table offset */
     LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
 
+#ifdef BUILD_FLOAT
+    LVM_FLOAT        dBShifts_fac;
+#endif
     /*
      * Apply the volume if enabled
      */
@@ -237,33 +275,58 @@
     dBOffset = (LVM_UINT16)(6 + Volume % 6);                    /* Get the dBs 0-5 */
     dBShifts = (LVM_UINT16)(Volume / -6);                       /* Get the 6dB shifts */
 
-
+#ifdef BUILD_FLOAT
+    dBShifts_fac = (LVM_FLOAT)(1 << dBShifts);
+#endif
     /*
      * When DBE is enabled use AGC volume
      */
+#ifndef BUILD_FLOAT
     pInstance->pData->AGCInstance.Target = ((LVM_INT32)LVDBE_VolumeTable[dBOffset] << 16);
     pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target >> dBShifts;
-
+#else
+    pInstance->pData->AGCInstance.Target = (LVDBE_VolumeTable[dBOffset]);
+    pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target / dBShifts_fac;
+#endif
     pInstance->pData->AGCInstance.VolumeTC    = LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate];   /* Volume update time constant */
+#ifndef BUILD_FLOAT
     pInstance->pData->AGCInstance.VolumeShift = VOLUME_SHIFT+1;
+#endif
 
     /*
      * When DBE is disabled use the bypass volume control
      */
     if(dBShifts > 0)
     {
+#ifndef BUILD_FLOAT
         LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(((LVM_INT32)LVDBE_VolumeTable[dBOffset]) >> dBShifts));
+#else
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
+                            LVDBE_VolumeTable[dBOffset] / dBShifts_fac);
+#endif
     }
     else
     {
+#ifndef BUILD_FLOAT
         LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(LVM_INT32)LVDBE_VolumeTable[dBOffset]);
+#else
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
+                            LVDBE_VolumeTable[dBOffset]);
+#endif
     }
 
     pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1;
+#ifndef BUILD_FLOAT
     LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
                                 LVDBE_MIXER_TC,
                                 (LVM_Fs_en)pInstance->Params.SampleRate,
                                 2);
+#else
+    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
+                                LVDBE_MIXER_TC,
+                                (LVM_Fs_en)pInstance->Params.SampleRate,
+                                2);
+#endif
 }
 
 
@@ -309,7 +372,11 @@
 {
 
     LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
+#ifndef BUILD_FLOAT
     LVMixer3_2St_st     *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
+#else
+    LVMixer3_2St_FLOAT_st     *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
+#endif
 
 
     /*
@@ -332,12 +399,19 @@
     {
         LVDBE_SetAGC(pInstance,                         /* Instance pointer */
                      pParams);                          /* New parameters */
-
+#ifndef BUILD_FLOAT
         LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
             LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
 
         LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
             LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+#else
+        LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
+            LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
+
+        LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
+            LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
+#endif
 
 
     }
@@ -357,13 +431,23 @@
 
     if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF)
     {
+#ifndef BUILD_FLOAT
         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0);
         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0x00007FFF);
+#else
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 0);
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 1.0f);
+#endif
     }
     if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
     {
+#ifndef BUILD_FLOAT
         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0x00007FFF);
         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0);
+#else
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 1.0f);
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 0);
+#endif
     }
 
     /*
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
index a3623bc..3fff2a2 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
@@ -80,7 +80,11 @@
         /*
          * Data memory
          */
+#ifdef BUILD_FLOAT
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size   = sizeof(LVDBE_Data_FLOAT_t);
+#else
         pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size         = sizeof(LVDBE_Data_t);
+#endif
         pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Alignment    = LVDBE_PERSISTENT_DATA_ALIGN;
         pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Type         = LVDBE_PERSISTENT_DATA;
         pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
@@ -88,7 +92,11 @@
         /*
          * Coef memory
          */
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size         = sizeof(LVDBE_Coef_t);
+#ifdef BUILD_FLOAT
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size   = sizeof(LVDBE_Coef_FLOAT_t);
+#else
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size         = sizeof(LVDBE_Coef_t);   
+#endif
         pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Alignment    = LVDBE_PERSISTENT_COEF_ALIGN;
         pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Type         = LVDBE_PERSISTENT_COEF;
         pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
@@ -96,7 +104,12 @@
         /*
          * Scratch memory
          */
+#ifdef BUILD_FLOAT
+        ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_FLOAT) * \
+                                        pCapabilities->MaxBlockSize);
+#else /*BUILD_FLOAT*/
         ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
+#endif
         pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Size         = ScratchSize;
         pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Alignment    = LVDBE_SCRATCH_ALIGN;
         pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Type         = LVDBE_SCRATCH;
@@ -151,10 +164,16 @@
 {
 
     LVDBE_Instance_t      *pInstance;
+#ifdef BUILD_FLOAT
+    LVMixer3_1St_FLOAT_st       *pMixer_Instance;
+    LVMixer3_2St_FLOAT_st       *pBypassMixer_Instance;
+    LVM_FLOAT             MixGain;
+#else
     LVMixer3_1St_st       *pMixer_Instance;
     LVMixer3_2St_st       *pBypassMixer_Instance;
-    LVM_INT16             i;
     LVM_INT32             MixGain;
+#endif
+    LVM_INT16             i;
 
 
     /*
@@ -235,7 +254,11 @@
     // initialize the mixer with some fixes values since otherwise LVDBE_SetVolume ends up
     // reading uninitialized data
     pMixer_Instance = &pInstance->pData->BypassVolume;
+#ifndef BUILD_FLOAT
     LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],0x00007FFF,0x00007FFF);
+#else
+    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0], 1.0, 1.0);
+#endif
 
     /*
      * Initialise the volume
@@ -245,9 +268,13 @@
 
     pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target;
                                                 /* Initialise as the target */
-
+#ifndef BUILD_FLOAT
     MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
     LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],MixGain,MixGain);
+#else
+    MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
+    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0], MixGain, MixGain);
+#endif
 
     /* Configure the mixer process path */
     pMixer_Instance->MixerStream[0].CallbackParam = 0;
@@ -268,9 +295,11 @@
     pBypassMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
     pBypassMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
     pBypassMixer_Instance->MixerStream[0].CallbackSet=0;
+
     LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[0],0,0);
     LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
         LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate,2);
+
     /*
      * Setup the mixer gain for the unprocessed path
      */
@@ -278,9 +307,15 @@
     pBypassMixer_Instance->MixerStream[1].pCallbackHandle = LVM_NULL;
     pBypassMixer_Instance->MixerStream[1].pCallBack = LVM_NULL;
     pBypassMixer_Instance->MixerStream[1].CallbackSet=0;
+#ifndef BUILD_FLOAT
     LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1],0x00007FFF,0x00007FFF);
     LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
         LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate,2);
+#else
+    LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1], 1.0, 1.0);
+    LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
+        LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate, 2);
+#endif
 
     return(LVDBE_SUCCESS);
 }
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index 8339d3c..4e5207f 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -77,6 +77,7 @@
 /****************************************************************************************/
 
 /* Data structure */
+#ifndef BUILD_FLOAT
 typedef struct
 {
     /* AGC parameters */
@@ -98,7 +99,29 @@
     Biquad_Instance_t           BPFInstance;        /* Band pass filter instance */
 
 } LVDBE_Coef_t;
+#else
+/* Data structure */
+typedef struct
+{
+    /* AGC parameters */
+    AGC_MIX_VOL_2St1Mon_FLOAT_t   AGCInstance;        /* AGC instance parameters */
 
+    /* Process variables */
+    Biquad_2I_Order2_FLOAT_Taps_t     HPFTaps;            /* High pass filter taps */
+    Biquad_1I_Order2_FLOAT_Taps_t     BPFTaps;            /* Band pass filter taps */
+    LVMixer3_1St_FLOAT_st             BypassVolume;       /* Bypass volume scaler */
+    LVMixer3_2St_FLOAT_st             BypassMixer;        /* Bypass Mixer for Click Removal */
+
+} LVDBE_Data_FLOAT_t;
+
+/* Coefs structure */
+typedef struct
+{
+    /* Process variables */
+    Biquad_FLOAT_Instance_t           HPFInstance;        /* High pass filter instance */
+    Biquad_FLOAT_Instance_t           BPFInstance;        /* Band pass filter instance */
+} LVDBE_Coef_FLOAT_t;
+#endif
 /* Instance structure */
 typedef struct
 {
@@ -108,8 +131,13 @@
     LVDBE_Capabilities_t        Capabilities;         /* Instance capabilities */
 
     /* Data and coefficient pointers */
+#ifndef BUILD_FLOAT
     LVDBE_Data_t                *pData;                /* Instance data */
     LVDBE_Coef_t                *pCoef;                /* Instance coefficients */
+#else
+    LVDBE_Data_FLOAT_t                *pData;                /* Instance data */
+    LVDBE_Coef_FLOAT_t                *pCoef;                /* Instance coefficients */
+#endif
 } LVDBE_Instance_t;
 
 
@@ -136,5 +164,3 @@
 #endif /* __cplusplus */
 
 #endif      /* __LVDBE_PRIVATE_H__ */
-
-
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
index 69d79d2..10ea700 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
@@ -27,7 +27,6 @@
 #include "AGC.h"
 #include "LVDBE_Coeffs.h"               /* Filter coefficients */
 
-
 /********************************************************************************************/
 /*                                                                                          */
 /* FUNCTION:                 LVDBE_Process                                                  */
@@ -72,136 +71,236 @@
 /*     overall end to end gain is odB.                                                      */
 /*                                                                                          */
 /********************************************************************************************/
+#ifndef BUILD_FLOAT
+LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
+    const LVM_INT16 *pInData, LVM_INT16 *pOutData, LVM_UINT16 NumSamples) {
 
-LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t            hInstance,
-                                       const LVM_INT16         *pInData,
-                                       LVM_INT16               *pOutData,
-                                       LVM_UINT16                   NumSamples)
+  LVDBE_Instance_t *pInstance = (LVDBE_Instance_t *) hInstance;
+  LVM_INT32 *pScratch =
+      (LVM_INT32 *) pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
+  LVM_INT32 *pMono;
+  LVM_INT16 *pInput = (LVM_INT16 *) pInData;
+
+  /* Scratch for Volume Control starts at offset of 2*NumSamples short values from pScratch */
+  LVM_INT16 *pScratchVol = (LVM_INT16 *) (&pScratch[NumSamples]);
+
+  /* Scratch for Mono path starts at offset of 2*NumSamples 32-bit values from pScratch */
+  pMono = &pScratch[2 * NumSamples];
+
+  /*
+   * Check the number of samples is not too large
+   */
+  if (NumSamples > pInstance->Capabilities.MaxBlockSize) {
+    return (LVDBE_TOOMANYSAMPLES);
+  }
+
+  /*
+   * Check if the algorithm is enabled
+   */
+  /* DBE path is processed when DBE is ON or during On/Off transitions */
+  if ((pInstance->Params.OperatingMode == LVDBE_ON)
+      || (LVC_Mixer_GetCurrent(
+          &pInstance->pData->BypassMixer.MixerStream[0])
+          != LVC_Mixer_GetTarget(
+              &pInstance->pData->BypassMixer.MixerStream[0]))) {
+
+    /*
+     * Convert 16-bit samples to 32-bit and scale
+     * (For a 16-bit implementation apply headroom loss here)
+     */
+    Int16LShiftToInt32_16x32(pInput, /* Source 16-bit data    */
+    pScratch, /* Dest. 32-bit data     */
+    (LVM_INT16) (2 * NumSamples), /* Left and right        */
+    LVDBE_SCALESHIFT); /* Shift scale           */
+
+    /*
+     * Apply the high pass filter if selected
+     */
+    if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
+      BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance      */
+      (LVM_INT32 *) pScratch, /* Source               */
+      (LVM_INT32 *) pScratch, /* Destination          */
+      (LVM_INT16) NumSamples); /* Number of samples    */
+    }
+
+    /*
+     * Create the mono stream
+     */
+    From2iToMono_32(pScratch, /* Stereo source         */
+    pMono, /* Mono destination      */
+    (LVM_INT16) NumSamples); /* Number of samples     */
+
+    /*
+     * Apply the band pass filter
+     */
+    BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance       */
+    (LVM_INT32 *) pMono, /* Source                */
+    (LVM_INT32 *) pMono, /* Destination           */
+    (LVM_INT16) NumSamples); /* Number of samples     */
+
+    /*
+     * Apply the AGC and mix
+     */
+    AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer      */
+    pScratch, /* Stereo source         */
+    pMono, /* Mono band pass source */
+    pScratch, /* Stereo destination    */
+    NumSamples); /* Number of samples     */
+
+    /*
+     * Convert 32-bit samples to 16-bit and saturate
+     * (Not required for 16-bit implemenations)
+     */
+    Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data    */
+    (LVM_INT16 *) pScratch, /* Dest. 16-bit data     */
+    (LVM_INT16) (2 * NumSamples), /* Left and right        */
+    LVDBE_SCALESHIFT); /* Shift scale           */
+
+  }
+
+  /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
+  if ((pInstance->Params.OperatingMode == LVDBE_OFF)
+      || (LVC_Mixer_GetCurrent(
+          &pInstance->pData->BypassMixer.MixerStream[1])
+          != LVC_Mixer_GetTarget(
+              &pInstance->pData->BypassMixer.MixerStream[1]))) {
+
+    /*
+     * The algorithm is disabled but volume management is required to compensate for
+     * headroom and volume (if enabled)
+     */
+    LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume, pInData,
+        pScratchVol, (LVM_INT16) (2 * NumSamples)); /* Left and right          */
+
+  }
+
+  /*
+   * Mix DBE processed path and bypass volume path
+   */
+  LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
+      (LVM_INT16 *) pScratch, pScratchVol, pOutData,
+      (LVM_INT16) (2 * NumSamples));
+
+  return (LVDBE_SUCCESS);
+}
+#else /*BUILD_FLOAT*/
+LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
+    const LVM_FLOAT *pInData,
+    LVM_FLOAT *pOutData,
+    LVM_UINT16 NumSamples)
 {
 
-    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
-    LVM_INT32           *pScratch  = (LVM_INT32 *)pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
-    LVM_INT32           *pMono;
-    LVM_INT16           *pInput    = (LVM_INT16 *)pInData;
+  LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
+  LVM_FLOAT *pScratch_in = (LVM_FLOAT *)pInstance->MemoryTable.Region
+  [LVDBE_MEMREGION_SCRATCH].pBaseAddress;
+  LVM_FLOAT *pScratch = pScratch_in + 2 * NumSamples;
+  LVM_FLOAT *pMono;
+  LVM_INT32 ii = 0;
 
+  /* Scratch for Volume Control starts at offset of 4*NumSamples float values from pScratch */
+  LVM_FLOAT           *pScratchVol = (LVM_FLOAT *)(&pScratch_in[4 * NumSamples]);
+//  LVM_INT16 *pScratchVol_int = (LVM_INT16 *)(pScratchVol);
 
-    /* Scratch for Volume Control starts at offset of 2*NumSamples short values from pScratch */
-    LVM_INT16           *pScratchVol = (LVM_INT16 *)(&pScratch[NumSamples]);
+  /* Scratch for Mono path starts at offset of 6*NumSamples 32-bit values from pScratch */
+  pMono = &pScratch_in[4 * NumSamples];
 
-    /* Scratch for Mono path starts at offset of 2*NumSamples 32-bit values from pScratch */
-    pMono                            = &pScratch[2*NumSamples];
+  /*
+   * Check the number of samples is not too large
+   */
+  if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+  {
+    return(LVDBE_TOOMANYSAMPLES);
+  }
+
+  /*
+   * Convert 16-bit samples to Float
+   */
+  Copy_Float(pInData, /* Source 16-bit data    */
+      pScratch_in, /* Dest. 32-bit data     */
+      (LVM_INT16)(2 * NumSamples)); /* Left and right        */
+
+  for (ii = 0; ii < 2 * NumSamples; ii++) {
+    pScratch[ii] = pScratch_in[ii];
+  }
+  /*
+   * Check if the algorithm is enabled
+   */
+  /* DBE path is processed when DBE is ON or during On/Off transitions */
+  if ((pInstance->Params.OperatingMode == LVDBE_ON)||
+      (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
+          !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
+  {
 
     /*
-     * Check the number of samples is not too large
+     * Apply the high pass filter if selected
      */
-    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+    if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
     {
-        return(LVDBE_TOOMANYSAMPLES);
+      BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance      */
+          (LVM_FLOAT *)pScratch, /* Source               */
+          (LVM_FLOAT *)pScratch, /* Destination          */
+          (LVM_INT16)NumSamples); /* Number of samples    */
     }
 
     /*
-     * Check if the algorithm is enabled
+     * Create the mono stream
      */
-    /* DBE path is processed when DBE is ON or during On/Off transitions */
-    if ((pInstance->Params.OperatingMode == LVDBE_ON)||
-        (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
-         !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
-    {
-
-        /*
-         * Convert 16-bit samples to 32-bit and scale
-         * (For a 16-bit implementation apply headroom loss here)
-         */
-        Int16LShiftToInt32_16x32(pInput,                               /* Source 16-bit data    */
-                                 pScratch,                             /* Dest. 32-bit data     */
-                                 (LVM_INT16)(2*NumSamples),            /* Left and right        */
-                                 LVDBE_SCALESHIFT);                    /* Shift scale           */
-
-
-        /*
-         * Apply the high pass filter if selected
-         */
-        if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
-        {
-              BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance      */
-                                       (LVM_INT32 *)pScratch,           /* Source               */
-                                       (LVM_INT32 *)pScratch,           /* Destination          */
-                                       (LVM_INT16)NumSamples);          /* Number of samples    */
-        }
-
-
-        /*
-         * Create the mono stream
-         */
-        From2iToMono_32(pScratch,                                      /* Stereo source         */
-                        pMono,                                         /* Mono destination      */
-                        (LVM_INT16)NumSamples);                        /* Number of samples     */
-
-
-        /*
-         * Apply the band pass filter
-         */
-        BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance,     /* Filter instance       */
-                                   (LVM_INT32 *)pMono,                 /* Source                */
-                                   (LVM_INT32 *)pMono,                 /* Destination           */
-                                   (LVM_INT16)NumSamples);             /* Number of samples     */
-
-
-        /*
-         * Apply the AGC and mix
-         */
-        AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance,    /* Instance pointer      */
-                                    pScratch,                          /* Stereo source         */
-                                    pMono,                             /* Mono band pass source */
-                                    pScratch,                          /* Stereo destination    */
-                                    NumSamples);                       /* Number of samples     */
-
-        /*
-         * Convert 32-bit samples to 16-bit and saturate
-         * (Not required for 16-bit implemenations)
-         */
-        Int32RShiftToInt16_Sat_32x16(pScratch,                         /* Source 32-bit data    */
-                                     (LVM_INT16 *)pScratch,            /* Dest. 16-bit data     */
-                                     (LVM_INT16)(2*NumSamples),        /* Left and right        */
-                                     LVDBE_SCALESHIFT);                /* Shift scale           */
-
-    }
-
-    /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
-    if ((pInstance->Params.OperatingMode == LVDBE_OFF)||
-        (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1])
-         !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1])))
-    {
-
-        /*
-         * The algorithm is disabled but volume management is required to compensate for
-         * headroom and volume (if enabled)
-         */
-        LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
-                                  pInData,
-                                  pScratchVol,
-                               (LVM_INT16)(2*NumSamples));           /* Left and right          */
-
-    }
+    From2iToMono_Float((LVM_FLOAT *)pScratch, /* Stereo source         */
+        pMono, /* Mono destination      */
+        (LVM_INT16)NumSamples); /* Number of samples     */
 
     /*
-     * Mix DBE processed path and bypass volume path
+     * Apply the band pass filter
      */
-    LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
-                                    (LVM_INT16 *) pScratch,
-                                    pScratchVol,
-                                    pOutData,
-                                    (LVM_INT16)(2*NumSamples));
+    BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance       */
+        (LVM_FLOAT *)pMono, /* Source                */
+        (LVM_FLOAT *)pMono, /* Destination           */
+        (LVM_INT16)NumSamples); /* Number of samples     */
 
-    return(LVDBE_SUCCESS);
+    /*
+     * Apply the AGC and mix
+     */
+    AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer      */
+        pScratch, /* Stereo source         */
+        pMono, /* Mono band pass source */
+        pScratch, /* Stereo destination    */
+        NumSamples); /* Number of samples     */
+
+    for (ii = 0; ii < 2 * NumSamples; ii++) {
+      //TODO: replace with existing clamping function
+      if(pScratch[ii] < -1.0) {
+        pScratch[ii] = -1.0;
+      } else if(pScratch[ii] > 1.0) {
+        pScratch[ii] = 1.0;
+      }
+    }
+  }
+
+  /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
+  if ((pInstance->Params.OperatingMode == LVDBE_OFF)||
+      (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1])
+          !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1])))
+  {
+
+    /*
+     * The algorithm is disabled but volume management is required to compensate for
+     * headroom and volume (if enabled)
+     */
+    LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
+        pScratch_in,
+        pScratchVol,
+        (LVM_INT16)(2 * NumSamples)); /* Left and right */
+  }
+
+  /*
+   * Mix DBE processed path and bypass volume path
+   */
+  LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
+      pScratch,
+      pScratchVol,
+      pOutData,
+      (LVM_INT16)(2 * NumSamples));
+
+  return(LVDBE_SUCCESS);
 }
-
-
-
-
-
-
-
-
-
-
+#endif
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
index f5d229e..c4a9b14 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
@@ -36,7 +36,11 @@
 /*
  * High Pass Filter Coefficient table
  */
+#ifndef BUILD_FLOAT
 const BQ_C32_Coefs_t LVDBE_HPF_Table[] = {
+#else /*BUILD_FLOAT*/
+const BQ_FLOAT_Coefs_t LVDBE_HPF_Table[] = {
+#endif /*BUILD_FLOAT*/
     /* Coefficients for 55Hz centre frequency */
     {HPF_Fs8000_Fc55_A2,                /* 8kS/s coefficients */
      HPF_Fs8000_Fc55_A1,
@@ -83,6 +87,18 @@
      HPF_Fs48000_Fc55_A0,
      -HPF_Fs48000_Fc55_B2,
      -HPF_Fs48000_Fc55_B1},
+#ifdef HIGHER_FS
+    {HPF_Fs96000_Fc55_A2,                /* 96kS/s coefficients */
+     HPF_Fs96000_Fc55_A1,
+     HPF_Fs96000_Fc55_A0,
+     -HPF_Fs96000_Fc55_B2,
+     -HPF_Fs96000_Fc55_B1},
+    {HPF_Fs192000_Fc55_A2,                /* 192kS/s coefficients */
+     HPF_Fs192000_Fc55_A1,
+     HPF_Fs192000_Fc55_A0,
+     -HPF_Fs192000_Fc55_B2,
+     -HPF_Fs192000_Fc55_B1},
+#endif
 
     /* Coefficients for 66Hz centre frequency */
     {HPF_Fs8000_Fc66_A2,                /* 8kS/s coefficients */
@@ -130,6 +146,19 @@
      HPF_Fs48000_Fc66_A0,
      -HPF_Fs48000_Fc66_B2,
      -HPF_Fs48000_Fc66_B1},
+#ifdef HIGHER_FS
+    {HPF_Fs96000_Fc66_A2,                /* 96kS/s coefficients */
+     HPF_Fs96000_Fc66_A1,
+     HPF_Fs96000_Fc66_A0,
+     -HPF_Fs96000_Fc66_B2,
+     -HPF_Fs96000_Fc66_B1},
+    {HPF_Fs192000_Fc66_A2,                /* 192kS/s coefficients */
+     HPF_Fs192000_Fc66_A1,
+     HPF_Fs192000_Fc66_A0,
+     -HPF_Fs192000_Fc66_B2,
+     -HPF_Fs192000_Fc66_B1},
+#endif
+
 
     /* Coefficients for 78Hz centre frequency */
     {HPF_Fs8000_Fc78_A2,                /* 8kS/s coefficients */
@@ -177,6 +206,19 @@
      HPF_Fs48000_Fc78_A0,
      -HPF_Fs48000_Fc78_B2,
      -HPF_Fs48000_Fc78_B1},
+#ifdef HIGHER_FS
+    {HPF_Fs96000_Fc78_A2,                /* 96kS/s coefficients */
+     HPF_Fs96000_Fc78_A1,
+     HPF_Fs96000_Fc78_A0,
+     -HPF_Fs96000_Fc78_B2,
+     -HPF_Fs96000_Fc78_B1},
+    {HPF_Fs192000_Fc78_A2,                /* 192kS/s coefficients */
+     HPF_Fs192000_Fc78_A1,
+     HPF_Fs192000_Fc78_A0,
+     -HPF_Fs192000_Fc78_B2,
+     -HPF_Fs192000_Fc78_B1},
+#endif
+
 
     /* Coefficients for 90Hz centre frequency */
     {HPF_Fs8000_Fc90_A2,                /* 8kS/s coefficients */
@@ -223,12 +265,32 @@
      HPF_Fs48000_Fc90_A1,
      HPF_Fs48000_Fc90_A0,
      -HPF_Fs48000_Fc90_B2,
-     -HPF_Fs48000_Fc90_B1}};
+     -HPF_Fs48000_Fc90_B1}
+
+#ifdef HIGHER_FS
+    ,
+    {HPF_Fs96000_Fc90_A2,                /* 96kS/s coefficients */
+     HPF_Fs96000_Fc90_A1,
+     HPF_Fs96000_Fc90_A0,
+     -HPF_Fs96000_Fc90_B2,
+     -HPF_Fs96000_Fc90_B1},
+    {HPF_Fs192000_Fc90_A2,                /* 192kS/s coefficients */
+     HPF_Fs192000_Fc90_A1,
+     HPF_Fs192000_Fc90_A0,
+     -HPF_Fs192000_Fc90_B2,
+     -HPF_Fs192000_Fc90_B1}
+#endif
+
+};
 
 /*
  * Band Pass Filter coefficient table
  */
+#ifndef BUILD_FLOAT
 const BP_C32_Coefs_t LVDBE_BPF_Table[] = {
+#else /*BUILD_FLOAT*/
+const BP_FLOAT_Coefs_t LVDBE_BPF_Table[] = {
+#endif /*BUILD_FLOAT*/
     /* Coefficients for 55Hz centre frequency */
     {BPF_Fs8000_Fc55_A0,                /* 8kS/s coefficients */
      -BPF_Fs8000_Fc55_B2,
@@ -257,6 +319,14 @@
     {BPF_Fs48000_Fc55_A0,                /* 48kS/s coefficients */
      -BPF_Fs48000_Fc55_B2,
      -BPF_Fs48000_Fc55_B1},
+#ifdef HIGHER_FS
+     {BPF_Fs96000_Fc55_A0,                /* 96kS/s coefficients */
+     -BPF_Fs96000_Fc55_B2,
+     -BPF_Fs96000_Fc55_B1},
+     {BPF_Fs192000_Fc55_A0,                /* 192kS/s coefficients */
+     -BPF_Fs192000_Fc55_B2,
+     -BPF_Fs192000_Fc55_B1},
+#endif
 
     /* Coefficients for 66Hz centre frequency */
     {BPF_Fs8000_Fc66_A0,                /* 8kS/s coefficients */
@@ -286,6 +356,14 @@
     {BPF_Fs48000_Fc66_A0,                /* 48kS/s coefficients */
      -BPF_Fs48000_Fc66_B2,
      -BPF_Fs48000_Fc66_B1},
+#ifdef HIGHER_FS
+    {BPF_Fs96000_Fc66_A0,                /* 96kS/s coefficients */
+     -BPF_Fs96000_Fc66_B2,
+     -BPF_Fs96000_Fc66_B1},
+    {BPF_Fs192000_Fc66_A0,                /* 192kS/s coefficients */
+     -BPF_Fs192000_Fc66_B2,
+     -BPF_Fs192000_Fc66_B1},
+#endif
 
     /* Coefficients for 78Hz centre frequency */
     {BPF_Fs8000_Fc78_A0,                /* 8kS/s coefficients */
@@ -315,6 +393,14 @@
     {BPF_Fs48000_Fc78_A0,                /* 48kS/s coefficients */
      -BPF_Fs48000_Fc78_B2,
      -BPF_Fs48000_Fc78_B1},
+#ifdef HIGHER_FS
+    {BPF_Fs96000_Fc78_A0,                /* 96kS/s coefficients */
+     -BPF_Fs96000_Fc78_B2,
+     -BPF_Fs96000_Fc78_B1},
+    {BPF_Fs192000_Fc78_A0,                /* 192kS/s coefficients */
+     -BPF_Fs192000_Fc78_B2,
+     -BPF_Fs192000_Fc78_B1},
+#endif
 
     /* Coefficients for 90Hz centre frequency */
     {BPF_Fs8000_Fc90_A0,                /* 8kS/s coefficients */
@@ -343,7 +429,19 @@
      -BPF_Fs44100_Fc90_B1},
     {BPF_Fs48000_Fc90_A0,                /* 48kS/s coefficients */
      -BPF_Fs48000_Fc90_B2,
-     -BPF_Fs48000_Fc90_B1}};
+     -BPF_Fs48000_Fc90_B1}
+#ifdef HIGHER_FS
+    ,
+    {BPF_Fs96000_Fc90_A0,                /* 96kS/s coefficients */
+     -BPF_Fs96000_Fc90_B2,
+     -BPF_Fs96000_Fc90_B1},
+    {BPF_Fs192000_Fc90_A0,                /* 192kS/s coefficients */
+     -BPF_Fs192000_Fc90_B2,
+     -BPF_Fs192000_Fc90_B1}
+#endif
+
+
+};
 
 
 /************************************************************************************/
@@ -353,7 +451,11 @@
 /************************************************************************************/
 
 /* Attack time (signal too large) */
+#ifndef BUILD_FLOAT
 const LVM_INT16 LVDBE_AGC_ATTACK_Table[] = {
+#else /*BUILD_FLOAT*/
+const LVM_FLOAT LVDBE_AGC_ATTACK_Table[] = {
+#endif /*BUILD_FLOAT*/
     AGC_ATTACK_Fs8000,
     AGC_ATTACK_Fs11025,
     AGC_ATTACK_Fs12000,
@@ -362,10 +464,20 @@
     AGC_ATTACK_Fs24000,
     AGC_ATTACK_Fs32000,
     AGC_ATTACK_Fs44100,
-    AGC_ATTACK_Fs48000};
+    AGC_ATTACK_Fs48000
+#ifdef HIGHER_FS
+    ,AGC_ATTACK_Fs96000
+    ,AGC_ATTACK_Fs192000
+#endif
+
+};
 
 /* Decay time (signal too small) */
+#ifndef BUILD_FLOAT
 const LVM_INT16 LVDBE_AGC_DECAY_Table[] = {
+#else /*BUILD_FLOAT*/
+const LVM_FLOAT LVDBE_AGC_DECAY_Table[] = {
+#endif /*BUILD_FLOAT*/
     AGC_DECAY_Fs8000,
     AGC_DECAY_Fs11025,
     AGC_DECAY_Fs12000,
@@ -374,10 +486,20 @@
     AGC_DECAY_Fs24000,
     AGC_DECAY_Fs32000,
     AGC_DECAY_Fs44100,
-    AGC_DECAY_Fs48000};
+    AGC_DECAY_Fs48000
+#ifdef HIGHER_FS
+    ,AGC_DECAY_FS96000
+    ,AGC_DECAY_FS192000
+#endif
+
+};
 
 /* Gain for use without the high pass filter */
+#ifndef BUILD_FLOAT
 const LVM_INT32 LVDBE_AGC_GAIN_Table[] = {
+#else /*BUILD_FLOAT*/
+const LVM_FLOAT LVDBE_AGC_GAIN_Table[] = {
+#endif /*BUILD_FLOAT*/
     AGC_GAIN_0dB,
     AGC_GAIN_1dB,
     AGC_GAIN_2dB,
@@ -396,7 +518,11 @@
     AGC_GAIN_15dB};
 
 /* Gain for use with the high pass filter */
+#ifndef BUILD_FLOAT
 const LVM_INT32 LVDBE_AGC_HPFGAIN_Table[] = {
+#else /*BUILD_FLOAT*/
+const LVM_FLOAT LVDBE_AGC_HPFGAIN_Table[] = {
+#endif /*BUILD_FLOAT*/
     AGC_HPFGAIN_0dB,
     AGC_HPFGAIN_1dB,
     AGC_HPFGAIN_2dB,
@@ -422,6 +548,7 @@
 /************************************************************************************/
 
 /* dB to linear conversion table */
+#ifndef BUILD_FLOAT
 const LVM_INT16 LVDBE_VolumeTable[] = {
     0x4000,             /* -6dB */
     0x47FB,             /* -5dB */
@@ -430,8 +557,22 @@
     0x65AD,             /* -2dB */
     0x7215,             /* -1dB */
     0x7FFF};            /*  0dB */
+#else /*BUILD_FLOAT*/
+const LVM_FLOAT LVDBE_VolumeTable[] = {
+    0.500000f,         /* -6dB */
+    0.562341f,         /* -5dB */
+    0.630957f,         /* -4dB */
+    0.707946f,         /* -3dB */
+    0.794328f,         /* -2dB */
+    0.891251f,         /* -1dB */
+    1.000000f};        /*  0dB */
+#endif /*BUILD_FLOAT*/
 
+#ifndef BUILD_FLOAT
 const LVM_INT16 LVDBE_VolumeTCTable[] = {
+#else /*BUILD_FLOAT*/
+const LVM_FLOAT LVDBE_VolumeTCTable[] = {
+#endif /*BUILD_FLOAT*/
     VOL_TC_Fs8000,
     VOL_TC_Fs11025,
     VOL_TC_Fs12000,
@@ -440,9 +581,17 @@
     VOL_TC_Fs24000,
     VOL_TC_Fs32000,
     VOL_TC_Fs44100,
-    VOL_TC_Fs48000};
+    VOL_TC_Fs48000
+#ifdef HIGHER_FS
+    ,VOL_TC_Fs96000
+    ,VOL_TC_Fs192000
+#endif
+};
+
+
 
 const LVM_INT16 LVDBE_MixerTCTable[] = {
+
     MIX_TC_Fs8000,
     MIX_TC_Fs11025,
     MIX_TC_Fs12000,
@@ -451,6 +600,10 @@
     MIX_TC_Fs24000,
     MIX_TC_Fs32000,
     MIX_TC_Fs44100,
-    MIX_TC_Fs48000};
+    MIX_TC_Fs48000
+#ifdef HIGHER_FS
+    ,MIX_TC_Fs96000
+    ,MIX_TC_Fs192000
+#endif
 
-
+};
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
index 476e6a0..ca46e37 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
@@ -31,6 +31,7 @@
 #include "BIQUAD.h"
 #include "LVM_Types.h"
 
+#ifndef BUILD_FLOAT
 /************************************************************************************/
 /*                                                                                  */
 /*    Coefficients constant table                                                   */
@@ -76,8 +77,57 @@
 
 extern const LVM_INT16 LVDBE_VolumeTCTable[];
 
+#else /*BUILD_FLOAT*/
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Coefficients constant table                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * High Pass Filter Coefficient table
+ */
+extern const BQ_FLOAT_Coefs_t LVDBE_HPF_Table[];
+
+/*
+ * Band Pass Filter coefficient table
+ */
+extern const BP_FLOAT_Coefs_t LVDBE_BPF_Table[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*    AGC constant tables                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Attack time (signal too large) */
+extern const LVM_FLOAT LVDBE_AGC_ATTACK_Table[];
+
+/* Decay time (signal too small) */
+extern const LVM_FLOAT LVDBE_AGC_DECAY_Table[];
+
+/* Gain for use without the high pass filter */
+extern const LVM_FLOAT LVDBE_AGC_GAIN_Table[];
+
+/* Gain for use with the high pass filter */
+extern const LVM_FLOAT LVDBE_AGC_HPFGAIN_Table[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Volume control gain and time constant tables                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/* dB to linear conversion table */
+extern const LVM_FLOAT LVDBE_VolumeTable[];
+extern const LVM_FLOAT LVDBE_VolumeTCTable[];
+
+#endif /*BUILD_FLOAT*/
+
 extern const LVM_INT16 LVDBE_MixerTCTable[];
 
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/Bundle/lib/LVM.h b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
index 1ff2a2c..9b6da31 100644
--- a/media/libeffects/lvm/lib/Bundle/lib/LVM.h
+++ b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
@@ -514,11 +514,19 @@
 /*      STEREO              the number of sample pairs in the block                     */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
+                                const LVM_FLOAT             *pInData,
+                                LVM_FLOAT                      *pOutData,
+                                LVM_UINT16                  NumSamples,
+                                LVM_UINT32                  AudioTime);
+#else
 LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
                                 const LVM_INT16             *pInData,
                                 LVM_INT16                   *pOutData,
                                 LVM_UINT16                  NumSamples,
                                 LVM_UINT32                  AudioTime);
+#endif
 
 
 /****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
index 6cbee7d..0a3c30e 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
@@ -48,7 +48,152 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
+                         const LVM_FLOAT    *pInData,
+                         LVM_FLOAT          **pToProcess,
+                         LVM_FLOAT          **pProcessed,
+                         LVM_UINT16         *pNumSamples)
+{
 
+    LVM_INT16        SampleCount;           /* Number of samples to be processed this call */
+    LVM_INT16        NumSamples;            /* Number of samples in scratch buffer */
+    LVM_FLOAT        *pStart;
+    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
+    LVM_Buffer_t     *pBuffer;
+    LVM_FLOAT        *pDest;
+    LVM_INT16        NumChannels = 2;
+
+
+    /*
+     * Set the processing address pointers
+     */
+    pBuffer     = pInstance->pBufferManagement;
+    pDest       = pBuffer->pScratch;
+    *pToProcess = pBuffer->pScratch;
+    *pProcessed = pBuffer->pScratch;
+
+    /*
+     * Check if it is the first call of a block
+     */
+    if (pInstance->SamplesToProcess == 0)
+    {
+        /*
+         * First call for a new block of samples
+         */
+        pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
+        pInstance->pInputSamples    = (LVM_FLOAT *)pInData;
+        pBuffer->BufferState        = LVM_FIRSTCALL;
+    }
+    pStart = pInstance->pInputSamples;                 /* Pointer to the input samples */
+    pBuffer->SamplesToOutput  = 0;                     /* Samples to output is same as
+                                                          number read for inplace processing */
+
+
+    /*
+     * Calculate the number of samples to process this call and update the buffer state
+     */
+    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+    {
+        /*
+         * Process the maximum bock size of samples.
+         */
+        SampleCount = pInstance->InternalBlockSize;
+        NumSamples  = pInstance->InternalBlockSize;
+    }
+    else
+    {
+        /*
+         * Last call for the block, so calculate how many frames and samples to process
+          */
+        LVM_INT16   NumFrames;
+
+        NumSamples  = pInstance->SamplesToProcess;
+        NumFrames    = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+        SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+
+        /*
+         * Update the buffer state
+         */
+        if (pBuffer->BufferState == LVM_FIRSTCALL)
+        {
+            pBuffer->BufferState = LVM_FIRSTLASTCALL;
+        }
+        else
+        {
+            pBuffer->BufferState = LVM_LASTCALL;
+        }
+    }
+    *pNumSamples = (LVM_UINT16)SampleCount;  /* Set the number of samples to process this call */
+
+
+    /*
+     * Copy samples from the delay buffer as required
+     */
+    if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
+        (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
+        (pBuffer->InDelaySamples != 0))
+    {
+        Copy_Float(&pBuffer->InDelayBuffer[0],                             /* Source */
+                   pDest,                                                  /* Destination */
+                   (LVM_INT16)(NumChannels * pBuffer->InDelaySamples));    /* Number of delay \
+                                                                       samples, left and right */
+        NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
+        pDest += NumChannels * pBuffer->InDelaySamples;      /* Update the destination pointer */
+    }
+
+
+    /*
+     * Copy the rest of the samples for this call from the input buffer
+     */
+    if (NumSamples > 0)
+    {
+        Copy_Float(pStart,                                      /* Source */
+                   pDest,                                       /* Destination */
+                   (LVM_INT16)(NumChannels * NumSamples));      /* Number of input samples */
+        pStart += NumChannels * NumSamples;                     /* Update the input pointer */
+
+        /*
+         * Update the input data pointer and samples to output
+         */
+        /* Update samples to output */
+        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples);
+    }
+
+
+    /*
+      * Update the sample count and input pointer
+     */
+    /* Update the count of samples */
+    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);
+    pInstance->pInputSamples     = pStart; /* Update input sample pointer */
+
+
+    /*
+     * Save samples to the delay buffer if any left unprocessed
+     */
+    if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
+        (pBuffer->BufferState == LVM_LASTCALL))
+    {
+        NumSamples = pInstance->SamplesToProcess;
+        pStart     = pBuffer->pScratch;                             /* Start of the buffer */
+        pStart    += NumChannels * SampleCount; /* Offset by the number of processed samples */
+        if (NumSamples != 0)
+        {
+            Copy_Float(pStart,                                         /* Source */
+                       &pBuffer->InDelayBuffer[0],                     /* Destination */
+                       (LVM_INT16)(NumChannels * NumSamples));   /* Number of input samples */
+        }
+
+
+        /*
+         * Update the delay sample count
+         */
+        pBuffer->InDelaySamples     = NumSamples;       /* Number of delay sample pairs */
+        pInstance->SamplesToProcess = 0;                            /* All Samples used */
+    }
+}
+#else
 void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
                          const LVM_INT16    *pInData,
                          LVM_INT16          **pToProcess,
@@ -189,7 +334,7 @@
         pInstance->SamplesToProcess = 0;                            /* All Samples used */
     }
 }
-
+#endif
 
 /****************************************************************************************/
 /*                                                                                      */
@@ -213,7 +358,47 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
+                           LVM_FLOAT        **pToProcess,
+                           LVM_FLOAT        **pProcessed,
+                           LVM_UINT16       *pNumSamples)
+{
 
+    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
+
+
+    /*
+     * Check if this is the first call of a block
+     */
+    if (pInstance->SamplesToProcess == 0)
+    {
+        pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;    /* Get the number of samples
+                                                                               on first call */
+        pInstance->pInputSamples    = *pToProcess;                /* Get the I/O pointers */
+        pInstance->pOutputSamples    = *pProcessed;
+
+
+        /*
+         * Set te block size to process
+         */
+        if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+        {
+            *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
+        }
+        else
+        {
+            *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+        }
+    }
+
+    /*
+     * Set the process pointers
+     */
+    *pToProcess = pInstance->pInputSamples;
+    *pProcessed = pInstance->pOutputSamples;
+}
+#else
 void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
                            LVM_INT16        **pToProcess,
                            LVM_INT16        **pProcessed,
@@ -252,7 +437,7 @@
     *pToProcess = pInstance->pInputSamples;
     *pProcessed = pInstance->pOutputSamples;
 }
-
+#endif
 
 /****************************************************************************************/
 /*                                                                                      */
@@ -278,6 +463,7 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifndef BUILD_FLOAT
 void LVM_BufferOptimisedIn(LVM_Handle_t         hInstance,
                            const LVM_INT16      *pInData,
                            LVM_INT16            **pToProcess,
@@ -416,7 +602,7 @@
         }
     }
 }
-
+#endif
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                 LVM_BufferIn                                               */
@@ -471,7 +657,37 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+void LVM_BufferIn(LVM_Handle_t      hInstance,
+                  const LVM_FLOAT   *pInData,
+                  LVM_FLOAT         **pToProcess,
+                  LVM_FLOAT         **pProcessed,
+                  LVM_UINT16        *pNumSamples)
+{
 
+    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
+
+
+    /*
+     * Check which mode, managed or unmanaged
+     */
+    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        LVM_BufferManagedIn(hInstance,
+                            pInData,
+                            pToProcess,
+                            pProcessed,
+                            pNumSamples);
+    }
+    else
+    {
+        LVM_BufferUnmanagedIn(hInstance,
+                              pToProcess,
+                              pProcessed,
+                              pNumSamples);
+    }
+}
+#else
 void LVM_BufferIn(LVM_Handle_t      hInstance,
                   const LVM_INT16   *pInData,
                   LVM_INT16         **pToProcess,
@@ -501,7 +717,7 @@
                               pNumSamples);
     }
 }
-
+#endif
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                 LVM_BufferManagedOut                                       */
@@ -522,7 +738,156 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
+                          LVM_FLOAT            *pOutData,
+                          LVM_UINT16        *pNumSamples)
+{
 
+    LVM_Instance_t  *pInstance  = (LVM_Instance_t  *)hInstance;
+    LVM_Buffer_t    *pBuffer    = pInstance->pBufferManagement;
+    LVM_INT16       SampleCount = (LVM_INT16)*pNumSamples;
+    LVM_INT16       NumSamples;
+    LVM_FLOAT       *pStart;
+    LVM_FLOAT       *pDest;
+
+
+    /*
+     * Set the pointers
+     */
+    NumSamples = pBuffer->SamplesToOutput;
+    pStart     = pBuffer->pScratch;
+
+
+    /*
+     * check if it is the first call of a block
+      */
+    if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
+        (pBuffer->BufferState == LVM_FIRSTLASTCALL))
+    {
+        /* First call for a new block */
+        pInstance->pOutputSamples = pOutData;                 /* Initialise the destination */
+    }
+    pDest = pInstance->pOutputSamples;                        /* Set the output address */
+
+
+    /*
+     * If the number of samples is non-zero then there are still samples to send to
+     * the output buffer
+     */
+    if ((NumSamples != 0) &&
+        (pBuffer->OutDelaySamples != 0))
+    {
+        /*
+         * Copy the delayed output buffer samples to the output
+         */
+        if (pBuffer->OutDelaySamples <= NumSamples)
+        {
+            /*
+             * Copy all output delay samples to the output
+             */
+            Copy_Float(&pBuffer->OutDelayBuffer[0],                /* Source */
+                       pDest,                                      /* Detsination */
+                       (LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of delay samples */
+
+            /*
+             * Update the pointer and sample counts
+             */
+            pDest += 2 * pBuffer->OutDelaySamples; /* Output sample pointer */
+            NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples); /* Samples left \
+                                                                                to send */
+            pBuffer->OutDelaySamples = 0; /* No samples left in the buffer */
+        }
+        else
+        {
+            /*
+             * Copy only some of the ouput delay samples to the output
+             */
+            Copy_Float(&pBuffer->OutDelayBuffer[0],                    /* Source */
+                       pDest,                                          /* Detsination */
+                       (LVM_INT16)(2 * NumSamples));       /* Number of delay samples */
+
+            /*
+             * Update the pointer and sample counts
+             */
+            pDest += 2 * NumSamples; /* Output sample pointer */
+            /* No samples left in the buffer */
+            pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);
+
+            /*
+             * Realign the delay buffer data to avoid using circular buffer management
+             */
+            Copy_Float(&pBuffer->OutDelayBuffer[2 * NumSamples],         /* Source */
+                       &pBuffer->OutDelayBuffer[0],                    /* Destination */
+                       (LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of samples to move */
+            NumSamples = 0;                                /* Samples left to send */
+        }
+    }
+
+
+    /*
+     * Copy the processed results to the output
+     */
+    if ((NumSamples != 0) &&
+        (SampleCount != 0))
+    {
+        if (SampleCount <= NumSamples)
+        {
+            /*
+             * Copy all processed samples to the output
+             */
+            Copy_Float(pStart,                                      /* Source */
+                       pDest,                                       /* Detsination */
+                       (LVM_INT16)(2 * SampleCount)); /* Number of processed samples */
+            /*
+             * Update the pointer and sample counts
+             */
+            pDest      += 2 * SampleCount;                          /* Output sample pointer */
+            NumSamples  = (LVM_INT16)(NumSamples - SampleCount);    /* Samples left to send */
+            SampleCount = 0; /* No samples left in the buffer */
+        }
+        else
+        {
+            /*
+             * Copy only some processed samples to the output
+             */
+            Copy_Float(pStart,                                         /* Source */
+                       pDest,                                          /* Destination */
+                       (LVM_INT16)(2 * NumSamples));     /* Number of processed samples */
+            /*
+             * Update the pointers and sample counts
+               */
+            pStart      += 2 * NumSamples;                        /* Processed sample pointer */
+            pDest       += 2 * NumSamples;                        /* Output sample pointer */
+            SampleCount  = (LVM_INT16)(SampleCount - NumSamples); /* Processed samples left */
+            NumSamples   = 0;                                     /* Clear the sample count */
+        }
+    }
+
+
+    /*
+     * Copy the remaining processed data to the output delay buffer
+     */
+    if (SampleCount != 0)
+    {
+        Copy_Float(pStart,                                                 /* Source */
+                   &pBuffer->OutDelayBuffer[2 * pBuffer->OutDelaySamples], /* Destination */
+                   (LVM_INT16)(2 * SampleCount));               /* Number of processed samples */
+        /* Update the buffer count */
+        pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount);
+    }
+
+    /*
+     * pointers, counts and set default buffer processing
+     */
+    pBuffer->SamplesToOutput  = NumSamples;                         /* Samples left to send */
+    pInstance->pOutputSamples = pDest;                              /* Output sample pointer */
+    pBuffer->BufferState      = LVM_MAXBLOCKCALL;                   /* Set for the default call \
+                                                                            block size */
+    /* This will terminate the loop when all samples processed */
+    *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+}
+#else
 void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
                           LVM_INT16            *pOutData,
                           LVM_UINT16        *pNumSamples)
@@ -672,7 +1037,7 @@
     pBuffer->BufferState      = LVM_MAXBLOCKCALL;                   /* Set for the default call block size */
     *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;         /* This will terminate the loop when all samples processed */
 }
-
+#endif
 
 /****************************************************************************************/
 /*                                                                                      */
@@ -741,6 +1106,7 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifndef BUILD_FLOAT
 void LVM_BufferOptimisedOut(LVM_Handle_t    hInstance,
                             LVM_UINT16        *pNumSamples)
 {
@@ -805,7 +1171,7 @@
         }
     }
 }
-
+#endif
 
 /****************************************************************************************/
 /*                                                                                      */
@@ -843,7 +1209,31 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+void LVM_BufferOut(LVM_Handle_t     hInstance,
+                   LVM_FLOAT        *pOutData,
+                   LVM_UINT16       *pNumSamples)
+{
 
+    LVM_Instance_t    *pInstance  = (LVM_Instance_t  *)hInstance;
+
+
+    /*
+     * Check which mode, managed or unmanaged
+     */
+    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        LVM_BufferManagedOut(hInstance,
+                             pOutData,
+                             pNumSamples);
+    }
+    else
+    {
+        LVM_BufferUnmanagedOut(hInstance,
+                               pNumSamples);
+    }
+}
+#else
 void LVM_BufferOut(LVM_Handle_t     hInstance,
                    LVM_INT16        *pOutData,
                    LVM_UINT16       *pNumSamples)
@@ -867,4 +1257,4 @@
                                pNumSamples);
     }
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
index 2712b2c..353560c 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
@@ -26,10 +26,655 @@
 /************************************************************************************/
 
 #define TrebleBoostCorner                                  8000
-#define TrebleBoostMinRate                                     4
-#define TrebleBoostSteps                                    15
+#define TrebleBoostMinRate                                    4
+#define TrebleBoostSteps                                     15
 
+#ifdef BUILD_FLOAT
+/* Coefficients for sample rate 22050Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs22050_Gain1_A0                            1.038434
+#define HPF_Fs22050_Gain1_A1                            0.331599
+#define HPF_Fs22050_Gain1_A2                            0.000000
+#define HPF_Fs22050_Gain1_B1                            0.370033
+#define HPF_Fs22050_Gain1_B2                            0.000000
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs22050_Gain2_A0                            1.081557
+#define HPF_Fs22050_Gain2_A1                            0.288475
+#define HPF_Fs22050_Gain2_A2                            0.000000
+#define HPF_Fs22050_Gain2_B1                            0.370033
+#define HPF_Fs22050_Gain2_B2                            0.000000
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs22050_Gain3_A0                            1.129943
+#define HPF_Fs22050_Gain3_A1                            0.240090
+#define HPF_Fs22050_Gain3_A2                            0.000000
+#define HPF_Fs22050_Gain3_B1                            0.370033
+#define HPF_Fs22050_Gain3_B2                            0.000000
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs22050_Gain4_A0                            1.184232
+#define HPF_Fs22050_Gain4_A1                            0.185801
+#define HPF_Fs22050_Gain4_A2                            0.000000
+#define HPF_Fs22050_Gain4_B1                            0.370033
+#define HPF_Fs22050_Gain4_B2                            0.000000
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs22050_Gain5_A0                            1.245145
+#define HPF_Fs22050_Gain5_A1                            0.124887
+#define HPF_Fs22050_Gain5_A2                            0.000000
+#define HPF_Fs22050_Gain5_B1                            0.370033
+#define HPF_Fs22050_Gain5_B2                            0.000000
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs22050_Gain6_A0                            1.313491
+#define HPF_Fs22050_Gain6_A1                            0.056541
+#define HPF_Fs22050_Gain6_A2                            0.000000
+#define HPF_Fs22050_Gain6_B1                            0.370033
+#define HPF_Fs22050_Gain6_B2                            0.000000
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs22050_Gain7_A0                            1.390177
+#define HPF_Fs22050_Gain7_A1                            -0.020144
+#define HPF_Fs22050_Gain7_A2                            0.000000
+#define HPF_Fs22050_Gain7_B1                            0.370033
+#define HPF_Fs22050_Gain7_B2                            0.000000
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs22050_Gain8_A0                            1.476219
+#define HPF_Fs22050_Gain8_A1                            -0.106187
+#define HPF_Fs22050_Gain8_A2                            0.000000
+#define HPF_Fs22050_Gain8_B1                            0.370033
+#define HPF_Fs22050_Gain8_B2                            0.000000
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs22050_Gain9_A0                            1.572761
+#define HPF_Fs22050_Gain9_A1                            -0.202728
+#define HPF_Fs22050_Gain9_A2                            0.000000
+#define HPF_Fs22050_Gain9_B1                            0.370033
+#define HPF_Fs22050_Gain9_B2                            0.000000
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs22050_Gain10_A0                           1.681082
+#define HPF_Fs22050_Gain10_A1                           -0.311049
+#define HPF_Fs22050_Gain10_A2                           0.000000
+#define HPF_Fs22050_Gain10_B1                           0.370033
+#define HPF_Fs22050_Gain10_B2                           0.000000
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs22050_Gain11_A0                           1.802620
+#define HPF_Fs22050_Gain11_A1                           -0.432588
+#define HPF_Fs22050_Gain11_A2                           0.000000
+#define HPF_Fs22050_Gain11_B1                           0.370033
+#define HPF_Fs22050_Gain11_B2                           0.000000
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs22050_Gain12_A0                           1.938989
+#define HPF_Fs22050_Gain12_A1                           -0.568956
+#define HPF_Fs22050_Gain12_A2                           0.000000
+#define HPF_Fs22050_Gain12_B1                           0.370033
+#define HPF_Fs22050_Gain12_B2                           0.000000
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs22050_Gain13_A0                           2.091997
+#define HPF_Fs22050_Gain13_A1                           -0.721964
+#define HPF_Fs22050_Gain13_A2                           0.000000
+#define HPF_Fs22050_Gain13_B1                           0.370033
+#define HPF_Fs22050_Gain13_B2                           0.000000
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs22050_Gain14_A0                           2.263674
+#define HPF_Fs22050_Gain14_A1                           -0.893641
+#define HPF_Fs22050_Gain14_A2                           0.000000
+#define HPF_Fs22050_Gain14_B1                           0.370033
+#define HPF_Fs22050_Gain14_B2                           0.000000
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs22050_Gain15_A0                           2.456300
+#define HPF_Fs22050_Gain15_A1                           -1.086267
+#define HPF_Fs22050_Gain15_A2                           0.000000
+#define HPF_Fs22050_Gain15_B1                           0.370033
+#define HPF_Fs22050_Gain15_B2                           0.000000
+/* Coefficients for sample rate 24000Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs24000_Gain1_A0                            1.044662
+#define HPF_Fs24000_Gain1_A1                            0.223287
+#define HPF_Fs24000_Gain1_A2                            0.000000
+#define HPF_Fs24000_Gain1_B1                            0.267949
+#define HPF_Fs24000_Gain1_B2                            0.000000
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs24000_Gain2_A0                            1.094773
+#define HPF_Fs24000_Gain2_A1                            0.173176
+#define HPF_Fs24000_Gain2_A2                            0.000000
+#define HPF_Fs24000_Gain2_B1                            0.267949
+#define HPF_Fs24000_Gain2_B2                            0.000000
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs24000_Gain3_A0                            1.150999
+#define HPF_Fs24000_Gain3_A1                            0.116950
+#define HPF_Fs24000_Gain3_A2                            0.000000
+#define HPF_Fs24000_Gain3_B1                            0.267949
+#define HPF_Fs24000_Gain3_B2                            0.000000
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs24000_Gain4_A0                            1.214086
+#define HPF_Fs24000_Gain4_A1                            0.053863
+#define HPF_Fs24000_Gain4_A2                            0.000000
+#define HPF_Fs24000_Gain4_B1                            0.267949
+#define HPF_Fs24000_Gain4_B2                            0.000000
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs24000_Gain5_A0                            1.284870
+#define HPF_Fs24000_Gain5_A1                            -0.016921
+#define HPF_Fs24000_Gain5_A2                            0.000000
+#define HPF_Fs24000_Gain5_B1                            0.267949
+#define HPF_Fs24000_Gain5_B2                            0.000000
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs24000_Gain6_A0                           1.364291
+#define HPF_Fs24000_Gain6_A1                           -0.096342
+#define HPF_Fs24000_Gain6_A2                           0.000000
+#define HPF_Fs24000_Gain6_B1                           0.267949
+#define HPF_Fs24000_Gain6_B2                           0.000000
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs24000_Gain7_A0                            1.453403
+#define HPF_Fs24000_Gain7_A1                            -0.185454
+#define HPF_Fs24000_Gain7_A2                            0.000000
+#define HPF_Fs24000_Gain7_B1                            0.267949
+#define HPF_Fs24000_Gain7_B2                            0.000000
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs24000_Gain8_A0                            1.553389
+#define HPF_Fs24000_Gain8_A1                            -0.285440
+#define HPF_Fs24000_Gain8_A2                            0.000000
+#define HPF_Fs24000_Gain8_B1                            0.267949
+#define HPF_Fs24000_Gain8_B2                            0.000000
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs24000_Gain9_A0                            1.665574
+#define HPF_Fs24000_Gain9_A1                            -0.397625
+#define HPF_Fs24000_Gain9_A2                            0.000000
+#define HPF_Fs24000_Gain9_B1                            0.267949
+#define HPF_Fs24000_Gain9_B2                            0.000000
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs24000_Gain10_A0                           1.791449
+#define HPF_Fs24000_Gain10_A1                           -0.523499
+#define HPF_Fs24000_Gain10_A2                           0.000000
+#define HPF_Fs24000_Gain10_B1                           0.267949
+#define HPF_Fs24000_Gain10_B2                           0.000000
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs24000_Gain11_A0                           1.932682
+#define HPF_Fs24000_Gain11_A1                           -0.664733
+#define HPF_Fs24000_Gain11_A2                           0.000000
+#define HPF_Fs24000_Gain11_B1                           0.267949
+#define HPF_Fs24000_Gain11_B2                           0.000000
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs24000_Gain12_A0                           2.091148
+#define HPF_Fs24000_Gain12_A1                           -0.823199
+#define HPF_Fs24000_Gain12_A2                           0.000000
+#define HPF_Fs24000_Gain12_B1                           0.267949
+#define HPF_Fs24000_Gain12_B2                           0.000000
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs24000_Gain13_A0                           2.268950
+#define HPF_Fs24000_Gain13_A1                           -1.001001
+#define HPF_Fs24000_Gain13_A2                           0.000000
+#define HPF_Fs24000_Gain13_B1                           0.267949
+#define HPF_Fs24000_Gain13_B2                           0.000000
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs24000_Gain14_A0                           2.468447
+#define HPF_Fs24000_Gain14_A1                           -1.200498
+#define HPF_Fs24000_Gain14_A2                           0.000000
+#define HPF_Fs24000_Gain14_B1                           0.267949
+#define HPF_Fs24000_Gain14_B2                           0.000000
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs24000_Gain15_A0                           2.692287
+#define HPF_Fs24000_Gain15_A1                           -1.424338
+#define HPF_Fs24000_Gain15_A2                           0.000000
+#define HPF_Fs24000_Gain15_B1                           0.267949
+#define HPF_Fs24000_Gain15_B2                           0.000000
+/* Coefficients for sample rate 32000Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs32000_Gain1_A0                            1.061009
+#define HPF_Fs32000_Gain1_A1                            -0.061009
+#define HPF_Fs32000_Gain1_A2                            0.000000
+#define HPF_Fs32000_Gain1_B1                            -0.000000
+#define HPF_Fs32000_Gain1_B2                            0.000000
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs32000_Gain2_A0                             1.129463
+#define HPF_Fs32000_Gain2_A1                             -0.129463
+#define HPF_Fs32000_Gain2_A2                             0.000000
+#define HPF_Fs32000_Gain2_B1                             -0.000000
+#define HPF_Fs32000_Gain2_B2                             0.000000
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs32000_Gain3_A0                             1.206267
+#define HPF_Fs32000_Gain3_A1                             -0.206267
+#define HPF_Fs32000_Gain3_A2                             0.000000
+#define HPF_Fs32000_Gain3_B1                             -0.000000
+#define HPF_Fs32000_Gain3_B2                             0.000000
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs32000_Gain4_A0                            1.292447
+#define HPF_Fs32000_Gain4_A1                            -0.292447
+#define HPF_Fs32000_Gain4_A2                            0.000000
+#define HPF_Fs32000_Gain4_B1                            -0.000000
+#define HPF_Fs32000_Gain4_B2                            0.000000
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs32000_Gain5_A0                            1.389140
+#define HPF_Fs32000_Gain5_A1                            -0.389140
+#define HPF_Fs32000_Gain5_A2                            0.000000
+#define HPF_Fs32000_Gain5_B1                            -0.000000
+#define HPF_Fs32000_Gain5_B2                            0.000000
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs32000_Gain6_A0                             1.497631
+#define HPF_Fs32000_Gain6_A1                             -0.497631
+#define HPF_Fs32000_Gain6_A2                             0.000000
+#define HPF_Fs32000_Gain6_B1                             -0.000000
+#define HPF_Fs32000_Gain6_B2                             0.000000
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs32000_Gain7_A0                             1.619361
+#define HPF_Fs32000_Gain7_A1                             -0.619361
+#define HPF_Fs32000_Gain7_A2                             0.000000
+#define HPF_Fs32000_Gain7_B1                             -0.000000
+#define HPF_Fs32000_Gain7_B2                             0.000000
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs32000_Gain8_A0                             1.755943
+#define HPF_Fs32000_Gain8_A1                             -0.755943
+#define HPF_Fs32000_Gain8_A2                             0.000000
+#define HPF_Fs32000_Gain8_B1                             -0.000000
+#define HPF_Fs32000_Gain8_B2                             0.000000
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs32000_Gain9_A0                             1.909191
+#define HPF_Fs32000_Gain9_A1                             -0.909191
+#define HPF_Fs32000_Gain9_A2                             0.000000
+#define HPF_Fs32000_Gain9_B1                             -0.000000
+#define HPF_Fs32000_Gain9_B2                             0.000000
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs32000_Gain10_A0                            2.081139
+#define HPF_Fs32000_Gain10_A1                            -1.081139
+#define HPF_Fs32000_Gain10_A2                            0.000000
+#define HPF_Fs32000_Gain10_B1                            -0.000000
+#define HPF_Fs32000_Gain10_B2                            0.000000
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs32000_Gain11_A0                           2.274067
+#define HPF_Fs32000_Gain11_A1                           -1.274067
+#define HPF_Fs32000_Gain11_A2                           0.000000
+#define HPF_Fs32000_Gain11_B1                           -0.000000
+#define HPF_Fs32000_Gain11_B2                           0.000000
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs32000_Gain12_A0                          2.490536
+#define HPF_Fs32000_Gain12_A1                          -1.490536
+#define HPF_Fs32000_Gain12_A2                          0.000000
+#define HPF_Fs32000_Gain12_B1                          -0.000000
+#define HPF_Fs32000_Gain12_B2                          0.000000
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs32000_Gain13_A0                           2.733418
+#define HPF_Fs32000_Gain13_A1                           -1.733418
+#define HPF_Fs32000_Gain13_A2                           0.000000
+#define HPF_Fs32000_Gain13_B1                           -0.000000
+#define HPF_Fs32000_Gain13_B2                           0.000000
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs32000_Gain14_A0                           3.005936
+#define HPF_Fs32000_Gain14_A1                           -2.005936
+#define HPF_Fs32000_Gain14_A2                           0.000000
+#define HPF_Fs32000_Gain14_B1                           -0.000000
+#define HPF_Fs32000_Gain14_B2                           0.000000
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs32000_Gain15_A0                          3.311707
+#define HPF_Fs32000_Gain15_A1                          -2.311707
+#define HPF_Fs32000_Gain15_A2                          0.000000
+#define HPF_Fs32000_Gain15_B1                          -0.000000
+#define HPF_Fs32000_Gain15_B2                          0.000000
+/* Coefficients for sample rate 44100Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs44100_Gain1_A0                            1.074364
+#define HPF_Fs44100_Gain1_A1                            -0.293257
+#define HPF_Fs44100_Gain1_A2                            0.000000
+#define HPF_Fs44100_Gain1_B1                            -0.218894
+#define HPF_Fs44100_Gain1_B2                            0.000000
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs44100_Gain2_A0                            1.157801
+#define HPF_Fs44100_Gain2_A1                            -0.376695
+#define HPF_Fs44100_Gain2_A2                            0.000000
+#define HPF_Fs44100_Gain2_B1                            -0.218894
+#define HPF_Fs44100_Gain2_B2                            0.000000
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs44100_Gain3_A0                           1.251420
+#define HPF_Fs44100_Gain3_A1                           -0.470313
+#define HPF_Fs44100_Gain3_A2                           0.000000
+#define HPF_Fs44100_Gain3_B1                           -0.218894
+#define HPF_Fs44100_Gain3_B2                           0.000000
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs44100_Gain4_A0                            1.356461
+#define HPF_Fs44100_Gain4_A1                            -0.575355
+#define HPF_Fs44100_Gain4_A2                            0.000000
+#define HPF_Fs44100_Gain4_B1                            -0.218894
+#define HPF_Fs44100_Gain4_B2                            0.000000
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs44100_Gain5_A0                            1.474320
+#define HPF_Fs44100_Gain5_A1                            -0.693213
+#define HPF_Fs44100_Gain5_A2                            0.000000
+#define HPF_Fs44100_Gain5_B1                            -0.218894
+#define HPF_Fs44100_Gain5_B2                            0.000000
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs44100_Gain6_A0                           1.606559
+#define HPF_Fs44100_Gain6_A1                           -0.825453
+#define HPF_Fs44100_Gain6_A2                           0.000000
+#define HPF_Fs44100_Gain6_B1                           -0.218894
+#define HPF_Fs44100_Gain6_B2                           0.000000
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs44100_Gain7_A0                           1.754935
+#define HPF_Fs44100_Gain7_A1                           -0.973828
+#define HPF_Fs44100_Gain7_A2                           0.000000
+#define HPF_Fs44100_Gain7_B1                           -0.218894
+#define HPF_Fs44100_Gain7_B2                           0.000000
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs44100_Gain8_A0                            1.921414
+#define HPF_Fs44100_Gain8_A1                            -1.140308
+#define HPF_Fs44100_Gain8_A2                            0.000000
+#define HPF_Fs44100_Gain8_B1                            -0.218894
+#define HPF_Fs44100_Gain8_B2                            0.000000
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs44100_Gain9_A0                            2.108208
+#define HPF_Fs44100_Gain9_A1                            -1.327101
+#define HPF_Fs44100_Gain9_A2                            0.000000
+#define HPF_Fs44100_Gain9_B1                            -0.218894
+#define HPF_Fs44100_Gain9_B2                            0.000000
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs44100_Gain10_A0                          2.317793
+#define HPF_Fs44100_Gain10_A1                          -1.536687
+#define HPF_Fs44100_Gain10_A2                          0.000000
+#define HPF_Fs44100_Gain10_B1                          -0.218894
+#define HPF_Fs44100_Gain10_B2                          0.000000
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs44100_Gain11_A0                          2.552952
+#define HPF_Fs44100_Gain11_A1                          -1.771846
+#define HPF_Fs44100_Gain11_A2                          0.000000
+#define HPF_Fs44100_Gain11_B1                          -0.218894
+#define HPF_Fs44100_Gain11_B2                          0.000000
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs44100_Gain12_A0                          2.816805
+#define HPF_Fs44100_Gain12_A1                          -2.035698
+#define HPF_Fs44100_Gain12_A2                          0.000000
+#define HPF_Fs44100_Gain12_B1                          -0.218894
+#define HPF_Fs44100_Gain12_B2                          0.000000
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs44100_Gain13_A0                           3.112852
+#define HPF_Fs44100_Gain13_A1                           -2.331746
+#define HPF_Fs44100_Gain13_A2                           0.000000
+#define HPF_Fs44100_Gain13_B1                           -0.218894
+#define HPF_Fs44100_Gain13_B2                           0.000000
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs44100_Gain14_A0                          3.445023
+#define HPF_Fs44100_Gain14_A1                          -2.663916
+#define HPF_Fs44100_Gain14_A2                          0.000000
+#define HPF_Fs44100_Gain14_B1                          -0.218894
+#define HPF_Fs44100_Gain14_B2                          0.000000
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs44100_Gain15_A0                          3.817724
+#define HPF_Fs44100_Gain15_A1                          -3.036618
+#define HPF_Fs44100_Gain15_A2                          0.000000
+#define HPF_Fs44100_Gain15_B1                          -0.218894
+#define HPF_Fs44100_Gain15_B2                          0.000000
+/* Coefficients for sample rate 48000Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs48000_Gain1_A0                          1.077357
+#define HPF_Fs48000_Gain1_A1                          -0.345306
+#define HPF_Fs48000_Gain1_A2                          0.000000
+#define HPF_Fs48000_Gain1_B1                          -0.267949
+#define HPF_Fs48000_Gain1_B2                          0.000000
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs48000_Gain2_A0                          1.164152
+#define HPF_Fs48000_Gain2_A1                          -0.432101
+#define HPF_Fs48000_Gain2_A2                          0.000000
+#define HPF_Fs48000_Gain2_B1                          -0.267949
+#define HPF_Fs48000_Gain2_B2                          0.000000
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs48000_Gain3_A0                          1.261538
+#define HPF_Fs48000_Gain3_A1                          -0.529488
+#define HPF_Fs48000_Gain3_A2                          0.000000
+#define HPF_Fs48000_Gain3_B1                          -0.267949
+#define HPF_Fs48000_Gain3_B2                          0.000000
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs48000_Gain4_A0                           1.370807
+#define HPF_Fs48000_Gain4_A1                           -0.638757
+#define HPF_Fs48000_Gain4_A2                           0.000000
+#define HPF_Fs48000_Gain4_B1                           -0.267949
+#define HPF_Fs48000_Gain4_B2                           0.000000
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs48000_Gain5_A0                           1.493409
+#define HPF_Fs48000_Gain5_A1                           -0.761359
+#define HPF_Fs48000_Gain5_A2                           0.000000
+#define HPF_Fs48000_Gain5_B1                           -0.267949
+#define HPF_Fs48000_Gain5_B2                           0.000000
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs48000_Gain6_A0                            1.630971
+#define HPF_Fs48000_Gain6_A1                            -0.898920
+#define HPF_Fs48000_Gain6_A2                            0.000000
+#define HPF_Fs48000_Gain6_B1                            -0.267949
+#define HPF_Fs48000_Gain6_B2                            0.000000
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs48000_Gain7_A0                            1.785318
+#define HPF_Fs48000_Gain7_A1                            -1.053267
+#define HPF_Fs48000_Gain7_A2                            0.000000
+#define HPF_Fs48000_Gain7_B1                            -0.267949
+#define HPF_Fs48000_Gain7_B2                            0.000000
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs48000_Gain8_A0                           1.958498
+#define HPF_Fs48000_Gain8_A1                           -1.226447
+#define HPF_Fs48000_Gain8_A2                           0.000000
+#define HPF_Fs48000_Gain8_B1                           -0.267949
+#define HPF_Fs48000_Gain8_B2                           0.000000
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs48000_Gain9_A0                          2.152809
+#define HPF_Fs48000_Gain9_A1                          -1.420758
+#define HPF_Fs48000_Gain9_A2                          0.000000
+#define HPF_Fs48000_Gain9_B1                          -0.267949
+#define HPF_Fs48000_Gain9_B2                          0.000000
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs48000_Gain10_A0                         2.370829
+#define HPF_Fs48000_Gain10_A1                         -1.638778
+#define HPF_Fs48000_Gain10_A2                         0.000000
+#define HPF_Fs48000_Gain10_B1                         -0.267949
+#define HPF_Fs48000_Gain10_B2                         0.000000
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs48000_Gain11_A0                          2.615452
+#define HPF_Fs48000_Gain11_A1                          -1.883401
+#define HPF_Fs48000_Gain11_A2                          0.000000
+#define HPF_Fs48000_Gain11_B1                          -0.267949
+#define HPF_Fs48000_Gain11_B2                          0.000000
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs48000_Gain12_A0                          2.889924
+#define HPF_Fs48000_Gain12_A1                          -2.157873
+#define HPF_Fs48000_Gain12_A2                          0.000000
+#define HPF_Fs48000_Gain12_B1                          -0.267949
+#define HPF_Fs48000_Gain12_B2                          0.000000
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs48000_Gain13_A0                           3.197886
+#define HPF_Fs48000_Gain13_A1                           -2.465835
+#define HPF_Fs48000_Gain13_A2                           0.000000
+#define HPF_Fs48000_Gain13_B1                           -0.267949
+#define HPF_Fs48000_Gain13_B2                           0.000000
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs48000_Gain14_A0                          3.543425
+#define HPF_Fs48000_Gain14_A1                          -2.811374
+#define HPF_Fs48000_Gain14_A2                          0.000000
+#define HPF_Fs48000_Gain14_B1                          -0.267949
+#define HPF_Fs48000_Gain14_B2                          0.000000
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs48000_Gain15_A0                         3.931127
+#define HPF_Fs48000_Gain15_A1                         -3.199076
+#define HPF_Fs48000_Gain15_A2                         0.000000
+#define HPF_Fs48000_Gain15_B1                         -0.267949
+#define HPF_Fs48000_Gain15_B2                         0.000000
 
+#ifdef HIGHER_FS
+
+/* Coefficients for sample rate 96000Hz */
+                                                                 /* Gain =  1.000000 dB */
+#define HPF_Fs96000_Gain1_A0                          1.096233
+#define HPF_Fs96000_Gain1_A1                          -0.673583
+#define HPF_Fs96000_Gain1_A2                          0.000000
+#define HPF_Fs96000_Gain1_B1                          -0.577350
+#define HPF_Fs96000_Gain1_B2                          0.000000
+                                                                 /* Gain =  2.000000 dB */
+#define HPF_Fs96000_Gain2_A0                          1.204208
+#define HPF_Fs96000_Gain2_A1                          -0.781558
+#define HPF_Fs96000_Gain2_A2                          0.000000
+#define HPF_Fs96000_Gain2_B1                          -0.577350
+#define HPF_Fs96000_Gain2_B2                          0.000000
+                                                                 /* Gain =  3.000000 dB */
+#define HPF_Fs96000_Gain3_A0                          1.325358
+#define HPF_Fs96000_Gain3_A1                          -0.902708
+#define HPF_Fs96000_Gain3_A2                          0.000000
+#define HPF_Fs96000_Gain3_B1                          -0.577350
+#define HPF_Fs96000_Gain3_B2                          0.000000
+                                                                 /* Gain =  4.000000 dB */
+#define HPF_Fs96000_Gain4_A0                           1.461291
+#define HPF_Fs96000_Gain4_A1                           -1.038641
+#define HPF_Fs96000_Gain4_A2                           0.000000
+#define HPF_Fs96000_Gain4_B1                           -0.577350
+#define HPF_Fs96000_Gain4_B2                           0.000000
+                                                                 /* Gain =  5.000000 dB */
+#define HPF_Fs96000_Gain5_A0                           1.613810
+#define HPF_Fs96000_Gain5_A1                           -1.191160
+#define HPF_Fs96000_Gain5_A2                           0.000000
+#define HPF_Fs96000_Gain5_B1                           -0.577350
+#define HPF_Fs96000_Gain5_B2                           0.000000
+                                                                 /* Gain =  6.000000 dB */
+#define HPF_Fs96000_Gain6_A0                            1.784939
+#define HPF_Fs96000_Gain6_A1                            -1.362289
+#define HPF_Fs96000_Gain6_A2                            0.000000
+#define HPF_Fs96000_Gain6_B1                            -0.577350
+#define HPF_Fs96000_Gain6_B2                            0.000000
+                                                                /* Gain =  7.000000 dB */
+#define HPF_Fs96000_Gain7_A0                            1.976949
+#define HPF_Fs96000_Gain7_A1                            -1.554299
+#define HPF_Fs96000_Gain7_A2                            0.000000
+#define HPF_Fs96000_Gain7_B1                            -0.577350
+#define HPF_Fs96000_Gain7_B2                            0.000000
+                                                                 /* Gain =  8.000000 dB */
+#define HPF_Fs96000_Gain8_A0                           2.192387
+#define HPF_Fs96000_Gain8_A1                           -1.769738
+#define HPF_Fs96000_Gain8_A2                           0.000000
+#define HPF_Fs96000_Gain8_B1                           -0.577350
+#define HPF_Fs96000_Gain8_B2                           0.000000
+                                                                /* Gain =  9.000000 dB */
+#define HPF_Fs96000_Gain9_A0                          2.434113
+#define HPF_Fs96000_Gain9_A1                          -2.011464
+#define HPF_Fs96000_Gain9_A2                          0.000000
+#define HPF_Fs96000_Gain9_B1                          -0.577350
+#define HPF_Fs96000_Gain9_B2                          0.000000
+                                                               /* Gain =  10.000000 dB */
+#define HPF_Fs96000_Gain10_A0                        2.705335
+#define HPF_Fs96000_Gain10_A1                        -2.282685
+#define HPF_Fs96000_Gain10_A2                         0.000000
+#define HPF_Fs96000_Gain10_B1                         -0.577350
+#define HPF_Fs96000_Gain10_B2                         0.000000
+                                                              /* Gain =  11.000000 dB */
+#define HPF_Fs96000_Gain11_A0                          3.009650
+#define HPF_Fs96000_Gain11_A1                          -2.587000
+#define HPF_Fs96000_Gain11_A2                          0.000000
+#define HPF_Fs96000_Gain11_B1                          -0.577350
+#define HPF_Fs96000_Gain11_B2                          0.000000
+                                                                  /* Gain =  12.000000 dB */
+#define HPF_Fs96000_Gain12_A0                          3.351097
+#define HPF_Fs96000_Gain12_A1                          -2.928447
+#define HPF_Fs96000_Gain12_A2                          0.000000
+#define HPF_Fs96000_Gain12_B1                          -0.577350
+#define HPF_Fs96000_Gain12_B2                          0.000000
+                                                                /* Gain =  13.000000 dB */
+#define HPF_Fs96000_Gain13_A0                           3.734207
+#define HPF_Fs96000_Gain13_A1                           -3.311558
+#define HPF_Fs96000_Gain13_A2                           0.000000
+#define HPF_Fs96000_Gain13_B1                           -0.577350
+#define HPF_Fs96000_Gain13_B2                           0.000000
+                                                                 /* Gain =  14.000000 dB */
+#define HPF_Fs96000_Gain14_A0                         4.164064
+#define HPF_Fs96000_Gain14_A1                         -3.741414
+#define HPF_Fs96000_Gain14_A2                          0.000000
+#define HPF_Fs96000_Gain14_B1                          -0.577350
+#define HPF_Fs96000_Gain14_B2                          0.000000
+                                                                 /* Gain =  15.000000 dB */
+#define HPF_Fs96000_Gain15_A0                         4.646371
+#define HPF_Fs96000_Gain15_A1                         -4.223721
+#define HPF_Fs96000_Gain15_A2                         0.000000
+#define HPF_Fs96000_Gain15_B1                         -0.577350
+#define HPF_Fs96000_Gain15_B2                         0.000000
+
+/* Coefficients for sample rate 192000Hz */
+                                                                  /* Gain =  1.000000 dB */
+#define HPF_Fs192000_Gain1_A0                          1.107823
+#define HPF_Fs192000_Gain1_A1                          -0.875150
+#define HPF_Fs192000_Gain1_A2                          0.000000
+#define HPF_Fs192000_Gain1_B1                          -0.767327
+#define HPF_Fs192000_Gain1_B2                          0.000000
+                                                                  /* Gain =  2.000000 dB */
+#define HPF_Fs192000_Gain2_A0                          1.228803
+#define HPF_Fs192000_Gain2_A1                          -0.996130
+#define HPF_Fs192000_Gain2_A2                          0.000000
+#define HPF_Fs192000_Gain2_B1                          -0.767327
+#define HPF_Fs192000_Gain2_B2                          0.000000
+                                                                   /* Gain =  3.000000 dB */
+#define HPF_Fs192000_Gain3_A0                          1.364544
+#define HPF_Fs192000_Gain3_A1                          -1.131871
+#define HPF_Fs192000_Gain3_A2                          0.000000
+#define HPF_Fs192000_Gain3_B1                          -0.767327
+#define HPF_Fs192000_Gain3_B2                          0.000000
+                                                                   /* Gain =  4.000000 dB */
+#define HPF_Fs192000_Gain4_A0                          1.516849
+#define HPF_Fs192000_Gain4_A1                          -1.284176
+#define HPF_Fs192000_Gain4_A2                           0.000000
+#define HPF_Fs192000_Gain4_B1                           -0.767327
+#define HPF_Fs192000_Gain4_B2                           0.000000
+                                                                   /* Gain =  5.000000 dB */
+#define HPF_Fs192000_Gain5_A0                           1.687737
+#define HPF_Fs192000_Gain5_A1                           -1.455064
+#define HPF_Fs192000_Gain5_A2                           0.000000
+#define HPF_Fs192000_Gain5_B1                           -0.767327
+#define HPF_Fs192000_Gain5_B2                           0.000000
+                                                                   /* Gain =  6.000000 dB */
+#define HPF_Fs192000_Gain6_A0                            1.879477
+#define HPF_Fs192000_Gain6_A1                            -1.646804
+#define HPF_Fs192000_Gain6_A2                            0.000000
+#define HPF_Fs192000_Gain6_B1                            -0.767327
+#define HPF_Fs192000_Gain6_B2                            0.000000
+                                                                 /* Gain =  7.000000 dB */
+#define HPF_Fs192000_Gain7_A0                            2.094613
+#define HPF_Fs192000_Gain7_A1                            -1.861940
+#define HPF_Fs192000_Gain7_A2                            0.000000
+#define HPF_Fs192000_Gain7_B1                            -0.767327
+#define HPF_Fs192000_Gain7_B2                            0.000000
+                                                                   /* Gain =  8.000000 dB */
+#define HPF_Fs192000_Gain8_A0                           2.335999
+#define HPF_Fs192000_Gain8_A1                           -2.103326
+#define HPF_Fs192000_Gain8_A2                           0.000000
+#define HPF_Fs192000_Gain8_B1                           -0.767327
+#define HPF_Fs192000_Gain8_B2                           0.000000
+                                                                   /* Gain =  9.000000 dB */
+#define HPF_Fs192000_Gain9_A0                          2.606839
+#define HPF_Fs192000_Gain9_A1                          -2.374166
+#define HPF_Fs192000_Gain9_A2                          0.000000
+#define HPF_Fs192000_Gain9_B1                          -0.767327
+#define HPF_Fs192000_Gain9_B2                          0.000000
+                                                                 /* Gain =  10.000000 dB */
+#define HPF_Fs192000_Gain10_A0                        2.910726
+#define HPF_Fs192000_Gain10_A1                        -2.678053
+#define HPF_Fs192000_Gain10_A2                         0.000000
+#define HPF_Fs192000_Gain10_B1                         -0.767327
+#define HPF_Fs192000_Gain10_B2                         0.000000
+                                                                  /* Gain =  11.000000 dB */
+#define HPF_Fs192000_Gain11_A0                          3.251693
+#define HPF_Fs192000_Gain11_A1                          -3.019020
+#define HPF_Fs192000_Gain11_A2                          0.000000
+#define HPF_Fs192000_Gain11_B1                          -0.767327
+#define HPF_Fs192000_Gain11_B2                          0.000000
+                                                                  /* Gain =  12.000000 dB */
+#define HPF_Fs192000_Gain12_A0                          3.634264
+#define HPF_Fs192000_Gain12_A1                          -3.401591
+#define HPF_Fs192000_Gain12_A2                          0.000000
+#define HPF_Fs192000_Gain12_B1                          -0.767327
+#define HPF_Fs192000_Gain12_B2                          0.000000
+                                                                /* Gain =  13.000000 dB */
+#define HPF_Fs192000_Gain13_A0                           4.063516
+#define HPF_Fs192000_Gain13_A1                           -3.830843
+#define HPF_Fs192000_Gain13_A2                           0.000000
+#define HPF_Fs192000_Gain13_B1                           -0.767327
+#define HPF_Fs192000_Gain13_B2                           0.000000
+                                                                /* Gain =  14.000000 dB */
+#define HPF_Fs192000_Gain14_A0                          4.545145
+#define HPF_Fs192000_Gain14_A1                          -4.312472
+#define HPF_Fs192000_Gain14_A2                          0.000000
+#define HPF_Fs192000_Gain14_B1                          -0.767327
+#define HPF_Fs192000_Gain14_B2                          0.000000
+                                                                  /* Gain =  15.000000 dB */
+#define HPF_Fs192000_Gain15_A0                         5.085542
+#define HPF_Fs192000_Gain15_A1                         -4.852868
+#define HPF_Fs192000_Gain15_A2                         0.000000
+#define HPF_Fs192000_Gain15_B1                         -0.767327
+#define HPF_Fs192000_Gain15_B2                         0.000000
+
+#endif
+
+#else
 /* Coefficients for sample rate 22050Hz */
                                                                     /* Gain =  1.000000 dB */
 #define HPF_Fs22050_Gain1_A0                             5383         /* Floating point value 0.164291 */
@@ -571,3 +1216,4 @@
 
 
 #endif
+#endif
\ No newline at end of file
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
index 72564d4..cfe53b8 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
@@ -65,9 +65,16 @@
     if(
         /* General parameters */
         ((pParams->OperatingMode != LVM_MODE_OFF) && (pParams->OperatingMode != LVM_MODE_ON))                                         ||
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+    ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000)       &&
+     (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000)      &&
+     (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000)      &&
+     (pParams->SampleRate != LVM_FS_96000) && (pParams->SampleRate != LVM_FS_192000))      ||
+#else
         ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000)       &&
         (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000)       &&
         (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000))      ||
+#endif
         ((pParams->SourceFormat != LVM_STEREO) && (pParams->SourceFormat != LVM_MONOINSTEREO) && (pParams->SourceFormat != LVM_MONO)) ||
         (pParams->SpeakerType > LVM_EX_HEADPHONES))
     {
@@ -268,7 +275,12 @@
 void LVM_SetTrebleBoost(LVM_Instance_t         *pInstance,
                         LVM_ControlParams_t    *pParams)
 {
+#ifdef BUILD_FLOAT
+    extern FO_FLOAT_LShx_Coefs_t  LVM_TrebleBoostCoefs[];
+#else
     extern FO_C16_LShx_Coefs_t  LVM_TrebleBoostCoefs[];
+#endif
+
     LVM_INT16               Offset;
     LVM_INT16               EffectLevel = 0;
 
@@ -298,6 +310,20 @@
              * Load the coefficients and enabled the treble boost
              */
             Offset = (LVM_INT16)(EffectLevel - 1 + TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
+#ifdef BUILD_FLOAT
+            FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
+                                            &pInstance->pTE_Taps->TrebleBoost_Taps,
+                                            &LVM_TrebleBoostCoefs[Offset]);
+
+            /*
+             * Clear the taps
+             */
+            LoadConst_Float((LVM_FLOAT)0,                                     /* Value */
+                            (void *)&pInstance->pTE_Taps->TrebleBoost_Taps,  /* Destination.\
+                                                     Cast to void: no dereferencing in function */
+                            (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps) / \
+                                                        sizeof(LVM_FLOAT))); /* Number of words */
+#else
             FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
                                             &pInstance->pTE_Taps->TrebleBoost_Taps,
                                             &LVM_TrebleBoostCoefs[Offset]);
@@ -309,6 +335,7 @@
                          (void *)&pInstance->pTE_Taps->TrebleBoost_Taps,  /* Destination.\
                                                      Cast to void: no dereferencing in function */
                          (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps)/sizeof(LVM_INT16))); /* Number of words */
+#endif
         }
     }
     else
@@ -342,6 +369,9 @@
     LVM_UINT16      dBShifts;                                   /* 6dB shifts */
     LVM_UINT16      dBOffset;                                   /* Table offset */
     LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
+#ifdef BUILD_FLOAT
+    LVM_FLOAT        Temp;
+#endif
 
     /*
      * Limit the gain to the maximum allowed
@@ -401,22 +431,46 @@
      */
     if(dBShifts == 0)
     {
+#ifdef BUILD_FLOAT
+        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
+                                (LVM_FLOAT)LVM_VolumeTable[dBOffset]);
+#else
         LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
                                 (LVM_INT32)LVM_VolumeTable[dBOffset]);
-    }
+#endif
+        }
     else
     {
+#ifdef BUILD_FLOAT
+        Temp = LVM_VolumeTable[dBOffset];
+        while(dBShifts) {
+            Temp = Temp / 2.0f;
+            dBShifts--;
+        }
+        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0], Temp);
+#else
         LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
                                 (((LVM_INT32)LVM_VolumeTable[dBOffset])>>dBShifts));
+#endif
     }
     pInstance->VC_Volume.MixerStream[0].CallbackSet = 1;
     if(pInstance->NoSmoothVolume == LVM_TRUE)
     {
+#ifdef BUILD_FLOAT
+        LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0], 0,
+                                  pInstance->Params.SampleRate, 2);
+#else
         LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,pInstance->Params.SampleRate,2);
+#endif
     }
     else
     {
+#ifdef BUILD_FLOAT
+        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],
+                                           LVM_VC_MIXER_TIME, pInstance->Params.SampleRate, 2);
+#else
         LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],LVM_VC_MIXER_TIME,pInstance->Params.SampleRate,2);
+#endif
     }
 }
 
@@ -554,8 +608,23 @@
         /* Configure Mixer module for gradual changes to volume*/
         if(LocalParams.VC_Balance < 0)
         {
+#ifdef BUILD_FLOAT
+            LVM_FLOAT Target_Float;
+#else
             LVM_INT32 Target;
+#endif
             /* Drop in right channel volume*/
+#ifdef BUILD_FLOAT
+            Target_Float = LVM_MAXFLOAT;
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0], Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
+                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
+
+            Target_Float = dB_to_LinFloat((LVM_INT16)(LocalParams.VC_Balance << 4));
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1], Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
+                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
+#else
             Target = LVM_MAXINT_16;
             LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
@@ -563,11 +632,27 @@
             Target = dB_to_Lin32((LVM_INT16)(LocalParams.VC_Balance<<4));
             LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+#endif
         }
         else if(LocalParams.VC_Balance >0)
         {
+#ifdef BUILD_FLOAT
+            LVM_FLOAT Target_Float;
+#else
             LVM_INT32 Target;
+#endif
             /* Drop in left channel volume*/
+#ifdef BUILD_FLOAT
+            Target_Float = dB_to_LinFloat((LVM_INT16)((-LocalParams.VC_Balance) << 4));
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0], Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
+                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
+
+            Target_Float = LVM_MAXFLOAT;
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1], Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
+                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
+#else
             Target = dB_to_Lin32((LVM_INT16)((-LocalParams.VC_Balance)<<4));
             LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
@@ -575,17 +660,36 @@
             Target = LVM_MAXINT_16;
             LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+#endif
         }
         else
         {
+#ifdef BUILD_FLOAT
+            LVM_FLOAT Target_Float;
+#else
             LVM_INT32 Target;
+#endif
             /* No drop*/
+#ifdef BUILD_FLOAT
+            Target_Float = LVM_MAXFLOAT;
+#else
             Target = LVM_MAXINT_16;
+#endif
+#ifdef BUILD_FLOAT
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
+                                               LVM_VC_MIXER_TIME,LocalParams.SampleRate, 1);
+
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
+                                               LVM_VC_MIXER_TIME,LocalParams.SampleRate, 1);
+#else
             LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
 
             LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+#endif
         }
     }
     /*
@@ -1008,18 +1112,30 @@
                             short   CallBackParam)
 {
     LVM_Instance_t *pInstance =(LVM_Instance_t  *)pBundleHandle;
+#ifdef BUILD_FLOAT
+    LVM_FLOAT    Target;
+#else
     LVM_INT32    Target;
+#endif
 
     (void) pGeneralPurpose;
     (void) CallBackParam;
 
     /* When volume mixer has reached 0 dB target then stop it to avoid
        unnecessary processing. */
+#ifdef BUILD_FLOAT
+    Target = LVC_Mixer_GetTarget(&pInstance->VC_Volume.MixerStream[0]);
+    if(Target == 1.0f)
+    {
+        pInstance->VC_Active = LVM_FALSE;
+    }
+#else
     Target = LVC_Mixer_GetTarget(&pInstance->VC_Volume.MixerStream[0]);
 
     if(Target == 0x7FFF)
     {
         pInstance->VC_Active = LVM_FALSE;
     }
+#endif
     return 1;
 }
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
index 542c3c8..26c1c4f 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
@@ -232,7 +232,11 @@
         /*
          * Set the capabilities
          */
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_192000;
+#else
         DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
+#endif
         DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
         DBE_Capabilities.MaxBlockSize    = InternalBlockSize;
 
@@ -265,7 +269,11 @@
         /*
          * Set the capabilities
          */
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+        EQNB_Capabilities.SampleRate   = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_192000;
+#else
         EQNB_Capabilities.SampleRate   = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
+#endif
         EQNB_Capabilities.SourceFormat = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
         EQNB_Capabilities.MaxBlockSize = InternalBlockSize;
         EQNB_Capabilities.MaxBands     = pInstParams->EQNB_NumBands;
@@ -542,10 +550,15 @@
         BundleScratchSize = (LVM_INT32)(6 * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) * sizeof(LVM_INT16));
         pInstance->pBufferManagement->pScratch = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],   /* Scratch 1 buffer */
                                                                      (LVM_UINT32)BundleScratchSize);
-
+#ifdef BUILD_FLOAT
+        LoadConst_Float(0,                                   /* Clear the input delay buffer */
+                        (LVM_FLOAT *)&pInstance->pBufferManagement->InDelayBuffer,
+                        (LVM_INT16)(2 * MIN_INTERNAL_BLOCKSIZE));
+#else
         LoadConst_16(0,                                                        /* Clear the input delay buffer */
                      (LVM_INT16 *)&pInstance->pBufferManagement->InDelayBuffer,
                      (LVM_INT16)(2 * MIN_INTERNAL_BLOCKSIZE));
+#endif
         pInstance->pBufferManagement->InDelaySamples = MIN_INTERNAL_BLOCKSIZE; /* Set the number of delay samples */
         pInstance->pBufferManagement->OutDelaySamples = 0;                     /* No samples in the output buffer */
         pInstance->pBufferManagement->BufferState = LVM_FIRSTCALL;             /* Set the state ready for the first call */
@@ -598,14 +611,26 @@
     /* In managed buffering, start with low signal level as delay in buffer management causes a click*/
     if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
     {
+#ifdef BUILD_FLOAT
+        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0], 0, 0);
+#else
         LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0],0,0);
+#endif
     }
     else
     {
+#ifdef BUILD_FLOAT
+        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0], LVM_MAXFLOAT, LVM_MAXFLOAT);
+#else
         LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0],LVM_MAXINT_16,LVM_MAXINT_16);
+#endif
     }
 
+#ifdef BUILD_FLOAT
     LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,LVM_FS_8000,2);
+#else
+    LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0], 0, LVM_FS_8000, 2);
+#endif
 
     pInstance->VC_VolumedB                  = 0;
     pInstance->VC_AVLFixedVolume            = 0;
@@ -615,15 +640,24 @@
     pInstance->VC_BalanceMix.MixerStream[0].CallbackSet        = 0;
     pInstance->VC_BalanceMix.MixerStream[0].pCallbackHandle    = pInstance;
     pInstance->VC_BalanceMix.MixerStream[0].pCallBack          = LVM_VCCallBack;
+#ifdef BUILD_FLOAT
+    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[0], LVM_MAXFLOAT, LVM_MAXFLOAT);
+#else
     LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[0],LVM_MAXINT_16,LVM_MAXINT_16);
+#endif
     LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
 
     pInstance->VC_BalanceMix.MixerStream[1].CallbackParam      = 0;
     pInstance->VC_BalanceMix.MixerStream[1].CallbackSet        = 0;
     pInstance->VC_BalanceMix.MixerStream[1].pCallbackHandle    = pInstance;
     pInstance->VC_BalanceMix.MixerStream[1].pCallBack          = LVM_VCCallBack;
+#ifdef BUILD_FLOAT
+    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[1], LVM_MAXFLOAT, LVM_MAXFLOAT);
+#else
     LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[1],LVM_MAXINT_16,LVM_MAXINT_16);
+#endif
     LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
+
     /*
      * Set the default EQNB pre-gain and pointer to the band definitions
      */
@@ -709,7 +743,11 @@
         /*
          * Set the initialisation capabilities
          */
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_192000;
+#else
         DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
+#endif
         DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
         DBE_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
 
@@ -763,7 +801,11 @@
         /*
          * Set the initialisation capabilities
          */
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+        EQNB_Capabilities.SampleRate      = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_192000;
+#else
         EQNB_Capabilities.SampleRate      = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
+#endif
         EQNB_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
         EQNB_Capabilities.MaxBands        = pInstParams->EQNB_NumBands;
         EQNB_Capabilities.SourceFormat    = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
@@ -868,9 +910,14 @@
                 PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].Size);
 
             /* Fast Temporary */
+#ifdef BUILD_FLOAT
             pInstance->pPSAInput = InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
-                                                                     (LVM_UINT32) MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_INT16));
-
+                                                       (LVM_UINT32) MAX_INTERNAL_BLOCKSIZE * \
+                                                       sizeof(LVM_FLOAT));
+#else
+            pInstance->pPSAInput = InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
+                                                       (LVM_UINT32) MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_INT16));
+#endif
             PSA_MemTab.Region[LVM_TEMPORARY_FAST].pBaseAddress       = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],0);
 
 
@@ -994,7 +1041,6 @@
     /* DC removal filter */
     DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
 
-
     return LVM_SUCCESS;
 }
 
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
index 2e85f77..b453222 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -138,6 +138,23 @@
 
 
 /* Buffer Management */
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT               *pScratch;          /* Bundle scratch buffer */
+
+    LVM_INT16               BufferState;        /* Buffer status */
+    LVM_FLOAT               InDelayBuffer[6 * MIN_INTERNAL_BLOCKSIZE]; /* Input buffer delay line, \
+                                                                           left and right */
+    LVM_INT16               InDelaySamples;     /* Number of samples in the input delay buffer */
+
+    LVM_FLOAT               OutDelayBuffer[2 * MIN_INTERNAL_BLOCKSIZE]; /* Output buffer delay \
+                                                                                      line */
+    LVM_INT16               OutDelaySamples;    /* Number of samples in the output delay buffer, \
+                                                                             left and right */
+    LVM_INT16               SamplesToOutput;    /* Samples to write to the output */
+} LVM_Buffer_t;
+#else
 typedef struct
 {
     LVM_INT16               *pScratch;          /* Bundle scratch buffer */
@@ -150,22 +167,28 @@
     LVM_INT16               OutDelaySamples;    /* Number of samples in the output delay buffer, left and right */
     LVM_INT16               SamplesToOutput;    /* Samples to write to the output */
 } LVM_Buffer_t;
-
+#endif
 
 /* Filter taps */
 typedef struct
 {
+#ifdef BUILD_FLOAT
+    Biquad_2I_Order1_FLOAT_Taps_t TrebleBoost_Taps;   /* Treble boost Taps */
+#else
     Biquad_2I_Order1_Taps_t TrebleBoost_Taps;   /* Treble boost Taps */
+#endif
 } LVM_TE_Data_t;
 
-
 /* Coefficients */
 typedef struct
 {
+#ifdef BUILD_FLOAT
+    Biquad_FLOAT_Instance_t       TrebleBoost_State;  /* State for the treble boost filter */
+#else
     Biquad_Instance_t       TrebleBoost_State;  /* State for the treble boost filter */
+#endif
 } LVM_TE_Coefs_t;
 
-
 typedef struct
 {
     /* Public parameters */
@@ -181,15 +204,24 @@
     LVM_INT16               InternalBlockSize;  /* Maximum internal block size */
     LVM_Buffer_t            *pBufferManagement; /* Buffer management variables */
     LVM_INT16               SamplesToProcess;   /* Input samples left to process */
+#ifdef BUILD_FLOAT
+    LVM_FLOAT               *pInputSamples;     /* External input sample pointer */
+    LVM_FLOAT               *pOutputSamples;    /* External output sample pointer */
+#else
     LVM_INT16               *pInputSamples;     /* External input sample pointer */
     LVM_INT16               *pOutputSamples;    /* External output sample pointer */
+#endif
 
     /* Configuration number */
     LVM_INT32               ConfigurationNumber;
     LVM_INT32               BlickSizeMultiple;
 
     /* DC removal */
+#ifdef BUILD_FLOAT
+    Biquad_FLOAT_Instance_t       DC_RemovalInstance; /* DC removal filter instance */
+#else
     Biquad_Instance_t       DC_RemovalInstance; /* DC removal filter instance */
+#endif
 
     /* Concert Sound */
     LVCS_Handle_t           hCSInstance;        /* Concert Sound instance handle */
@@ -209,8 +241,16 @@
     LVM_INT16               DBE_Active;         /* Control flag */
 
     /* Volume Control */
+#ifdef BUILD_FLOAT
+    LVMixer3_1St_FLOAT_st   VC_Volume;          /* Volume scaler */
+#else
     LVMixer3_1St_st         VC_Volume;          /* Volume scaler */
+#endif
+#ifdef BUILD_FLOAT
+    LVMixer3_2St_FLOAT_st         VC_BalanceMix;      /* VC balance mixer */
+#else
     LVMixer3_2St_st         VC_BalanceMix;      /* VC balance mixer */
+#endif
     LVM_INT16               VC_VolumedB;        /* Gain in dB */
     LVM_INT16               VC_Active;          /* Control flag */
     LVM_INT16               VC_AVLFixedVolume;  /* AVL fixed volume */
@@ -234,7 +274,11 @@
     LVPSA_ControlParams_t   PSA_ControlParams;  /* Spectrum Analyzer control parameters */
     LVM_INT16               PSA_GainOffset;     /* Tone control flag */
     LVM_Callback            CallBack;
+#ifdef BUILD_FLOAT
+    LVM_FLOAT               *pPSAInput;         /* PSA input pointer */
+#else
     LVM_INT16               *pPSAInput;         /* PSA input pointer */
+#endif
 
     LVM_INT16              NoSmoothVolume;      /* Enable or disable smooth volume changes*/
 
@@ -261,16 +305,28 @@
 
 void    LVM_SetHeadroom(    LVM_Instance_t         *pInstance,
                             LVM_ControlParams_t    *pParams);
-
+#ifdef BUILD_FLOAT
+void    LVM_BufferIn(   LVM_Handle_t      hInstance,
+                        const LVM_FLOAT   *pInData,
+                        LVM_FLOAT         **pToProcess,
+                        LVM_FLOAT         **pProcessed,
+                        LVM_UINT16        *pNumSamples);
+#else
 void    LVM_BufferIn(   LVM_Handle_t      hInstance,
                         const LVM_INT16   *pInData,
                         LVM_INT16         **pToProcess,
                         LVM_INT16         **pProcessed,
                         LVM_UINT16        *pNumSamples);
-
+#endif
+#ifdef BUILD_FLOAT
+void    LVM_BufferOut(  LVM_Handle_t     hInstance,
+                        LVM_FLOAT        *pOutData,
+                        LVM_UINT16       *pNumSamples);
+#else
 void    LVM_BufferOut(  LVM_Handle_t     hInstance,
                         LVM_INT16        *pOutData,
                         LVM_UINT16       *pNumSamples);
+#endif
 
 LVM_INT32 LVM_AlgoCallBack(     void          *pBundleHandle,
                                 void          *pData,
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
index f5a01f3..4a19a13 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
@@ -51,7 +51,231 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
+                                const LVM_FLOAT             *pInData,
+                                LVM_FLOAT                   *pOutData,
+                                LVM_UINT16                  NumSamples,
+                                LVM_UINT32                  AudioTime)
+{
 
+    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
+    LVM_UINT16          SampleCount = NumSamples;
+    LVM_FLOAT           *pInput     = (LVM_FLOAT *)pInData;
+    LVM_FLOAT           *pToProcess = (LVM_FLOAT *)pInData;
+    LVM_FLOAT           *pProcessed = pOutData;
+    LVM_ReturnStatus_en  Status;
+
+    /*
+     * Check if the number of samples is zero
+     */
+    if (NumSamples == 0)
+    {
+        return(LVM_SUCCESS);
+    }
+
+
+    /*
+     * Check valid points have been given
+     */
+    if ((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    /*
+     * For unmanaged mode only
+     */
+    if(pInstance->InstParams.BufferMode == LVM_UNMANAGED_BUFFERS)
+    {
+         /*
+         * Check if the number of samples is a good multiple (unmanaged mode only)
+         */
+        if((NumSamples % pInstance->BlickSizeMultiple) != 0)
+        {
+            return(LVM_INVALIDNUMSAMPLES);
+        }
+
+        /*
+         * Check the buffer alignment
+         */
+        if((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
+        {
+            return(LVM_ALIGNMENTERROR);
+        }
+    }
+
+
+    /*
+     * Update new parameters if necessary
+     */
+    if (pInstance->ControlPending == LVM_TRUE)
+    {
+        Status = LVM_ApplyNewSettings(hInstance);
+
+        if(Status != LVM_SUCCESS)
+        {
+            return Status;
+        }
+    }
+
+
+    /*
+     * Convert from Mono if necessary
+     */
+    if (pInstance->Params.SourceFormat == LVM_MONO)
+    {
+        MonoTo2I_Float(pInData,                                /* Source */
+                       pOutData,                               /* Destination */
+                       (LVM_INT16)NumSamples);                 /* Number of input samples */
+        pInput     = pOutData;
+        pToProcess = pOutData;
+    }
+
+
+    /*
+     * Process the data with managed buffers
+     */
+    while (SampleCount != 0)
+    {
+        /*
+         * Manage the input buffer and frame processing
+         */
+        LVM_BufferIn(hInstance,
+                     pInput,
+                     &pToProcess,
+                     &pProcessed,
+                     &SampleCount);
+
+        /*
+         * Only process data when SampleCount is none zero, a zero count can occur when
+         * the BufferIn routine is working in managed mode.
+         */
+        if (SampleCount != 0)
+        {
+
+            /*
+             * Apply ConcertSound if required
+             */
+            if (pInstance->CS_Active == LVM_TRUE)
+            {
+                (void)LVCS_Process(pInstance->hCSInstance,     /* Concert Sound instance handle */
+                                   pToProcess,
+                                   pProcessed,
+                                   SampleCount);
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Apply volume if required
+             */
+            if (pInstance->VC_Active!=0)
+            {
+                LVC_MixSoft_1St_D16C31_SAT(&pInstance->VC_Volume,
+                                       pToProcess,
+                                       pProcessed,
+                                       (LVM_INT16)(2 * SampleCount));     /* Left and right*/
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Call N-Band equaliser if enabled
+             */
+            if (pInstance->EQNB_Active == LVM_TRUE)
+            {
+                LVEQNB_Process(pInstance->hEQNBInstance,    /* N-Band equaliser instance handle */
+                               pToProcess,
+                               pProcessed,
+                               SampleCount);
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Call bass enhancement if enabled
+             */
+            if (pInstance->DBE_Active == LVM_TRUE)
+            {
+                LVDBE_Process(pInstance->hDBEInstance,       /* Dynamic Bass Enhancement \
+                                                                instance handle */
+                              pToProcess,
+                              pProcessed,
+                              SampleCount);
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Bypass mode or everything off, so copy the input to the output
+             */
+            if (pToProcess != pProcessed)
+            {
+                Copy_Float(pToProcess,                             /* Source */
+                           pProcessed,                             /* Destination */
+                           (LVM_INT16)(2 * SampleCount));          /* Left and right */
+            }
+
+            /*
+             * Apply treble boost if required
+             */
+            if (pInstance->TE_Active == LVM_TRUE)
+            {
+                /*
+                 * Apply the filter
+                 */
+                FO_2I_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
+                                           pProcessed,
+                                           pProcessed,
+                                           (LVM_INT16)SampleCount);
+
+            }
+
+            /*
+             * Volume balance
+             */
+            LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
+                                            pProcessed,
+                                            pProcessed,
+                                            SampleCount);
+
+            /*
+             * Perform Parametric Spectum Analysis
+             */
+            if ((pInstance->Params.PSA_Enable == LVM_PSA_ON) &&
+                                            (pInstance->InstParams.PSA_Included == LVM_PSA_ON))
+            {
+                    From2iToMono_Float(pProcessed,
+                                       pInstance->pPSAInput,
+                                       (LVM_INT16)(SampleCount));
+
+                    LVPSA_Process(pInstance->hPSAInstance,
+                            pInstance->pPSAInput,
+                            (LVM_UINT16)(SampleCount),
+                            AudioTime);
+            }
+
+
+            /*
+             * DC removal
+             */
+            DC_2I_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
+                                 pProcessed,
+                                 pProcessed,
+                                 (LVM_INT16)SampleCount);
+
+
+        }
+
+        /*
+         * Manage the output buffer
+         */
+        LVM_BufferOut(hInstance,
+                      pOutData,
+                      &SampleCount);
+
+    }
+
+    return(LVM_SUCCESS);
+}
+#else
 LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
                                 const LVM_INT16             *pInData,
                                 LVM_INT16                   *pOutData,
@@ -273,3 +497,4 @@
 
     return(LVM_SUCCESS);
 }
+#endif
\ No newline at end of file
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
index e14f909..199ddde 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
@@ -29,7 +29,342 @@
 /*    Treble Boost Filter Coefficients                                              */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
 
+FO_FLOAT_LShx_Coefs_t    LVM_TrebleBoostCoefs[] = {
+
+                    /* 22kHz sampling rate */
+                    {HPF_Fs22050_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs22050_Gain1_A0,
+                     -HPF_Fs22050_Gain1_B1},
+                    {HPF_Fs22050_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs22050_Gain2_A0,
+                     -HPF_Fs22050_Gain2_B1},
+                    {HPF_Fs22050_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs22050_Gain3_A0,
+                     -HPF_Fs22050_Gain3_B1},
+                    {HPF_Fs22050_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs22050_Gain4_A0,
+                     -HPF_Fs22050_Gain4_B1},
+                    {HPF_Fs22050_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs22050_Gain5_A0,
+                     -HPF_Fs22050_Gain5_B1},
+                    {HPF_Fs22050_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs22050_Gain6_A0,
+                     -HPF_Fs22050_Gain6_B1},
+                    {HPF_Fs22050_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs22050_Gain7_A0,
+                     -HPF_Fs22050_Gain7_B1},
+                    {HPF_Fs22050_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs22050_Gain8_A0,
+                     -HPF_Fs22050_Gain8_B1},
+                    {HPF_Fs22050_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs22050_Gain9_A0,
+                     -HPF_Fs22050_Gain9_B1},
+                    {HPF_Fs22050_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs22050_Gain10_A0,
+                     -HPF_Fs22050_Gain10_B1},
+                    {HPF_Fs22050_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs22050_Gain11_A0,
+                     -HPF_Fs22050_Gain11_B1},
+                    {HPF_Fs22050_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs22050_Gain12_A0,
+                     -HPF_Fs22050_Gain12_B1},
+                    {HPF_Fs22050_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs22050_Gain13_A0,
+                     -HPF_Fs22050_Gain13_B1},
+                    {HPF_Fs22050_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs22050_Gain14_A0,
+                     -HPF_Fs22050_Gain14_B1},
+                    {HPF_Fs22050_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs22050_Gain15_A0,
+                     -HPF_Fs22050_Gain15_B1},
+
+                    /* 24kHz sampling rate */
+                    {HPF_Fs24000_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs24000_Gain1_A0,
+                     -HPF_Fs24000_Gain1_B1},
+                    {HPF_Fs24000_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs24000_Gain2_A0,
+                     -HPF_Fs24000_Gain2_B1},
+                    {HPF_Fs24000_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs24000_Gain3_A0,
+                     -HPF_Fs24000_Gain3_B1},
+                    {HPF_Fs24000_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs24000_Gain4_A0,
+                     -HPF_Fs24000_Gain4_B1},
+                    {HPF_Fs24000_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs24000_Gain5_A0,
+                     -HPF_Fs24000_Gain5_B1},
+                    {HPF_Fs24000_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs24000_Gain6_A0,
+                     -HPF_Fs24000_Gain6_B1},
+                    {HPF_Fs24000_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs24000_Gain7_A0,
+                     -HPF_Fs24000_Gain7_B1},
+                    {HPF_Fs24000_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs24000_Gain8_A0,
+                     -HPF_Fs24000_Gain8_B1},
+                    {HPF_Fs24000_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs24000_Gain9_A0,
+                     -HPF_Fs24000_Gain9_B1},
+                    {HPF_Fs24000_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs24000_Gain10_A0,
+                     -HPF_Fs24000_Gain10_B1},
+                    {HPF_Fs24000_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs24000_Gain11_A0,
+                     -HPF_Fs24000_Gain11_B1},
+                    {HPF_Fs24000_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs24000_Gain12_A0,
+                     -HPF_Fs24000_Gain12_B1},
+                    {HPF_Fs24000_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs24000_Gain13_A0,
+                     -HPF_Fs24000_Gain13_B1},
+                    {HPF_Fs24000_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs24000_Gain14_A0,
+                     -HPF_Fs24000_Gain14_B1},
+                    {HPF_Fs24000_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs24000_Gain15_A0,
+                     -HPF_Fs24000_Gain15_B1},
+
+                    /* 32kHz sampling rate */
+                    {HPF_Fs32000_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs32000_Gain1_A0,
+                     -HPF_Fs32000_Gain1_B1},
+                    {HPF_Fs32000_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs32000_Gain2_A0,
+                     -HPF_Fs32000_Gain2_B1},
+                    {HPF_Fs32000_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs32000_Gain3_A0,
+                     -HPF_Fs32000_Gain3_B1},
+                    {HPF_Fs32000_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs32000_Gain4_A0,
+                     -HPF_Fs32000_Gain4_B1},
+                    {HPF_Fs32000_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs32000_Gain5_A0,
+                     -HPF_Fs32000_Gain5_B1},
+                    {HPF_Fs32000_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs32000_Gain6_A0,
+                     -HPF_Fs32000_Gain6_B1},
+                    {HPF_Fs32000_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs32000_Gain7_A0,
+                     -HPF_Fs32000_Gain7_B1},
+                    {HPF_Fs32000_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs32000_Gain8_A0,
+                     -HPF_Fs32000_Gain8_B1},
+                    {HPF_Fs32000_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs32000_Gain9_A0,
+                     -HPF_Fs32000_Gain9_B1},
+                    {HPF_Fs32000_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs32000_Gain10_A0,
+                     -HPF_Fs32000_Gain10_B1},
+                    {HPF_Fs32000_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs32000_Gain11_A0,
+                     -HPF_Fs32000_Gain11_B1},
+                    {HPF_Fs32000_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs32000_Gain12_A0,
+                     -HPF_Fs32000_Gain12_B1},
+                    {HPF_Fs32000_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs32000_Gain13_A0,
+                     -HPF_Fs32000_Gain13_B1},
+                    {HPF_Fs32000_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs32000_Gain14_A0,
+                     -HPF_Fs32000_Gain14_B1},
+                    {HPF_Fs32000_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs32000_Gain15_A0,
+                     -HPF_Fs32000_Gain15_B1},
+
+                    /* 44kHz sampling rate */
+                    {HPF_Fs44100_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs44100_Gain1_A0,
+                     -HPF_Fs44100_Gain1_B1,},
+                    {HPF_Fs44100_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs44100_Gain2_A0,
+                     -HPF_Fs44100_Gain2_B1},
+                    {HPF_Fs44100_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs44100_Gain3_A0,
+                     -HPF_Fs44100_Gain3_B1},
+                    {HPF_Fs44100_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs44100_Gain4_A0,
+                     -HPF_Fs44100_Gain4_B1},
+                    {HPF_Fs44100_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs44100_Gain5_A0,
+                     -HPF_Fs44100_Gain5_B1},
+                    {HPF_Fs44100_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs44100_Gain6_A0,
+                     -HPF_Fs44100_Gain6_B1},
+                    {HPF_Fs44100_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs44100_Gain7_A0,
+                     -HPF_Fs44100_Gain7_B1},
+                    {HPF_Fs44100_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs44100_Gain8_A0,
+                     -HPF_Fs44100_Gain8_B1},
+                    {HPF_Fs44100_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs44100_Gain9_A0,
+                     -HPF_Fs44100_Gain9_B1},
+                    {HPF_Fs44100_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs44100_Gain10_A0,
+                     -HPF_Fs44100_Gain10_B1},
+                    {HPF_Fs44100_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs44100_Gain11_A0,
+                     -HPF_Fs44100_Gain11_B1},
+                    {HPF_Fs44100_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs44100_Gain12_A0,
+                     -HPF_Fs44100_Gain12_B1},
+                    {HPF_Fs44100_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs44100_Gain13_A0,
+                     -HPF_Fs44100_Gain13_B1},
+                    {HPF_Fs44100_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs44100_Gain14_A0,
+                     -HPF_Fs44100_Gain14_B1},
+                    {HPF_Fs44100_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs44100_Gain15_A0,
+                     -HPF_Fs44100_Gain15_B1},
+
+                    /* 48kHz sampling rate */
+                    {HPF_Fs48000_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs48000_Gain1_A0,
+                     -HPF_Fs48000_Gain1_B1},
+                    {HPF_Fs48000_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs48000_Gain2_A0,
+                     -HPF_Fs48000_Gain2_B1},
+                    {HPF_Fs48000_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs48000_Gain3_A0,
+                     -HPF_Fs48000_Gain3_B1},
+                    {HPF_Fs48000_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs48000_Gain4_A0,
+                     -HPF_Fs48000_Gain4_B1},
+                    {HPF_Fs48000_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs48000_Gain5_A0,
+                     -HPF_Fs48000_Gain5_B1},
+                    {HPF_Fs48000_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs48000_Gain6_A0,
+                     -HPF_Fs48000_Gain6_B1},
+                    {HPF_Fs48000_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs48000_Gain7_A0,
+                     -HPF_Fs48000_Gain7_B1},
+                    {HPF_Fs48000_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs48000_Gain8_A0,
+                     -HPF_Fs48000_Gain8_B1},
+                    {HPF_Fs48000_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs48000_Gain9_A0,
+                     -HPF_Fs48000_Gain9_B1},
+                    {HPF_Fs48000_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs48000_Gain10_A0,
+                     -HPF_Fs48000_Gain10_B1},
+                    {HPF_Fs48000_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs48000_Gain11_A0,
+                     -HPF_Fs48000_Gain11_B1},
+                    {HPF_Fs48000_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs48000_Gain12_A0,
+                     -HPF_Fs48000_Gain12_B1},
+                    {HPF_Fs48000_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs48000_Gain13_A0,
+                     -HPF_Fs48000_Gain13_B1},
+                    {HPF_Fs48000_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs48000_Gain14_A0,
+                     -HPF_Fs48000_Gain14_B1},
+                    {HPF_Fs48000_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs48000_Gain15_A0,
+                     -HPF_Fs48000_Gain15_B1}
+#ifdef HIGHER_FS
+                    ,
+                    /* 96kHz sampling rate */
+                    {HPF_Fs96000_Gain1_A1,             /* Gain setting 1 */
+                    HPF_Fs96000_Gain1_A0,
+                    -HPF_Fs96000_Gain1_B1},
+                    {HPF_Fs96000_Gain2_A1,             /* Gain setting 2 */
+                    HPF_Fs96000_Gain2_A0,
+                    -HPF_Fs96000_Gain2_B1},
+                    {HPF_Fs96000_Gain3_A1,             /* Gain setting 3 */
+                    HPF_Fs96000_Gain3_A0,
+                    -HPF_Fs96000_Gain3_B1},
+                    {HPF_Fs96000_Gain4_A1,             /* Gain setting 4 */
+                    HPF_Fs96000_Gain4_A0,
+                    -HPF_Fs96000_Gain4_B1},
+                    {HPF_Fs96000_Gain5_A1,             /* Gain setting 5 */
+                    HPF_Fs96000_Gain5_A0,
+                    -HPF_Fs96000_Gain5_B1},
+                    {HPF_Fs96000_Gain6_A1,             /* Gain setting 6 */
+                    HPF_Fs96000_Gain6_A0,
+                    -HPF_Fs96000_Gain6_B1},
+                    {HPF_Fs96000_Gain7_A1,             /* Gain setting 7 */
+                    HPF_Fs96000_Gain7_A0,
+                    -HPF_Fs96000_Gain7_B1},
+                    {HPF_Fs96000_Gain8_A1,             /* Gain setting 8 */
+                    HPF_Fs96000_Gain8_A0,
+                    -HPF_Fs96000_Gain8_B1},
+                    {HPF_Fs96000_Gain9_A1,             /* Gain setting 9 */
+                    HPF_Fs96000_Gain9_A0,
+                    -HPF_Fs96000_Gain9_B1},
+                    {HPF_Fs96000_Gain10_A1,             /* Gain setting 10 */
+                    HPF_Fs96000_Gain10_A0,
+                    -HPF_Fs96000_Gain10_B1},
+                    {HPF_Fs96000_Gain11_A1,             /* Gain setting 11 */
+                    HPF_Fs96000_Gain11_A0,
+                    -HPF_Fs96000_Gain11_B1},
+                    {HPF_Fs96000_Gain12_A1,             /* Gain setting 12 */
+                    HPF_Fs96000_Gain12_A0,
+                    -HPF_Fs96000_Gain12_B1},
+                    {HPF_Fs96000_Gain13_A1,             /* Gain setting 13 */
+                    HPF_Fs96000_Gain13_A0,
+                    -HPF_Fs96000_Gain13_B1},
+                    {HPF_Fs96000_Gain14_A1,             /* Gain setting 14 */
+                    HPF_Fs96000_Gain14_A0,
+                    -HPF_Fs96000_Gain14_B1},
+                    {HPF_Fs96000_Gain15_A1,             /* Gain setting 15 */
+                    HPF_Fs96000_Gain15_A0,
+                    -HPF_Fs96000_Gain15_B1},
+
+                    /* 192kHz sampling rate */
+                    {HPF_Fs192000_Gain1_A1,             /* Gain setting 1 */
+                    HPF_Fs192000_Gain1_A0,
+                    -HPF_Fs192000_Gain1_B1},
+                    {HPF_Fs192000_Gain2_A1,             /* Gain setting 2 */
+                    HPF_Fs192000_Gain2_A0,
+                    -HPF_Fs192000_Gain2_B1},
+                    {HPF_Fs192000_Gain3_A1,             /* Gain setting 3 */
+                    HPF_Fs192000_Gain3_A0,
+                    -HPF_Fs192000_Gain3_B1},
+                    {HPF_Fs192000_Gain4_A1,             /* Gain setting 4 */
+                    HPF_Fs192000_Gain4_A0,
+                    -HPF_Fs192000_Gain4_B1},
+                    {HPF_Fs192000_Gain5_A1,             /* Gain setting 5 */
+                    HPF_Fs192000_Gain5_A0,
+                    -HPF_Fs192000_Gain5_B1},
+                    {HPF_Fs192000_Gain6_A1,             /* Gain setting 6 */
+                    HPF_Fs192000_Gain6_A0,
+                    -HPF_Fs192000_Gain6_B1},
+                    {HPF_Fs192000_Gain7_A1,             /* Gain setting 7 */
+                    HPF_Fs192000_Gain7_A0,
+                    -HPF_Fs192000_Gain7_B1},
+                    {HPF_Fs192000_Gain8_A1,             /* Gain setting 8 */
+                    HPF_Fs192000_Gain8_A0,
+                    -HPF_Fs192000_Gain8_B1},
+                    {HPF_Fs192000_Gain9_A1,             /* Gain setting 9 */
+                    HPF_Fs192000_Gain9_A0,
+                    -HPF_Fs192000_Gain9_B1},
+                    {HPF_Fs192000_Gain10_A1,             /* Gain setting 10 */
+                    HPF_Fs192000_Gain10_A0,
+                    -HPF_Fs192000_Gain10_B1},
+                    {HPF_Fs192000_Gain11_A1,             /* Gain setting 11 */
+                    HPF_Fs192000_Gain11_A0,
+                    -HPF_Fs192000_Gain11_B1},
+                    {HPF_Fs192000_Gain12_A1,             /* Gain setting 12 */
+                    HPF_Fs192000_Gain12_A0,
+                    -HPF_Fs192000_Gain12_B1},
+                    {HPF_Fs192000_Gain13_A1,             /* Gain setting 13 */
+                    HPF_Fs192000_Gain13_A0,
+                    -HPF_Fs192000_Gain13_B1},
+                    {HPF_Fs192000_Gain14_A1,             /* Gain setting 14 */
+                    HPF_Fs192000_Gain14_A0,
+                    -HPF_Fs192000_Gain14_B1},
+                    {HPF_Fs192000_Gain15_A1,             /* Gain setting 15 */
+                    HPF_Fs192000_Gain15_A0,
+                    -HPF_Fs192000_Gain15_B1}
+#endif
+                    };
+#else
 FO_C16_LShx_Coefs_t    LVM_TrebleBoostCoefs[] = {
 
                     /* 22kHz sampling rate */
@@ -340,8 +675,9 @@
                     {HPF_Fs48000_Gain15_A1,             /* Gain setting 15 */
                      HPF_Fs48000_Gain15_A0,
                      -HPF_Fs48000_Gain15_B1,
-                     HPF_Fs48000_Gain15_Shift}};
-
+                     HPF_Fs48000_Gain15_Shift}
+                    };
+#endif
 
 /************************************************************************************/
 /*                                                                                    */
@@ -350,6 +686,16 @@
 /************************************************************************************/
 
 /* dB to linear conversion table */
+#ifdef BUILD_FLOAT
+const LVM_FLOAT LVM_VolumeTable[] = {
+    1.000f,             /*  0dB */
+    0.891f,             /* -1dB */
+    0.794f,             /* -2dB */
+    0.708f,             /* -3dB */
+    0.631f,             /* -4dB */
+    0.562f,             /* -5dB */
+    0.501f};            /* -6dB */
+#else
 const LVM_INT16 LVM_VolumeTable[] = {
     0x7FFF,             /*  0dB */
     0x7215,             /* -1dB */
@@ -358,6 +704,7 @@
     0x50C3,             /* -4dB */
     0x47FB,             /* -5dB */
     0x4000};            /* -6dB */
+#endif
 
 /************************************************************************************/
 /*                                                                                  */
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
index a7601ff..4cf7119 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
@@ -37,16 +37,23 @@
 /*                                                                                  */
 /************************************************************************************/
 
+#ifdef BUILD_FLOAT
+extern FO_FLOAT_LShx_Coefs_t     LVM_TrebleBoostCoefs[];
+#else
 extern FO_C16_LShx_Coefs_t     LVM_TrebleBoostCoefs[];
-
+#endif
 
 /************************************************************************************/
 /*                                                                                  */
 /*    Volume control gain and time constant tables                                  */
 /*                                                                                  */
 /************************************************************************************/
-
+#ifdef BUILD_FLOAT
+extern const LVM_FLOAT LVM_VolumeTable[];
+#else
 extern const LVM_INT16 LVM_VolumeTable[];
+#endif
+
 extern const LVM_INT16 LVM_MixerTCTable[];
 
 
diff --git a/media/libeffects/lvm/lib/Common/lib/AGC.h b/media/libeffects/lvm/lib/Common/lib/AGC.h
index 2080d64..9a3d35d 100644
--- a/media/libeffects/lvm/lib/Common/lib/AGC.h
+++ b/media/libeffects/lvm/lib/Common/lib/AGC.h
@@ -37,7 +37,7 @@
 /*    Types                                                                       */
 /*                                                                                */
 /**********************************************************************************/
-
+#ifndef BUILD_FLOAT
 typedef struct
 {
     LVM_INT32  AGC_Gain;                        /* The current AGC gain */
@@ -52,20 +52,39 @@
     LVM_INT16  VolumeTC;                        /* Volume update time constant */
 
 } AGC_MIX_VOL_2St1Mon_D32_t;
+#else
+typedef struct
+{
+    LVM_FLOAT  AGC_Gain;                        /* The current AGC gain */
+    LVM_FLOAT  AGC_MaxGain;                     /* The maximum AGC gain */
+    LVM_FLOAT  Volume;                          /* The current volume setting */
+    LVM_FLOAT  Target;                          /* The target volume setting */
+    LVM_FLOAT  AGC_Target;                      /* AGC target level */
+    LVM_FLOAT  AGC_Attack;                      /* AGC attack scaler */
+    LVM_FLOAT  AGC_Decay;                       /* AGC decay scaler */
+    LVM_FLOAT  VolumeTC;                        /* Volume update time constant */
 
+} AGC_MIX_VOL_2St1Mon_FLOAT_t;
+#endif
 
 /**********************************************************************************/
 /*                                                                                */
 /*    Function Prototypes                                                              */
 /*                                                                                */
 /**********************************************************************************/
-
+#ifdef BUILD_FLOAT
+void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t  *pInstance,     /* Instance pointer */
+                                 const LVM_FLOAT            *pStSrc,        /* Stereo source */
+                                 const LVM_FLOAT            *pMonoSrc,      /* Mono source */
+                                 LVM_FLOAT                  *pDst,          /* Stereo destination */
+                                 LVM_UINT16                 n);             /* Number of samples */
+#else
 void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t  *pInstance,     /* Instance pointer */
                                  const LVM_INT32            *pStSrc,        /* Stereo source */
                                  const LVM_INT32            *pMonoSrc,      /* Mono source */
                                  LVM_INT32                  *pDst,          /* Stereo destination */
                                  LVM_UINT16                 n);             /* Number of samples */
-
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
index 7ac7fbd..3ee7f63 100644
--- a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
+++ b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
@@ -27,19 +27,34 @@
 /**********************************************************************************
    INSTANCE MEMORY TYPE DEFINITION
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT Storage[6];
 
+} Biquad_FLOAT_Instance_t;
+#else
 typedef struct
 {
     LVM_INT32 Storage[6];
 
 } Biquad_Instance_t;
-
-
+#endif
 /**********************************************************************************
    COEFFICIENT TYPE DEFINITIONS
 ***********************************************************************************/
 
 /*** Biquad coefficients **********************************************************/
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT  A2;   /*  a2  */
+    LVM_FLOAT  A1;   /*  a1  */
+    LVM_FLOAT  A0;   /*  a0  */
+    LVM_FLOAT  B2;   /* -b2! */
+    LVM_FLOAT  B1;   /* -b1! */
+} BQ_FLOAT_Coefs_t;
+#else
 typedef struct
 {
     LVM_INT16 A2;   /*  a2  */
@@ -57,8 +72,17 @@
     LVM_INT32  B2;   /* -b2! */
     LVM_INT32  B1;   /* -b1! */
 } BQ_C32_Coefs_t;
+#endif
 
 /*** First order coefficients *****************************************************/
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT A1;   /*  a1  */
+    LVM_FLOAT A0;   /*  a0  */
+    LVM_FLOAT B1;   /* -b1! */
+} FO_FLOAT_Coefs_t;
+#else
 typedef struct
 {
     LVM_INT16 A1;   /*  a1  */
@@ -72,8 +96,17 @@
     LVM_INT32  A0;   /*  a0  */
     LVM_INT32  B1;   /* -b1! */
 } FO_C32_Coefs_t;
+#endif
 
 /*** First order coefficients with Shift*****************************************************/
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT A1;    /*  a1  */
+    LVM_FLOAT A0;    /*  a0  */
+    LVM_FLOAT B1;    /* -b1! */
+} FO_FLOAT_LShx_Coefs_t;
+#else
 typedef struct
 {
     LVM_INT16 A1;    /*  a1  */
@@ -81,8 +114,16 @@
     LVM_INT16 B1;    /* -b1! */
     LVM_INT16 Shift; /* Shift */
 } FO_C16_LShx_Coefs_t;
-
+#endif
 /*** Band pass coefficients *******************************************************/
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT  A0;   /*  a0  */
+    LVM_FLOAT  B2;   /* -b2! */
+    LVM_FLOAT  B1;   /* -b1! */
+} BP_FLOAT_Coefs_t;
+#else
 typedef struct
 {
     LVM_INT16 A0;   /*  a0  */
@@ -96,8 +137,18 @@
     LVM_INT32  B2;   /* -b2! */
     LVM_INT32  B1;   /* -b1! */
 } BP_C32_Coefs_t;
+#endif
 
 /*** Peaking coefficients *********************************************************/
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT A0;   /*  a0  */
+    LVM_FLOAT B2;   /* -b2! */
+    LVM_FLOAT B1;   /* -b1! */
+    LVM_FLOAT  G;   /* Gain */
+} PK_FLOAT_Coefs_t;
+#else
 typedef struct
 {
     LVM_INT16 A0;   /*  a0  */
@@ -113,16 +164,26 @@
     LVM_INT32  B1;   /* -b1! */
     LVM_INT16  G;   /* Gain */
 } PK_C32_Coefs_t;
-
+#endif
 
 /**********************************************************************************
    TAPS TYPE DEFINITIONS
 ***********************************************************************************/
 
 /*** Types used for first order and shelving filter *******************************/
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT Storage[ (1 * 2) ];  /* One channel, two taps of size LVM_INT32 */
+} Biquad_1I_Order1_FLOAT_Taps_t;
 
 typedef struct
 {
+    LVM_FLOAT Storage[ (2 * 2) ];  /* Two channels, two taps of size LVM_INT32 */
+} Biquad_2I_Order1_FLOAT_Taps_t;
+#else
+typedef struct
+{
     LVM_INT32 Storage[ (1*2) ];  /* One channel, two taps of size LVM_INT32 */
 } Biquad_1I_Order1_Taps_t;
 
@@ -130,12 +191,22 @@
 {
     LVM_INT32 Storage[ (2*2) ];  /* Two channels, two taps of size LVM_INT32 */
 } Biquad_2I_Order1_Taps_t;
-
+#endif
 
 /*** Types used for biquad, band pass and peaking filter **************************/
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT Storage[ (1 * 4) ];  /* One channel, four taps of size LVM_INT32 */
+} Biquad_1I_Order2_FLOAT_Taps_t;
 
 typedef struct
 {
+    LVM_FLOAT Storage[ (2 * 4) ];  /* Two channels, four taps of size LVM_INT32 */
+} Biquad_2I_Order2_FLOAT_Taps_t;
+#else
+typedef struct
+{
     LVM_INT32 Storage[ (1*4) ];  /* One channel, four taps of size LVM_INT32 */
 } Biquad_1I_Order2_Taps_t;
 
@@ -143,7 +214,7 @@
 {
     LVM_INT32 Storage[ (2*4) ];  /* Two channels, four taps of size LVM_INT32 */
 } Biquad_2I_Order2_Taps_t;
-
+#endif
 /* The names of the functions are changed to satisfy QAC rules: Name should be Unique withing 16 characters*/
 #define BQ_2I_D32F32Cll_TRC_WRA_01_Init  Init_BQ_2I_D32F32Cll_TRC_WRA_01
 #define BP_1I_D32F32C30_TRC_WRA_02       TWO_BP_1I_D32F32C30_TRC_WRA_02
@@ -154,59 +225,148 @@
 
 /*** 16 bit data path *************************************************************/
 
+
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef);
+#else
 void BQ_2I_D16F32Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
                                             Biquad_2I_Order2_Taps_t *pTaps,
                                             BQ_C16_Coefs_t          *pCoef);
+#endif
 
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+#else
 void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
                                             LVM_INT16                    *pDataIn,
                                             LVM_INT16                    *pDataOut,
                                             LVM_INT16                    NrSamples);
+#endif
 
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+#else
 void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
                                             LVM_INT16                    *pDataIn,
                                             LVM_INT16                    *pDataOut,
                                             LVM_INT16                    NrSamples);
 
+#endif
+
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+#else
 void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
                                             LVM_INT16                    *pDataIn,
                                             LVM_INT16                    *pDataOut,
                                             LVM_INT16                    NrSamples);
 
+#endif
+
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef);
+#else
 void BQ_2I_D16F16Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
                                             Biquad_2I_Order2_Taps_t *pTaps,
                                             BQ_C16_Coefs_t          *pCoef);
 
+#endif
+
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F16C15_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                                 LVM_FLOAT               *pDataIn,
+                                 LVM_FLOAT               *pDataOut,
+                                 LVM_INT16               NrSamples);
+#else
 void BQ_2I_D16F16C15_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
                                             LVM_INT16                   *pDataIn,
                                             LVM_INT16                   *pDataOut,
                                             LVM_INT16                   NrSamples);
 
+#endif
+
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F16C14_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                                 LVM_FLOAT               *pDataIn,
+                                 LVM_FLOAT               *pDataOut,
+                                 LVM_INT16               NrSamples);
+#else
 void BQ_2I_D16F16C14_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
                                             LVM_INT16                   *pDataIn,
                                             LVM_INT16                   *pDataOut,
                                             LVM_INT16                   NrSamples);
+#endif
 
+#ifdef BUILD_FLOAT
+void BQ_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef);
+#else
 void BQ_1I_D16F16Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
                                             Biquad_1I_Order2_Taps_t *pTaps,
                                             BQ_C16_Coefs_t          *pCoef);
 
+#endif
+
+#ifdef BUILD_FLOAT
+void BQ_1I_D16F16C15_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples);
+#else
 void BQ_1I_D16F16C15_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
                                             LVM_INT16                   *pDataIn,
                                             LVM_INT16                   *pDataOut,
                                             LVM_INT16                   NrSamples);
 
+#endif
+
+#ifdef BUILD_FLOAT
+void BQ_1I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef);
+#else
 void BQ_1I_D16F32Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
                                             Biquad_1I_Order2_Taps_t *pTaps,
                                             BQ_C16_Coefs_t          *pCoef);
 
+#endif
+
+#ifdef BUILD_FLOAT
+void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT              *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples);
+#else
 void BQ_1I_D16F32C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
                                             LVM_INT16                    *pDataIn,
                                             LVM_INT16                    *pDataOut,
                                             LVM_INT16                    NrSamples);
 
+#endif
 /*** 32 bit data path *************************************************************/
-
+#ifdef BUILD_FLOAT
+void BQ_2I_D32F32Cll_TRC_WRA_01_Init (      Biquad_FLOAT_Instance_t       *pInstance,
+                                            Biquad_2I_Order2_FLOAT_Taps_t *pTaps,
+                                            BQ_FLOAT_Coefs_t          *pCoef);
+void BQ_2I_D32F32C30_TRC_WRA_01 (           Biquad_FLOAT_Instance_t  *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                 NrSamples);
+#else
 void BQ_2I_D32F32Cll_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
                                             Biquad_2I_Order2_Taps_t *pTaps,
                                             BQ_C32_Coefs_t          *pCoef);
@@ -215,33 +375,66 @@
                                             LVM_INT32                    *pDataIn,
                                             LVM_INT32                    *pDataOut,
                                             LVM_INT16                    NrSamples);
+#endif
 
 /**********************************************************************************
    FUNCTION PROTOTYPES: FIRST ORDER FILTERS
 ***********************************************************************************/
 
 /*** 16 bit data path *************************************************************/
-
+#ifdef BUILD_FLOAT
+void FO_1I_D16F16Css_TRC_WRA_01_Init(    Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order1_FLOAT_Taps_t   *pTaps,
+                                         FO_FLOAT_Coefs_t            *pCoef);
+#else
 void FO_1I_D16F16Css_TRC_WRA_01_Init(       Biquad_Instance_t       *pInstance,
                                             Biquad_1I_Order1_Taps_t *pTaps,
                                             FO_C16_Coefs_t          *pCoef);
+#endif
 
+#ifdef BUILD_FLOAT
+void FO_1I_D16F16C15_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                                 LVM_FLOAT               *pDataIn,
+                                 LVM_FLOAT               *pDataOut,
+                                 LVM_INT16               NrSamples);
+#else
 void FO_1I_D16F16C15_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
                                             LVM_INT16                   *pDataIn,
                                             LVM_INT16                   *pDataOut,
                                             LVM_INT16                   NrSamples);
+#endif
 
+#ifdef BUILD_FLOAT
+void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t       *pInstance,
+                                          Biquad_2I_Order1_FLOAT_Taps_t *pTaps,
+                                          FO_FLOAT_LShx_Coefs_t     *pCoef);
+#else
 void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_Instance_t       *pInstance,
                                           Biquad_2I_Order1_Taps_t *pTaps,
                                           FO_C16_LShx_Coefs_t     *pCoef);
+#endif
 
+#ifdef BUILD_FLOAT
+void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t       *pInstance,
+                                     LVM_FLOAT               *pDataIn,
+                                     LVM_FLOAT               *pDataOut,
+                                     LVM_INT16               NrSamples);
+#else
 void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_Instance_t       *pInstance,
                                      LVM_INT16               *pDataIn,
                                      LVM_INT16               *pDataOut,
                                      LVM_INT16               NrSamples);
-
+#endif
 /*** 32 bit data path *************************************************************/
-
+#ifdef BUILD_FLOAT
+void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_FLOAT_Instance_t       *pInstance,
+                                      Biquad_1I_Order1_FLOAT_Taps_t *pTaps,
+                                      FO_FLOAT_Coefs_t          *pCoef);
+void FO_1I_D32F32C31_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                                 LVM_FLOAT                     *pDataIn,
+                                 LVM_FLOAT                     *pDataOut,
+                                 LVM_INT16                     NrSamples);
+#else
 void FO_1I_D32F32Cll_TRC_WRA_01_Init(       Biquad_Instance_t       *pInstance,
                                             Biquad_1I_Order1_Taps_t *pTaps,
                                             FO_C32_Coefs_t          *pCoef);
@@ -250,13 +443,28 @@
                                             LVM_INT32               *pDataIn,
                                             LVM_INT32               *pDataOut,
                                             LVM_INT16               NrSamples);
-
+#endif
 /**********************************************************************************
    FUNCTION PROTOTYPES: BAND PASS FILTERS
 ***********************************************************************************/
 
 /*** 16 bit data path *************************************************************/
-
+#ifdef BUILD_FLOAT
+void BP_1I_D16F16Css_TRC_WRA_01_Init( Biquad_FLOAT_Instance_t       *pInstance,
+                                      Biquad_1I_Order2_FLOAT_Taps_t *pTaps,
+                                      BP_FLOAT_Coefs_t              *pCoef);
+void BP_1I_D16F16C14_TRC_WRA_01 (     Biquad_FLOAT_Instance_t       *pInstance,
+                                      LVM_FLOAT                     *pDataIn,
+                                      LVM_FLOAT                     *pDataOut,
+                                      LVM_INT16                     NrSamples);
+void BP_1I_D16F32Cll_TRC_WRA_01_Init (Biquad_FLOAT_Instance_t       *pInstance,
+                                      Biquad_1I_Order2_FLOAT_Taps_t *pTaps,
+                                      BP_FLOAT_Coefs_t              *pCoef);
+void BP_1I_D16F32C30_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+#else
 void BP_1I_D16F16Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
                                             Biquad_1I_Order2_Taps_t *pTaps,
                                             BP_C16_Coefs_t          *pCoef);
@@ -274,10 +482,17 @@
                                             LVM_INT16                    *pDataIn,
                                             LVM_INT16                    *pDataOut,
                                             LVM_INT16                    NrSamples);
-
-
+#endif
 /*** 32 bit data path *************************************************************/
-
+#ifdef BUILD_FLOAT
+void BP_1I_D32F32Cll_TRC_WRA_02_Init (      Biquad_FLOAT_Instance_t       *pInstance,
+                                            Biquad_1I_Order2_FLOAT_Taps_t *pTaps,
+                                            BP_FLOAT_Coefs_t          *pCoef);
+void BP_1I_D32F32C30_TRC_WRA_02(            Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+#else
 void BP_1I_D32F32Cll_TRC_WRA_02_Init (      Biquad_Instance_t       *pInstance,
                                             Biquad_1I_Order2_Taps_t *pTaps,
                                             BP_C32_Coefs_t          *pCoef);
@@ -286,42 +501,59 @@
                                             LVM_INT32                    *pDataIn,
                                             LVM_INT32                    *pDataOut,
                                             LVM_INT16                    NrSamples);
-
+#endif
 
 /*** 32 bit data path STEREO ******************************************************/
-
+#ifndef BUILD_FLOAT
 void PK_2I_D32F32CllGss_TRC_WRA_01_Init (   Biquad_Instance_t       *pInstance,
                                             Biquad_2I_Order2_Taps_t *pTaps,
                                             PK_C32_Coefs_t          *pCoef);
-
 void PK_2I_D32F32C30G11_TRC_WRA_01 (        Biquad_Instance_t       *pInstance,
                                             LVM_INT32                    *pDataIn,
                                             LVM_INT32                    *pDataOut,
                                             LVM_INT16                    NrSamples);
-
+#endif
+#ifdef BUILD_FLOAT
+void PK_2I_D32F32CssGss_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t       *pInstance,
+                                            Biquad_2I_Order2_FLOAT_Taps_t *pTaps,
+                                            PK_FLOAT_Coefs_t          *pCoef);
+#else
 void PK_2I_D32F32CssGss_TRC_WRA_01_Init (   Biquad_Instance_t       *pInstance,
                                             Biquad_2I_Order2_Taps_t *pTaps,
                                             PK_C16_Coefs_t          *pCoef);
-
+#endif
+#ifdef BUILD_FLOAT
+void PK_2I_D32F32C14G11_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                                    LVM_FLOAT               *pDataIn,
+                                    LVM_FLOAT               *pDataOut,
+                                    LVM_INT16               NrSamples);
+#else
 void PK_2I_D32F32C14G11_TRC_WRA_01 (        Biquad_Instance_t       *pInstance,
                                             LVM_INT32                    *pDataIn,
                                             LVM_INT32                    *pDataOut,
                                             LVM_INT16                    NrSamples);
-
+#endif
 
 /**********************************************************************************
    FUNCTION PROTOTYPES: DC REMOVAL FILTERS
 ***********************************************************************************/
 
 /*** 16 bit data path STEREO ******************************************************/
+#ifdef BUILD_FLOAT
+void DC_2I_D16_TRC_WRA_01_Init     (        Biquad_FLOAT_Instance_t       *pInstance);
 
+void DC_2I_D16_TRC_WRA_01          (        Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT               *pDataIn,
+                                            LVM_FLOAT               *pDataOut,
+                                            LVM_INT16               NrSamples);
+#else
 void DC_2I_D16_TRC_WRA_01_Init     (        Biquad_Instance_t       *pInstance);
 
 void DC_2I_D16_TRC_WRA_01          (        Biquad_Instance_t       *pInstance,
                                             LVM_INT16               *pDataIn,
                                             LVM_INT16               *pDataOut,
                                             LVM_INT16               NrSamples);
-
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/Common/lib/CompLim.h b/media/libeffects/lvm/lib/Common/lib/CompLim.h
index 4cb8aa2..498faa3 100644
--- a/media/libeffects/lvm/lib/Common/lib/CompLim.h
+++ b/media/libeffects/lvm/lib/Common/lib/CompLim.h
@@ -66,13 +66,17 @@
 /*  Function Prototypes                                                             */
 /*                                                                                  */
 /************************************************************************************/
-
+#ifdef BUILD_FLOAT
+void NonLinComp_Float(LVM_FLOAT        Gain,
+                      LVM_FLOAT        *pDataIn,
+                      LVM_FLOAT        *pDataOut,
+                      LVM_INT32        BlockLength);
+#else
 void NonLinComp_D16(LVM_INT16        Gain,
                     LVM_INT16        *pSterBfIn,
                     LVM_INT16        *pSterBfOut,
                     LVM_INT32        BlockLength);
-
-
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/Common/lib/Filter.h b/media/libeffects/lvm/lib/Common/lib/Filter.h
index 229701a..0c8955d 100644
--- a/media/libeffects/lvm/lib/Common/lib/Filter.h
+++ b/media/libeffects/lvm/lib/Common/lib/Filter.h
@@ -33,11 +33,32 @@
    DEFINES
 ***********************************************************************************/
 #define FILTER_LOSS     32730       /* -0.01dB loss to avoid wrapping due to band ripple */
-
+#ifdef BUILD_FLOAT
+#define FILTER_LOSS_FLOAT    0.998849f
+#endif
 /**********************************************************************************
    FUNCTION PROTOTYPES
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
 
+LVM_FLOAT LVM_Power10(   LVM_FLOAT  X);
+
+LVM_FLOAT LVM_Polynomial(LVM_UINT16 N,
+                         LVM_FLOAT  *pCoefficients,
+                         LVM_FLOAT  X);
+#ifdef HIGHER_FS
+LVM_FLOAT   LVM_GetOmega(LVM_UINT32  Fc,
+#else
+LVM_FLOAT   LVM_GetOmega(LVM_UINT16  Fc,
+#endif
+                         LVM_Fs_en   SampleRate);
+
+LVM_FLOAT LVM_FO_LPF(    LVM_FLOAT  w,
+                         FO_FLOAT_Coefs_t  *pCoeffs);
+
+LVM_FLOAT LVM_FO_HPF(    LVM_FLOAT  w,
+                         FO_FLOAT_Coefs_t  *pCoeffs);
+#else
 LVM_INT32 LVM_Polynomial(LVM_UINT16 N,
                          LVM_INT32  *pCoefficients,
                          LVM_INT32  X);
@@ -52,7 +73,7 @@
 
 LVM_INT32   LVM_GetOmega(LVM_UINT16  Fc,
                          LVM_Fs_en   SampleRate);
-
+#endif
 /**********************************************************************************/
 #ifdef __cplusplus
 }
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index 68c55f7..cb15b60 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -44,6 +44,9 @@
 
 #define LVM_MAXINT_8            127                 /* Maximum positive integer size */
 #define LVM_MAXINT_16           32767
+#ifdef BUILD_FLOAT
+#define LVM_MAXFLOAT            1.0f
+#endif
 #define LVM_MAXINT_32           2147483647
 #define LVM_MAXENUM             2147483647
 
@@ -95,7 +98,9 @@
 typedef     int32_t             LVM_INT32;          /* Signed 32-bit word */
 typedef     uint32_t            LVM_UINT32;         /* Unsigned 32-bit word */
 
-
+#ifdef BUILD_FLOAT
+typedef     float               LVM_FLOAT;          /* single precission floating point*/
+#endif
 /****************************************************************************************/
 /*                                                                                      */
 /*  Standard Enumerated types                                                           */
@@ -133,6 +138,10 @@
     LVM_FS_32000 = 6,
     LVM_FS_44100 = 7,
     LVM_FS_48000 = 8,
+#ifdef HIGHER_FS
+    LVM_FS_96000 = 9,
+    LVM_FS_192000 = 10,
+#endif
     LVM_FS_INVALID = LVM_MAXENUM-1,
     LVM_FS_DUMMY = LVM_MAXENUM
 } LVM_Fs_en;
diff --git a/media/libeffects/lvm/lib/Common/lib/Mixer.h b/media/libeffects/lvm/lib/Common/lib/Mixer.h
index 89deb0d..07c53cd 100644
--- a/media/libeffects/lvm/lib/Common/lib/Mixer.h
+++ b/media/libeffects/lvm/lib/Common/lib/Mixer.h
@@ -30,6 +30,43 @@
    INSTANCE MEMORY TYPE DEFINITION
 ***********************************************************************************/
 
+#ifdef BUILD_FLOAT /* BUILD_FLOAT*/
+typedef struct
+{
+    LVM_FLOAT   Alpha;                   /* Time constant. Set by calling application. \
+                                            Can be changed at any time */
+    LVM_FLOAT   Target;                  /* Target value.  Set by calling application. \
+                                            Can be changed at any time */
+    LVM_FLOAT   Current;                 /* Current value.  Set by the mixer function. */
+    LVM_INT16   CallbackSet;             /* Boolean.  Should be set by calling application \
+                                            each time the target value is updated */
+    LVM_INT16   CallbackParam;           /* Parameter that will be used in the calback function */
+    void        *pCallbackHandle;        /* Pointer to the instance of the callback function */
+    void        *pGeneralPurpose;        /* Pointer for general purpose usage */
+    LVM_Callback pCallBack;              /* Pointer to the callback function */
+} Mix_1St_Cll_FLOAT_t;
+typedef struct
+{
+    LVM_FLOAT   Alpha1;
+    LVM_FLOAT   Target1;
+    LVM_FLOAT   Current1;
+    LVM_INT16   CallbackSet1;
+    LVM_INT16   CallbackParam1;
+    void        *pCallbackHandle1;
+    void        *pGeneralPurpose1;
+    LVM_Callback pCallBack1;
+
+    LVM_FLOAT   Alpha2;                   /* Warning the address of this location is passed as a \
+                                             pointer to Mix_1St_Cll_t in some functions */
+    LVM_FLOAT   Target2;
+    LVM_FLOAT   Current2;
+    LVM_INT16   CallbackSet2;
+    LVM_INT16   CallbackParam2;
+    void        *pCallbackHandle2;
+    void        *pGeneralPurpose2;
+    LVM_Callback pCallBack2;
+} Mix_2St_Cll_FLOAT_t;
+#else
 typedef struct
 {
     LVM_INT32   Alpha;                    /* Time constant. Set by calling application.  Can be changed at any time */
@@ -64,9 +101,35 @@
 
 } Mix_2St_Cll_t;
 
+#endif
 
 /*** General functions ************************************************************/
+#ifdef BUILD_FLOAT
 
+LVM_FLOAT LVM_Mixer_TimeConstant(LVM_UINT32   tc,
+#ifdef HIGHER_FS
+                                 LVM_UINT32   Fs,
+#else
+                                 LVM_UINT16   Fs,
+#endif
+                                 LVM_UINT16   NumChannels);
+
+void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_FLOAT_t       *pInstance,
+                                const LVM_FLOAT     *src,
+                                LVM_FLOAT     *dst,
+                                LVM_INT16     n);
+
+void MixSoft_2St_D32C31_SAT(    Mix_2St_Cll_FLOAT_t       *pInstance,
+                                const LVM_FLOAT     *src1,
+                                const LVM_FLOAT     *src2,
+                                LVM_FLOAT     *dst,
+                                LVM_INT16     n);
+
+void MixInSoft_D32C31_SAT(      Mix_1St_Cll_FLOAT_t       *pInstance,
+                                const LVM_FLOAT     *src,
+                                LVM_FLOAT     *dst,
+                                LVM_INT16     n);
+#else
 LVM_UINT32 LVM_Mixer_TimeConstant(LVM_UINT32   tc,
                                   LVM_UINT16   Fs,
                                   LVM_UINT16   NumChannels);
@@ -88,10 +151,26 @@
                                       LVM_INT32     *dst,
                                       LVM_INT16     n);
 
+#endif
+
 /**********************************************************************************
    FUNCTION PROTOTYPES (LOW LEVEL SUBFUNCTIONS)
 ***********************************************************************************/
-
+#ifdef BUILD_FLOAT
+void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_FLOAT_t       *pInstance,
+                                    const LVM_FLOAT     *src,
+                                    LVM_FLOAT     *dst,
+                                    LVM_INT16     n);
+void Core_MixHard_2St_D32C31_SAT(   Mix_2St_Cll_FLOAT_t       *pInstance,
+                                    const LVM_FLOAT     *src1,
+                                    const LVM_FLOAT     *src2,
+                                    LVM_FLOAT     *dst,
+                                    LVM_INT16     n);
+void Core_MixInSoft_D32C31_SAT(     Mix_1St_Cll_FLOAT_t       *pInstance,
+                                    const LVM_FLOAT     *src,
+                                    LVM_FLOAT     *dst,
+                                    LVM_INT16     n);
+#else
 void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_t       *pInstance,
                                     const LVM_INT32     *src,
                                           LVM_INT32     *dst,
@@ -107,6 +186,7 @@
                                     const LVM_INT32     *src,
                                           LVM_INT32     *dst,
                                           LVM_INT16     n);
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
@@ -115,13 +195,3 @@
 /**********************************************************************************/
 
 #endif /* __MIXER_H__ */
-
-
-
-
-
-
-
-
-
-
diff --git a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
index 3d62704..cdb3837 100644
--- a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
@@ -34,7 +34,12 @@
 /*######################################################################################*/
 
 /* Absolute value including the corner case for the extreme negative value */
+
+#ifdef BUILD_FLOAT
+LVM_FLOAT   Abs_Float(LVM_FLOAT     input);
+#else
 LVM_INT32   Abs_32(LVM_INT32     input);
+#endif
 
 /****************************************************************************************
  *  Name        : dB_to_Lin32()
@@ -48,8 +53,11 @@
  *                  (15->01) = decimal part
  *  Returns     : Lin value format 1.16.15
  ****************************************************************************************/
-
+#ifdef BUILD_FLOAT
+LVM_FLOAT dB_to_LinFloat(LVM_INT16    db_fix);
+#else
 LVM_INT32 dB_to_Lin32(LVM_INT16  db_fix);
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
index 2b791bd..0ba20a3 100644
--- a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
@@ -29,6 +29,11 @@
     VARIOUS FUNCTIONS
 ***********************************************************************************/
 
+#ifdef BUILD_FLOAT
+void LoadConst_Float(          const LVM_FLOAT val,
+                               LVM_FLOAT *dst,
+                               LVM_INT16 n );
+#else
 void LoadConst_16(            const LVM_INT16 val,
                                     LVM_INT16 *dst,
                                     LVM_INT16 n );
@@ -36,10 +41,17 @@
 void LoadConst_32(            const LVM_INT32 val,
                                     LVM_INT32 *dst,
                                     LVM_INT16 n );
+#endif
 
+#ifdef BUILD_FLOAT
+void Copy_Float(                 const LVM_FLOAT *src,
+                                 LVM_FLOAT *dst,
+                                 LVM_INT16 n );
+#else
 void Copy_16(                 const LVM_INT16 *src,
                                     LVM_INT16 *dst,
                                     LVM_INT16 n );
+#endif
 
 /*********************************************************************************
  * note: In Mult3s_16x16() saturation of result is not taken care when           *
@@ -49,10 +61,17 @@
  *       This is the only case which will give wrong result.                     *
  *       For more information refer to Vector_Arithmetic.doc in /doc folder      *
  *********************************************************************************/
+#ifdef BUILD_FLOAT
+void Mult3s_Float(            const LVM_FLOAT *src,
+                              const LVM_FLOAT val,
+                              LVM_FLOAT *dst,
+                              LVM_INT16 n);
+#else
 void Mult3s_16x16(            const LVM_INT16 *src,
                               const LVM_INT16 val,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 n);
+                              LVM_INT16 *dst,
+                              LVM_INT16 n);
+#endif
 
 /*********************************************************************************
  * note: In Mult3s_32x16() saturation of result is not taken care when           *
@@ -66,20 +85,31 @@
                               const LVM_INT16 val,
                                     LVM_INT32  *dst,
                                     LVM_INT16 n);
-
+#ifdef BUILD_FLOAT
+void DelayMix_Float(const LVM_FLOAT *src,           /* Source 1, to be delayed */
+                    LVM_FLOAT *delay,         /* Delay buffer */
+                    LVM_INT16 size,           /* Delay size */
+                    LVM_FLOAT *dst,           /* Source/destination */
+                    LVM_INT16 *pOffset,       /* Delay offset */
+                    LVM_INT16 n)  ;            /* Number of stereo samples */
+#else
 void DelayMix_16x16(          const LVM_INT16 *src,
                                     LVM_INT16 *delay,
                                     LVM_INT16 size,
                                     LVM_INT16 *dst,
                                     LVM_INT16 *pOffset,
                                     LVM_INT16 n);
-
+#endif
 void DelayWrite_32(           const LVM_INT32  *src,               /* Source 1, to be delayed */
                                     LVM_INT32  *delay,             /* Delay buffer */
                                     LVM_UINT16 size,               /* Delay size */
                                     LVM_UINT16 *pOffset,           /* Delay offset */
                                     LVM_INT16 n);
-
+#ifdef BUILD_FLOAT
+void Add2_Sat_Float(          const LVM_FLOAT *src,
+                              LVM_FLOAT *dst,
+                              LVM_INT16 n );
+#else
 void Add2_Sat_16x16(          const LVM_INT16 *src,
                                     LVM_INT16 *dst,
                                     LVM_INT16 n );
@@ -87,7 +117,13 @@
 void Add2_Sat_32x32(          const LVM_INT32  *src,
                                     LVM_INT32  *dst,
                                     LVM_INT16 n );
-
+#endif
+#ifdef BUILD_FLOAT
+void Mac3s_Sat_Float(         const LVM_FLOAT *src,
+                              const LVM_FLOAT val,
+                              LVM_FLOAT *dst,
+                              LVM_INT16 n);
+#else
 void Mac3s_Sat_16x16(         const LVM_INT16 *src,
                               const LVM_INT16 val,
                                     LVM_INT16 *dst,
@@ -97,7 +133,7 @@
                               const LVM_INT16 val,
                                     LVM_INT32  *dst,
                                     LVM_INT16 n);
-
+#endif
 void DelayAllPass_Sat_32x16To32(    LVM_INT32  *delay,              /* Delay buffer */
                                     LVM_UINT16 size,                /* Delay size */
                                     LVM_INT16 coeff,                /* All pass filter coefficient */
@@ -109,7 +145,12 @@
 /**********************************************************************************
     SHIFT FUNCTIONS
 ***********************************************************************************/
-
+#ifdef BUILD_FLOAT
+void Shift_Sat_Float (const   LVM_INT16   val,
+                      const   LVM_FLOAT   *src,
+                      LVM_FLOAT   *dst,
+                      LVM_INT16   n);
+#else
 void Shift_Sat_v16xv16 (      const LVM_INT16 val,
                               const LVM_INT16 *src,
                                     LVM_INT16 *dst,
@@ -119,11 +160,15 @@
                               const LVM_INT32 *src,
                                     LVM_INT32 *dst,
                                     LVM_INT16 n);
-
+#endif
 /**********************************************************************************
     AUDIO FORMAT CONVERSION FUNCTIONS
 ***********************************************************************************/
-
+#ifdef BUILD_FLOAT
+void MonoTo2I_Float( const LVM_FLOAT     *src,
+                     LVM_FLOAT     *dst,
+                     LVM_INT16 n);
+#else
 void MonoTo2I_16(             const LVM_INT16 *src,
                                     LVM_INT16 *dst,
                                     LVM_INT16 n);
@@ -131,29 +176,52 @@
 void MonoTo2I_32(             const LVM_INT32  *src,
                                     LVM_INT32  *dst,
                                     LVM_INT16 n);
-
+#endif
+#ifdef BUILD_FLOAT
+void From2iToMono_Float(         const LVM_FLOAT  *src,
+                                 LVM_FLOAT  *dst,
+                                 LVM_INT16 n);
+#else
 void From2iToMono_32(         const LVM_INT32  *src,
                                     LVM_INT32  *dst,
                                     LVM_INT16 n);
-
+#endif
+#ifdef BUILD_FLOAT
+void MSTo2i_Sat_Float(        const LVM_FLOAT *srcM,
+                              const LVM_FLOAT *srcS,
+                              LVM_FLOAT *dst,
+                              LVM_INT16 n );
+#else
 void MSTo2i_Sat_16x16(        const LVM_INT16 *srcM,
                               const LVM_INT16 *srcS,
                                     LVM_INT16 *dst,
                                     LVM_INT16 n );
-
+#endif
+#ifdef BUILD_FLOAT
+void From2iToMS_Float(        const LVM_FLOAT *src,
+                              LVM_FLOAT *dstM,
+                              LVM_FLOAT *dstS,
+                              LVM_INT16 n );
+#else
 void From2iToMS_16x16(        const LVM_INT16 *src,
                                     LVM_INT16 *dstM,
                                     LVM_INT16 *dstS,
                                     LVM_INT16 n );
-
+#endif
+#ifdef BUILD_FLOAT
+void JoinTo2i_Float(          const LVM_FLOAT  *srcL,
+                              const LVM_FLOAT  *srcR,
+                              LVM_FLOAT  *dst,
+                              LVM_INT16 n );
+#else
 void From2iToMono_16(         const LVM_INT16 *src,
                                     LVM_INT16 *dst,
                                     LVM_INT16 n);
-
 void JoinTo2i_32x32(          const LVM_INT32  *srcL,
                               const LVM_INT32  *srcR,
-                                    LVM_INT32  *dst,
-                                    LVM_INT16 n );
+                              LVM_INT32  *dst,
+                              LVM_INT16 n );
+#endif
 
 /**********************************************************************************
     DATA TYPE CONVERSION FUNCTIONS
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
index 920b515..fa9f01f 100644
--- a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
+++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
@@ -33,7 +33,10 @@
 
 #define VOL_TC_SHIFT                                        21          /* As a power of 2 */
 #define DECAY_SHIFT                                        10           /* As a power of 2 */
-
+#ifdef BUILD_FLOAT
+#define VOL_TC_FLOAT                                      2.0f          /* As a power of 2 */
+#define DECAY_FAC_FLOAT                                  64.0f          /* As a power of 2 */
+#endif
 
 /****************************************************************************************/
 /*                                                                                      */
@@ -69,7 +72,7 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
-
+#ifndef BUILD_FLOAT
 void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t  *pInstance,     /* Instance pointer */
                                  const LVM_INT32            *pStSrc,        /* Stereo source */
                                  const LVM_INT32            *pMonoSrc,      /* Mono source */
@@ -193,4 +196,113 @@
 
     return;
 }
+#else
+void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t  *pInstance,     /* Instance pointer */
+                                 const LVM_FLOAT            *pStSrc,        /* Stereo source */
+                                 const LVM_FLOAT            *pMonoSrc,      /* Mono source */
+                                 LVM_FLOAT                  *pDst,          /* Stereo destination */
+                                 LVM_UINT16                 NumSamples)     /* Number of samples */
+{
 
+    /*
+     * General variables
+     */
+    LVM_UINT16      i;                                          /* Sample index */
+    LVM_FLOAT       Left;                                       /* Left sample */
+    LVM_FLOAT       Right;                                      /* Right sample */
+    LVM_FLOAT       Mono;                                       /* Mono sample */
+    LVM_FLOAT       AbsPeak;                                    /* Absolute peak signal */
+    LVM_FLOAT       AGC_Mult;                                   /* Short AGC gain */
+    LVM_FLOAT       Vol_Mult;                                   /* Short volume */
+
+
+    /*
+     * Instance control variables
+     */
+    LVM_FLOAT      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
+    LVM_FLOAT      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
+    LVM_FLOAT      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
+    LVM_FLOAT      AGC_Decay     = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));/* Decay scaler */
+    LVM_FLOAT      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
+    LVM_FLOAT      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
+    LVM_FLOAT      Vol_Target    = pInstance->Target;           /* Target volume setting */
+    LVM_FLOAT      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
+
+
+    /*
+     * Process on a sample by sample basis
+     */
+    for (i = 0; i < NumSamples; i++)                                  /* For each sample */
+    {
+
+        /*
+         * Get the short scalers
+         */
+        AGC_Mult    = (LVM_FLOAT)(AGC_Gain);              /* Get the short AGC gain */
+        Vol_Mult    = (LVM_FLOAT)(Vol_Current);           /* Get the short volume gain */
+
+
+        /*
+         * Get the input samples
+         */
+        Left  = *pStSrc++;                                      /* Get the left sample */
+        Right = *pStSrc++;                                      /* Get the right sample */
+        Mono  = *pMonoSrc++;                                    /* Get the mono sample */
+
+
+        /*
+         * Apply the AGC gain to the mono input and mix with the stereo signal
+         */
+        Left  += (Mono * AGC_Mult);                               /* Mix in the mono signal */
+        Right += (Mono * AGC_Mult);
+
+        /*
+         * Apply the volume and write to the output stream
+         */
+        Left  = Left  * Vol_Mult;
+        Right = Right * Vol_Mult;
+        *pDst++ = Left;                                         /* Save the results */
+        *pDst++ = Right;
+
+        /*
+         * Update the AGC gain
+         */
+        AbsPeak = Abs_Float(Left) > Abs_Float(Right) ? Abs_Float(Left) : Abs_Float(Right);
+        if (AbsPeak > AGC_Target)
+        {
+            /*
+             * The signal is too large so decrease the gain
+             */
+            AGC_Gain = AGC_Gain * AGC_Attack;
+        }
+        else
+        {
+            /*
+             * The signal is too small so increase the gain
+             */
+            if (AGC_Gain > AGC_MaxGain)
+            {
+                AGC_Gain -= (AGC_Decay);
+            }
+            else
+            {
+                AGC_Gain += (AGC_Decay);
+            }
+        }
+
+        /*
+         * Update the gain
+         */
+        Vol_Current +=  (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
+    }
+
+
+    /*
+     * Update the parameters
+     */
+    pInstance->Volume = Vol_Current;                            /* Actual volume setting */
+    pInstance->AGC_Gain = AGC_Gain;
+
+    return;
+}
+#endif /*BUILD_FLOAT*/
diff --git a/media/libeffects/lvm/lib/Common/src/Abs_32.c b/media/libeffects/lvm/lib/Common/src/Abs_32.c
index 9128b82..84fabd8 100644
--- a/media/libeffects/lvm/lib/Common/src/Abs_32.c
+++ b/media/libeffects/lvm/lib/Common/src/Abs_32.c
@@ -47,4 +47,14 @@
     }
     return input;
 }
-
+#ifdef BUILD_FLOAT
+LVM_FLOAT    Abs_Float(LVM_FLOAT    input)
+{
+    if(input <  0)
+    {
+        /* Negative input, so invert */
+        input = (LVM_FLOAT)(-input);
+    }
+    return input;
+}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
index 69d357e..e3edccc 100644
--- a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
@@ -57,4 +57,33 @@
     return;
 }
 
+#ifdef BUILD_FLOAT
+void Add2_Sat_Float( const LVM_FLOAT  *src,
+                           LVM_FLOAT  *dst,
+                           LVM_INT16  n )
+{
+    LVM_FLOAT Temp;
+    LVM_INT16 ii;
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = ((LVM_FLOAT) *src) + ((LVM_FLOAT) *dst);
+        src++;
+
+        if (Temp > 1.000000f)
+        {
+            *dst = 1.000000f;
+        }
+        else if (Temp < -1.000000f)
+        {
+            *dst = -1.000000f;
+        }
+        else
+        {
+            *dst = Temp;
+        }
+        dst++;
+    }
+    return;
+}
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c
index f4c5757..88f9986 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c
@@ -33,7 +33,51 @@
  pBiquadState->pDelays[2] is y(n-1)L in Q0 format
  pBiquadState->pDelays[3] is y(n-2)L in Q0 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BP_1I_D16F16C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
 
+
+    {
+        LVM_FLOAT ynL;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL= (A0  * (x(n)L  - x(n-2)L  ) )
+            ynL = pBiquadState->coefs[0] * ((*pDataIn)-pBiquadState->pDelays[1]);
+
+            // ynL+= ((-B2  * y(n-2)L  ) )
+            ynL += pBiquadState->coefs[1] * pBiquadState->pDelays[3];
+
+            // ynL+= ((-B1  * y(n-1)L  ) )
+            ynL += pBiquadState->coefs[2] * pBiquadState->pDelays[2];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=ynL; // Write Left output
+
+        }
+
+    }
+#else
 void BP_1I_D16F16C14_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
                                   LVM_INT16               *pDataIn,
                                   LVM_INT16               *pDataOut,
@@ -78,4 +122,5 @@
         }
 
     }
+#endif
 
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
index 88914ad..27ab57a 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -38,6 +38,19 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void BP_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t          *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t    *pTaps,
+                                         BP_FLOAT_Coefs_t                  *pCoef)
+{
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps;
+
+    pBiquadState->coefs[0] = pCoef->A0;
+    pBiquadState->coefs[1] = pCoef->B2;
+    pBiquadState->coefs[2] = pCoef->B1;
+}
+#else
 void BP_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
                                          Biquad_1I_Order2_Taps_t   *pTaps,
                                          BP_C16_Coefs_t            *pCoef)
@@ -49,6 +62,7 @@
   pBiquadState->coefs[1]=pCoef->B2;
   pBiquadState->coefs[2]=pCoef->B1;
   }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BP_1I_D16F16Css_TRC_WRA_01_Init.c                              */
 
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
index 980539c..e194f92 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -27,4 +27,13 @@
 
 typedef Filter_State * PFilter_State ;
 
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT
+{
+
+    LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+    LVM_FLOAT         coefs[3];       /* pointer to the filter coefficients */
+}Filter_State_FLOAT;
+typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
+#endif
 #endif /*_BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c
index ba1a42f..3abdd43 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c
@@ -33,7 +33,48 @@
  pBiquadState->pDelays[2] is y(n-1)L in Q16 format
  pBiquadState->pDelays[3] is y(n-2)L in Q16 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BP_1I_D16F32C30_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+{
+    LVM_FLOAT ynL,templ;
+    LVM_INT16 ii;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
 
+    for (ii = NrSamples; ii != 0; ii--)
+    {
+        /**************************************************************************
+                       PROCESSING OF THE LEFT CHANNEL
+        ***************************************************************************/
+        // ynL= (A0 * (x(n)L - x(n-2)L ))
+        templ = (LVM_FLOAT) *pDataIn - pBiquadState->pDelays[1];
+        ynL = pBiquadState->coefs[0] * templ;
+
+        // ynL+= ((-B2  * y(n-2)L  ) )
+        templ = pBiquadState->coefs[1] * pBiquadState->pDelays[3];
+        ynL += templ;
+
+        // ynL+= ((-B1  * y(n-1)L  ))
+        templ = pBiquadState->coefs[2] * pBiquadState->pDelays[2];
+        ynL += templ;
+
+        /**************************************************************************
+                        UPDATING THE DELAYS
+        ***************************************************************************/
+        pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+        pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+        pBiquadState->pDelays[2] = ynL; // Update y(n-1)L in Q16
+        pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L in Q0
+
+        /**************************************************************************
+                        WRITING THE OUTPUT
+        ***************************************************************************/
+        *pDataOut++ = (ynL); // Write Left output
+        }
+}
+#else
 void BP_1I_D16F32C30_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
                                   LVM_INT16               *pDataIn,
                                   LVM_INT16               *pDataOut,
@@ -80,4 +121,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c
index e833218..d6e047a 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c
@@ -48,6 +48,20 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void BP_1I_D16F32Cll_TRC_WRA_01_Init (    Biquad_FLOAT_Instance_t         *pInstance,
+                                          Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                          BP_FLOAT_Coefs_t                *pCoef)
+{
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays       =(LVM_FLOAT *) pTaps;
+
+
+    pBiquadState->coefs[0] =  pCoef->A0;
+    pBiquadState->coefs[1] =  pCoef->B2;
+    pBiquadState->coefs[2] =  pCoef->B1;
+}
+#else
 void BP_1I_D16F32Cll_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
                                          Biquad_1I_Order2_Taps_t   *pTaps,
                                          BP_C32_Coefs_t            *pCoef)
@@ -59,6 +73,7 @@
   pBiquadState->coefs[1] =  pCoef->B2;
   pBiquadState->coefs[2] =  pCoef->B1;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BP_1I_D16F32Cll_TRC_WRA_01_Init.c                              */
 
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
index 9cca627..aa9e669 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
@@ -26,5 +26,12 @@
 }Filter_State;
 
 typedef Filter_State * PFilter_State ;
-
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT
+{
+    LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+    LVM_FLOAT         coefs[3];       /* pointer to the filter coefficients */
+}Filter_State_Float;
+typedef Filter_State_Float * PFilter_State_FLOAT ;
+#endif
 #endif /*_BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c
index b09c1aa..abdb2f7 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c
@@ -33,7 +33,52 @@
  pBiquadState->pDelays[2] is y(n-1)L in Q0 format
  pBiquadState->pDelays[3] is y(n-2)L in Q0 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BP_1I_D32F32C30_TRC_WRA_02 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT ynL,templ;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
 
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL= (A0  * (x(n)L  - x(n-2)L  ) )
+            templ = (*pDataIn) - pBiquadState->pDelays[1];
+            ynL = pBiquadState->coefs[0] * templ;
+
+            // ynL+= ((-B2  * y(n-2)L  ) )
+            templ = pBiquadState->coefs[1] * pBiquadState->pDelays[3];
+            ynL += templ;
+
+            // ynL+= ((-B1  * y(n-1)L  ) )
+            templ = pBiquadState->coefs[2] * pBiquadState->pDelays[2];
+            ynL += templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = ynL; // Write Left output in Q0
+
+        }
+
+    }
+#else
 void BP_1I_D32F32C30_TRC_WRA_02 ( Biquad_Instance_t       *pInstance,
                                   LVM_INT32               *pDataIn,
                                   LVM_INT32               *pDataOut,
@@ -78,4 +123,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
index 9367912..5590c32 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
@@ -37,6 +37,21 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void BP_1I_D32F32Cll_TRC_WRA_02_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BP_FLOAT_Coefs_t            *pCoef)
+{
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays       =(LVM_FLOAT *) pTaps;
+
+    pBiquadState->coefs[0] = pCoef->A0;
+
+    pBiquadState->coefs[1] = pCoef->B2;
+
+    pBiquadState->coefs[2] = pCoef->B1;
+}
+#else
 void BP_1I_D32F32Cll_TRC_WRA_02_Init (   Biquad_Instance_t         *pInstance,
                                          Biquad_1I_Order2_Taps_t   *pTaps,
                                          BP_C32_Coefs_t            *pCoef)
@@ -50,6 +65,7 @@
 
   pBiquadState->coefs[2]=pCoef->B1;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BP_1I_D32F32Cll_TRC_WRA_02_Init.c                              */
 
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
index 5cc1ce2..80c3920 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
@@ -26,5 +26,13 @@
 }Filter_State;
 
 typedef Filter_State * PFilter_State ;
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT
+{
+    LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+    LVM_FLOAT         coefs[3];       /* pointer to the filter coefficients */
+}Filter_State_Float;
+typedef Filter_State_Float* PFilter_State_FLOAT ;
+#endif
 
 #endif /*_BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
index f2f8c6b..ee9bf7a 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
@@ -32,7 +32,56 @@
  pBiquadState->pDelays[2] is y(n-1)L in Q0 format
  pBiquadState->pDelays[3] is y(n-2)L in Q0 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BQ_1I_D16F16C15_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
 
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2  * x(n-2)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[1];
+
+            // ynL+=A1 * x(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            // ynL+=A0 * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            // ynL+=  (-B2  * y(n-2)L )
+            ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[3];
+
+            // ynL+= (-B1  * y(n-1)L  )
+            ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[2];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
+
+
+        }
+
+    }
+#else
 void BQ_1I_D16F16C15_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
                                   LVM_INT16               *pDataIn,
                                   LVM_INT16               *pDataOut,
@@ -82,4 +131,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
index baf0c1a..3d5befa 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -37,6 +37,26 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void BQ_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps ;
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+#else
 void BQ_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
                                          Biquad_1I_Order2_Taps_t   *pTaps,
                                          BQ_C16_Coefs_t            *pCoef)
@@ -56,6 +76,7 @@
   temp=pCoef->B1;
   pBiquadState->coefs[4]=temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_1I_D16F16Css_TRC_WRA_01_Init.c                              */
 
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
index 909c699..811da8b 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -27,4 +27,13 @@
 
 typedef Filter_State * PFilter_State ;
 
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT
+{
+    LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+    LVM_FLOAT         coefs[5];       /* pointer to the filter coefficients */
+
+}Filter_State_FLOAT;
+typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
+#endif
 #endif /*_BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c
index 92f6caf..c74a137 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c
@@ -32,7 +32,54 @@
  pBiquadState->pDelays[2] is y(n-1)L in Q16 format
  pBiquadState->pDelays[3] is y(n-2)L in Q16 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
 
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2  * x(n-2)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[1];
+
+            // ynL+=A1  * x(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            // ynL+= ( (-B2  * y(n-2)L )
+            ynL += pBiquadState->pDelays[3] * pBiquadState->coefs[3];
+
+            // ynL+= -B1  * y(n-1)L
+            ynL += pBiquadState->pDelays[2] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[2];  // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1] = pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2] = ynL;                    // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++);              // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)(ynL); // Write Left output
+
+        }
+    }
+#else
 void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
                                   LVM_INT16               *pDataIn,
                                   LVM_INT16               *pDataOut,
@@ -81,4 +128,4 @@
 
         }
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
index aea10f0..9812274 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
@@ -27,4 +27,13 @@
 
 typedef Filter_State * PFilter_State ;
 
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT
+{
+    LVM_FLOAT *   pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+    LVM_FLOAT     coefs[5];       /* pointer to the filter coefficients */
+
+}Filter_State_FLOAT;
+typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
+#endif
 #endif /*_BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
index 1d6be4e..feae20d 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
@@ -38,6 +38,27 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void BQ_1I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *)pTaps;
+
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+#else
 void BQ_1I_D16F32Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
                                          Biquad_1I_Order2_Taps_t   *pTaps,
                                          BQ_C16_Coefs_t            *pCoef)
@@ -57,6 +78,7 @@
   temp=pCoef->B1;
   pBiquadState->coefs[4]=temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_1I_D16F32Css_TRC_WRA_01_Init                              */
 
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c
index 972e704..9b0fde3 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c
@@ -37,7 +37,81 @@
  pBiquadState->pDelays[6] is y(n-2)L in Q0 format
  pBiquadState->pDelays[7] is y(n-2)R in Q0 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F16C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
 
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2  * x(n-2)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            // ynL+=A1  * x(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            // ynL+= ( -B2  * y(n-2)L  )
+            ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[6];
+
+            // ynL+=( -B1  * y(n-1)L )
+            ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[4];
+
+
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            // ynR=A2  * x(n-2)R
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            // ynR+=A1  * x(n-1)R
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            // ynR+=A0  * x(n)R
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            // ynR+= ( -B2  * y(n-2)R  )
+            ynR += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[7];
+
+            // ynR+=( -B1  * y(n-1)R  )
+            ynR += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[5];
+
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[5] = ynR;                       // Update y(n-1)R
+            pBiquadState->pDelays[4] = ynL;                       // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++);              // Update x(n-1)L
+            pBiquadState->pDelays[1] = (*pDataIn++);              // Update x(n-1)R
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
+            *pDataOut++ = (LVM_FLOAT)ynR; // Write Right ouput
+
+
+        }
+
+    }
+#else
 void BQ_2I_D16F16C14_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
                                   LVM_INT16               *pDataIn,
                                   LVM_INT16               *pDataOut,
@@ -112,3 +186,4 @@
 
     }
 
+#endif
\ No newline at end of file
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c
index e056373..f24db8f 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c
@@ -37,7 +37,81 @@
  pBiquadState->pDelays[6] is y(n-2)L in Q0 format
  pBiquadState->pDelays[7] is y(n-2)R in Q0 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F16C15_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
 
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2  * x(n-2)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            // ynL+=A1  * x(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            // ynL+= ( -B2  * y(n-2)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[6];
+
+            // ynL+=( -B1  * y(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[4];
+
+
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            // ynR=A2  * x(n-2)R
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            // ynR+=A1  * x(n-1)R
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            // ynR+=A0  * x(n)R
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            // ynR+= ( -B2  * y(n-2)R  )
+            ynR += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[7];
+
+            // ynR+=( -B1  * y(n-1)R  )
+            ynR += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[5];
+
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[5] = ynR;                       // Update y(n-1)R
+            pBiquadState->pDelays[4] = ynL;                       // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++);              // Update x(n-1)L
+            pBiquadState->pDelays[1] = (*pDataIn++);              // Update x(n-1)R
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
+            *pDataOut++ = (LVM_FLOAT)ynR; // Write Right ouput
+
+        }
+
+    }
+#else
 void BQ_2I_D16F16C15_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
                                   LVM_INT16               *pDataIn,
                                   LVM_INT16               *pDataOut,
@@ -111,4 +185,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
index 0a8ac35..39e1bda 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
@@ -38,6 +38,27 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps            ;
+
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+#else
 void BQ_2I_D16F16Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
                                          Biquad_2I_Order2_Taps_t   *pTaps,
                                          BQ_C16_Coefs_t            *pCoef)
@@ -57,6 +78,7 @@
   temp=pCoef->B1;
   pBiquadState->coefs[4]=temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_2I_D16F16Css_TRC_WRA_01_Init.c                              */
 
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
index 7d42ced..0691b8c 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
@@ -28,4 +28,14 @@
 
 typedef Filter_State * PFilter_State ;
 
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT
+{
+    LVM_FLOAT *   pDelays;            /* pointer to the delayed samples (data of 32 bits) */
+    LVM_FLOAT     coefs[5];           /* pointer to the filter coefficients */
+
+}Filter_State_FLOAT;
+typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
+#endif
+
 #endif /* _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
index 4a0cce4..61c07c7 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
@@ -37,7 +37,79 @@
  pBiquadState->pDelays[6] is y(n-2)L in Q16 format
  pBiquadState->pDelays[7] is y(n-2)R in Q16 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
 
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL=A2 * x(n-2)L */
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            /* ynL+=A1* x(n-1)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            /* ynL+=A0* x(n)L   */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            /* ynL+=-B2*y(n-2)L */
+            ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
+
+            /* ynL+=-B1*y(n-1)L */
+            ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR=A2 * x(n-2)R */
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            /* ynR+=A1* x(n-1)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            /* ynR+=A0* x(n)R   */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            /* ynR+=-B2 * y(n-2)R */
+            ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
+
+            /* ynR+=-B1 * y(n-1)R */
+            ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = ynR;                       /* Update y(n-1)R */
+            pBiquadState->pDelays[4] = ynL;                       /* Update y(n-1)L */
+            pBiquadState->pDelays[0] = (*pDataIn);                /* Update x(n-1)L */
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn);                /* Update x(n-1)R */
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output */
+            pDataOut++;
+            *pDataOut = (LVM_FLOAT)(ynR); /* Write Right ouput */
+            pDataOut++;
+        }
+    }
+#else
 void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
                                             LVM_INT16                    *pDataIn,
                                             LVM_INT16                    *pDataOut,
@@ -115,4 +187,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
index 052e2a0..cf19e06 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
@@ -36,7 +36,82 @@
  pBiquadState->pDelays[6] is y(n-2)L in Q16 format
  pBiquadState->pDelays[7] is y(n-2)R in Q16 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
 
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL=A2  * x(n-2)L */
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            /* ynL+=A1  * x(n-1)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            /* ynL+=A0  * x(n)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            /* ynL+= ( (-B2  * y(n-2)L  ))*/
+            ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
+
+
+            /* ynL+=( (-B1  * y(n-1)L  ))  */
+            ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR=A2  * x(n-2)R */
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            /* ynR+=A1  * x(n-1)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            /* ynR+=A0  * x(n)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            /* ynR+= ( (-B2  * y(n-2)R  ))*/
+            ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
+
+            /* ynR+=( (-B1  * y(n-1)R  ))  */
+            ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = ynR;                    /* Update y(n-1)R */
+            pBiquadState->pDelays[4] = ynL;                    /* Update y(n-1)L */
+            pBiquadState->pDelays[0] = (*pDataIn);                /* Update x(n-1)L */
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn);                /* Update x(n-1)R */
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output */
+            pDataOut++;
+            *pDataOut = (LVM_FLOAT)(ynR); /* Write Right ouput */
+            pDataOut++;
+        }
+
+    }
+#else
 void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
                                             LVM_INT16                    *pDataIn,
                                             LVM_INT16                    *pDataOut,
@@ -114,4 +189,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
index 8c741e1..2611b19 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
@@ -36,7 +36,84 @@
  pBiquadState->pDelays[6] is y(n-2)L in Q16 format
  pBiquadState->pDelays[7] is y(n-2)R in Q16 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
 
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL=A2  * x(n-2)L */
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            /* ynL+=A1  * x(n-1)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            /* ynL+=A0  * x(n)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            /* ynL+= ( (-B2  * y(n-2)L )  */
+            ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
+
+
+            /* ynL+=( (-B1  * y(n-1)L  ))  */
+            ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
+
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR=A2  * x(n-2)R */
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            /* ynR+=A1  * x(n-1)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            /* ynR+=A0  * x(n)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            /* ynR+= ( (-B2  * y(n-2)R ) */
+            ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
+
+
+            /* ynR+=( (-B1  * y(n-1)R  )) in Q15 */
+            ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R*/
+            pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L*/
+            pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L*/
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R*/
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output*/
+            pDataOut++;
+            *pDataOut = (LVM_FLOAT)(ynR); /* Write Right ouput*/
+            pDataOut++;
+        }
+
+    }
+#else
 void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
                                             LVM_INT16                    *pDataIn,
                                             LVM_INT16                    *pDataOut,
@@ -114,4 +191,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
index 4f0cf67..c0319c9 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
@@ -28,4 +28,14 @@
 
 typedef Filter_State * PFilter_State ;
 
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT
+{
+    LVM_FLOAT *                          pDelays;        /* pointer to the delayed samples \
+                                                           (data of 32 bits)   */
+    LVM_FLOAT                           coefs[5];        /* pointer to the filter coefficients */
+}Filter_State_FLOAT;
+typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
+#endif
+
 #endif /* _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
index 4591ee0..4d9bbfe 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
@@ -37,6 +37,26 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void BQ_2I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps;
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+#else
 void BQ_2I_D16F32Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
                                          Biquad_2I_Order2_Taps_t   *pTaps,
                                          BQ_C16_Coefs_t            *pCoef)
@@ -56,6 +76,7 @@
   temp=pCoef->B1;
   pBiquadState->coefs[4]=temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_2I_D16F32Css_TRC_WRA_01_Init                              */
 
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
index fd8212e4..960de79 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
@@ -36,7 +36,94 @@
  pBiquadState->pDelays[6] is y(n-2)L in Q0 format
  pBiquadState->pDelays[7] is y(n-2)R in Q0 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void BQ_2I_D32F32C30_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
 
+
+    {
+        LVM_FLOAT ynL,ynR,templ,tempd;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL= ( A2  * x(n-2)L  ) */
+            ynL = pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            /* ynL+= ( A1  * x(n-1)L  )*/
+            templ = pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+            ynL += templ;
+
+            /* ynL+= ( A0  * x(n)L  ) */
+            templ = pBiquadState->coefs[2] * (*pDataIn);
+            ynL += templ;
+
+             /* ynL+= (-B2  * y(n-2)L  ) */
+            templ = pBiquadState->coefs[3] * pBiquadState->pDelays[6];
+            ynL += templ;
+
+            /* ynL+= (-B1  * y(n-1)L  )*/
+            templ = pBiquadState->coefs[4] * pBiquadState->pDelays[4];
+            ynL += templ;
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR= ( A2  * x(n-2)R  ) */
+            ynR = pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            /* ynR+= ( A1  * x(n-1)R  ) */
+            templ = pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+            ynR += templ;
+
+            /* ynR+= ( A0  * x(n)R  ) */
+            tempd =* (pDataIn+1);
+            templ = pBiquadState->coefs[2] * tempd;
+            ynR += templ;
+
+            /* ynR+= (-B2  * y(n-2)R  ) */
+            templ = pBiquadState->coefs[3] * pBiquadState->pDelays[7];
+            ynR += templ;
+
+            /* ynR+= (-B1  * y(n-1)R  )  */
+            templ = pBiquadState->coefs[4] * pBiquadState->pDelays[5];
+            ynR += templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = (LVM_FLOAT)ynR; /* Update y(n-1)R */
+            pBiquadState->pDelays[4] = (LVM_FLOAT)ynL; /* Update y(n-1)L */
+            pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = (LVM_FLOAT)ynL; /* Write Left output */
+            pDataOut++;
+            *pDataOut = (LVM_FLOAT)ynR; /* Write Right ouput */
+            pDataOut++;
+
+
+        }
+
+    }
+#else
 void BQ_2I_D32F32C30_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
                                             LVM_INT32                    *pDataIn,
                                             LVM_INT32                    *pDataOut,
@@ -123,4 +210,4 @@
         }
 
     }
-
+#endif /*BUILD_FLOAT*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
index 1709f71..fff05ed 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
@@ -37,6 +37,26 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void BQ_2I_D32F32Cll_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps;
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+#else
 void BQ_2I_D32F32Cll_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
                                          Biquad_2I_Order2_Taps_t   *pTaps,
                                          BQ_C32_Coefs_t            *pCoef)
@@ -56,6 +76,7 @@
   temp=pCoef->B1;
   pBiquadState->coefs[4]=temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_2I_D32F32C32_TRC_WRA_01_Init.c                              */
 
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
index 747af6a..c0f0dcc 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
@@ -29,4 +29,14 @@
 
 typedef Filter_State * PFilter_State ;
 
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT
+{
+    LVM_FLOAT *                          pDelays;        /* pointer to the delayed samples \
+                                                            (data of 32 bits)   */
+    LVM_FLOAT                            coefs[5];       /* pointer to the filter coefficients */
+}Filter_State_FLOAT;
+typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
+#endif
+
 #endif /* _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.c b/media/libeffects/lvm/lib/Common/src/Copy_16.c
index 20404ad..e489031 100644
--- a/media/libeffects/lvm/lib/Common/src/Copy_16.c
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.c
@@ -54,5 +54,35 @@
 
     return;
 }
+#ifdef BUILD_FLOAT
+void Copy_Float( const LVM_FLOAT *src,
+                 LVM_FLOAT *dst,
+                 LVM_INT16  n )
+{
+    LVM_INT16 ii;
 
+    if (src > dst)
+    {
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = *src;
+            dst++;
+            src++;
+        }
+    }
+    else
+    {
+        src += n - 1;
+        dst += n - 1;
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = *src;
+            dst--;
+            src--;
+        }
+    }
+
+    return;
+}
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c
index bf69e35..ea98041 100644
--- a/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c
@@ -25,7 +25,37 @@
 /**********************************************************************************
    FUNCTION CORE_MIXHARD_2ST_D32C31_SAT
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void Core_MixHard_2St_D32C31_SAT(   Mix_2St_Cll_FLOAT_t       *pInstance,
+                                    const LVM_FLOAT     *src1,
+                                    const LVM_FLOAT     *src2,
+                                    LVM_FLOAT     *dst,
+                                    LVM_INT16     n)
+{
+    LVM_FLOAT  Temp1,Temp2,Temp3;
+    LVM_INT16 ii;
+    LVM_FLOAT Current1Short;
+    LVM_FLOAT Current2Short;
 
+    Current1Short = (pInstance->Current1);
+    Current2Short = (pInstance->Current2);
+
+    for (ii = n; ii != 0; ii--){
+        Temp1 = *src1++;
+        Temp3 = Temp1 * Current1Short;
+        Temp2 = *src2++;
+        Temp1 = Temp2 * Current2Short;
+        Temp2 = (Temp1 / 2.0f) + (Temp3 / 2.0f);
+        if (Temp2 > 0.5f)
+            Temp2 = 1.0f;
+        else if (Temp2 < -0.5f )
+            Temp2 = -1.0f;
+        else
+            Temp2 = (Temp2 * 2);
+            *dst++ = Temp2;
+    }
+}
+#else
 void Core_MixHard_2St_D32C31_SAT(   Mix_2St_Cll_t       *pInstance,
                                     const LVM_INT32     *src1,
                                     const LVM_INT32     *src2,
@@ -55,6 +85,5 @@
             *dst++ = Temp2;
     }
 }
-
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c
index 3471f05..2814f19 100644
--- a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c
@@ -26,6 +26,70 @@
    FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
 ***********************************************************************************/
 
+#ifdef BUILD_FLOAT /* BUILD_FLOAT */
+void Core_MixInSoft_D32C31_SAT(     Mix_1St_Cll_FLOAT_t       *pInstance,
+                                    const LVM_FLOAT     *src,
+                                          LVM_FLOAT     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_FLOAT    Temp1,Temp2,Temp3;
+    LVM_INT16     OutLoop;
+    LVM_INT16     InLoop;
+    LVM_FLOAT    TargetTimesOneMinAlpha;
+    LVM_FLOAT    CurrentTimesAlpha;
+    LVM_INT16     ii,jj;
+
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    TargetTimesOneMinAlpha = ((1.0f -pInstance->Alpha) * pInstance->Target);
+    if (pInstance->Target >= pInstance->Current){
+        TargetTimesOneMinAlpha +=(LVM_FLOAT)(2.0f / 2147483647.0f); /* Ceil*/
+    }
+
+    if (OutLoop){
+
+        CurrentTimesAlpha = pInstance->Current * pInstance->Alpha;
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
+
+        for (ii = OutLoop; ii != 0; ii--){
+        Temp1 = *src++;
+        Temp2 = *dst;
+
+        Temp3 = Temp1 * (pInstance->Current);
+        Temp1 = Temp2 + Temp3;
+
+        if (Temp1 > 1.0f)
+            Temp1 = 1.0f;
+        else if (Temp1 < -1.0f)
+            Temp1 = -1.0f;
+
+        *dst++ = Temp1;
+        }
+    }
+
+    for (ii = InLoop; ii != 0; ii--){
+
+        CurrentTimesAlpha = pInstance->Current * pInstance->Alpha;
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
+
+        for (jj = 4; jj!=0 ; jj--){
+            Temp1 = *src++;
+            Temp2 = *dst;
+
+            Temp3 = Temp1 * (pInstance->Current);
+            Temp1 = Temp2 + Temp3;
+
+            if (Temp1 > 1.0f)
+                Temp1 = 1.0f;
+            else if (Temp1 < -1.0f)
+                Temp1 = -1.0f;
+            *dst++ = Temp1;
+        }
+    }
+}
+#else
 void Core_MixInSoft_D32C31_SAT(     Mix_1St_Cll_t       *pInstance,
                                     const LVM_INT32     *src,
                                           LVM_INT32     *dst,
@@ -89,6 +153,5 @@
         }
     }
 }
-
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c
index 709c304..814ccee 100644
--- a/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c
@@ -25,7 +25,79 @@
 /**********************************************************************************
    FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_FLOAT_t       *pInstance,
+                                    const LVM_FLOAT     *src,
+                                    LVM_FLOAT     *dst,
+                                    LVM_INT16     n)
+{
+    LVM_FLOAT Temp1,Temp2;
+    LVM_INT16 OutLoop;
+    LVM_INT16 InLoop;
+    LVM_FLOAT TargetTimesOneMinAlpha;
+    LVM_FLOAT CurrentTimesAlpha;
 
+    LVM_INT16 ii;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    TargetTimesOneMinAlpha = (1.0f - pInstance->Alpha) * pInstance->Target; /* float * float in float */
+    if (pInstance->Target >= pInstance->Current)
+    {
+        TargetTimesOneMinAlpha += (LVM_FLOAT)(2.0f / 2147483647.0f); /* Ceil*/
+    }
+
+    if (OutLoop != 0)
+    {
+        CurrentTimesAlpha = (pInstance->Current * pInstance->Alpha);
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
+
+        for (ii = OutLoop; ii != 0; ii--)
+        {
+            Temp1 = *src;
+            src++;
+
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+        }
+    }
+
+    for (ii = InLoop; ii != 0; ii--)
+    {
+        CurrentTimesAlpha = pInstance->Current * pInstance->Alpha;
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
+
+            Temp1 = *src;
+            src++;
+
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+
+            Temp1 = *src;
+            src++;
+
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+
+            Temp1 = *src;
+            src++;
+
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+
+            Temp1 = *src;
+            src++;
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+    }
+}
+#else
 void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_t       *pInstance,
                                     const LVM_INT32     *src,
                                           LVM_INT32     *dst,
@@ -98,6 +170,5 @@
             dst++;
     }
 }
-
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
index 49fa184..d261c9e 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
@@ -18,7 +18,53 @@
 #include "BIQUAD.h"
 #include "DC_2I_D16_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
+#ifdef BUILD_FLOAT
+void DC_2I_D16_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                           LVM_FLOAT               *pDataIn,
+                           LVM_FLOAT               *pDataOut,
+                           LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT LeftDC,RightDC;
+        LVM_FLOAT Diff;
+        LVM_INT32 j;
+        PFilter_FLOAT_State pBiquadState = (PFilter_FLOAT_State) pInstance;
 
+        LeftDC = pBiquadState->LeftDC;
+        RightDC = pBiquadState->RightDC;
+        for(j = NrSamples-1; j >= 0; j--)
+        {
+            /* Subtract DC an saturate */
+            Diff =* (pDataIn++) - (LeftDC);
+            if (Diff > 1.0f) {
+                Diff = 1.0f; }
+            else if (Diff < -1.0f) {
+                Diff = -1.0f; }
+            *(pDataOut++) = (LVM_FLOAT)Diff;
+            if (Diff < 0) {
+                LeftDC -= DC_FLOAT_STEP; }
+            else {
+                LeftDC += DC_FLOAT_STEP; }
+
+
+            /* Subtract DC an saturate */
+            Diff =* (pDataIn++) - (RightDC);
+            if (Diff > 1.0f) {
+                Diff = 1.0f; }
+            else if (Diff < -1.0f) {
+                Diff = -1.0f; }
+            *(pDataOut++) = (LVM_FLOAT)Diff;
+            if (Diff < 0) {
+                RightDC -= DC_FLOAT_STEP; }
+            else {
+                RightDC += DC_FLOAT_STEP; }
+
+        }
+        pBiquadState->LeftDC = LeftDC;
+        pBiquadState->RightDC = RightDC;
+
+
+    }
+#else
 void DC_2I_D16_TRC_WRA_01( Biquad_Instance_t       *pInstance,
                            LVM_INT16               *pDataIn,
                            LVM_INT16               *pDataOut,
@@ -64,4 +110,4 @@
 
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
index 468a88d..4f4fcd8 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
@@ -17,11 +17,18 @@
 
 #include "BIQUAD.h"
 #include "DC_2I_D16_TRC_WRA_01_Private.h"
-
+#ifdef BUILD_FLOAT
+void  DC_2I_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t   *pInstance)
+{
+    PFilter_FLOAT_State pBiquadState  = (PFilter_FLOAT_State) pInstance;
+    pBiquadState->LeftDC        = 0.0f;
+    pBiquadState->RightDC       = 0.0f;
+}
+#else
 void  DC_2I_D16_TRC_WRA_01_Init(Biquad_Instance_t   *pInstance)
 {
     PFilter_State pBiquadState  = (PFilter_State) pInstance;
     pBiquadState->LeftDC        = 0;
     pBiquadState->RightDC       = 0;
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
index 89a4e68..fa6b729 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
@@ -18,11 +18,23 @@
 #ifndef _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
 #define _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
 
+#ifdef BUILD_FLOAT
+#define DC_FLOAT_STEP   0.0000002384f;
+#else
 #define DC_D16_STEP     0x200;
+#endif
 
 
 /* The internal state variables are implemented in a (for the user)  hidden structure */
 /* In this (private) file, the internal structure is declared fro private use.*/
+#ifdef BUILD_FLOAT
+typedef struct _Filter_FLOAT_State_
+{
+    LVM_FLOAT  LeftDC;     /* LeftDC  */
+    LVM_FLOAT  RightDC;    /* RightDC  */
+}Filter_FLOAT_State;
+typedef Filter_FLOAT_State * PFilter_FLOAT_State ;
+#else
 typedef struct _Filter_State_
 {
   LVM_INT32  LeftDC;     /* LeftDC  */
@@ -30,5 +42,5 @@
 }Filter_State;
 
 typedef Filter_State * PFilter_State ;
-
+#endif
 #endif /* _DC_2I_D16_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
index 7e3182d..f502716 100644
--- a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
+++ b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
@@ -36,10 +36,55 @@
     LVM_INT16   Offset  = *pOffset;
     LVM_INT16   temp;
 
+    for (i = 0; i < n; i++)
+    {
+        /* Left channel */
+        temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) + (LVM_INT32)delay[Offset]) >> 1);
+        *dst = temp;
+        dst++;
+
+        delay[Offset] = *src;
+        Offset++;
+        src++;
+
+
+        /* Right channel */
+        temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) - (LVM_INT32)delay[Offset]) >> 1);
+        *dst = temp;
+        dst++;
+
+        delay[Offset] = *src;
+        Offset++;
+        src++;
+
+        /* Make the reverb delay buffer a circular buffer */
+        if (Offset >= size)
+        {
+            Offset = 0;
+        }
+    }
+
+    /* Update the offset */
+    *pOffset = Offset;
+
+    return;
+}
+#ifdef BUILD_FLOAT
+void DelayMix_Float(const LVM_FLOAT *src,           /* Source 1, to be delayed */
+                          LVM_FLOAT *delay,         /* Delay buffer */
+                          LVM_INT16 size,           /* Delay size */
+                          LVM_FLOAT *dst,           /* Source/destination */
+                          LVM_INT16 *pOffset,       /* Delay offset */
+                          LVM_INT16 n)              /* Number of stereo samples */
+{
+    LVM_INT16   i;
+    LVM_INT16   Offset  = *pOffset;
+    LVM_FLOAT   temp;
+
     for (i=0; i<n; i++)
     {
         /* Left channel */
-        temp            = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) + (LVM_INT32)delay[Offset]) >> 1);
+        temp            = (LVM_FLOAT)((LVM_FLOAT)(*dst + (LVM_FLOAT)delay[Offset]) / 2.0f);
         *dst            = temp;
         dst++;
 
@@ -49,7 +94,7 @@
 
 
         /* Right channel */
-        temp            = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) - (LVM_INT32)delay[Offset]) >> 1);
+        temp            = (LVM_FLOAT)((LVM_FLOAT)(*dst - (LVM_FLOAT)delay[Offset]) / 2.0f);
         *dst            = temp;
         dst++;
 
@@ -69,5 +114,5 @@
 
     return;
 }
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c
index de77361..039c88c 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c
@@ -31,6 +31,46 @@
  pBiquadState->pDelays[1] is y(n-1)L in Q0 format
 ***************************************************************************/
 
+#ifdef BUILD_FLOAT
+void FO_1I_D16F16C15_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                                 LVM_FLOAT               *pDataIn,
+                                 LVM_FLOAT               *pDataOut,
+                                 LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A1  * x(n-1)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
+
+            // ynL+=  (-B1  * y(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * pBiquadState->pDelays[1];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
+
+        }
+
+    }
+#else
 void FO_1I_D16F16C15_TRC_WRA_01( Biquad_Instance_t       *pInstance,
                                  LVM_INT16               *pDataIn,
                                  LVM_INT16               *pDataOut,
@@ -71,4 +111,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c
index 96252cc..b21b8a4 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -38,6 +38,22 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void FO_1I_D16F16Css_TRC_WRA_01_Init(    Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order1_FLOAT_Taps_t   *pTaps,
+                                         FO_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)  pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *)pTaps;
+    temp = pCoef->A1;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[2] = temp;
+}
+#else
 void FO_1I_D16F16Css_TRC_WRA_01_Init(    Biquad_Instance_t         *pInstance,
                                          Biquad_1I_Order1_Taps_t   *pTaps,
                                          FO_C16_Coefs_t            *pCoef)
@@ -53,6 +69,7 @@
   temp=pCoef->B1;
   pBiquadState->coefs[2]=temp;
 }
+#endif
 /*------------------------------------------------*/
 /* End Of File: FO_1I_D16F16Css_TRC_WRA_01_Init.c */
 
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
index 516ca83..6fdb039 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -28,4 +28,14 @@
 
 typedef Filter_State * PFilter_State ;
 
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT
+{
+    LVM_FLOAT *                          pDelays;        /* pointer to the delayed samples \
+                                                            (data of 32 bits)   */
+    LVM_FLOAT                            coefs[3];       /* pointer to the filter coefficients */
+}Filter_State_FLOAT;
+
+typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
+#endif
 #endif /* _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c
index 0f1d5bc..416e8eb 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c
@@ -31,7 +31,47 @@
  pBiquadState->pDelays[0] is x(n-1)L in Q0 format
  pBiquadState->pDelays[1] is y(n-1)L in Q0 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void FO_1I_D32F32C31_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                                 LVM_FLOAT               *pDataIn,
+                                 LVM_FLOAT               *pDataOut,
+                                 LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL,templ;
+        LVM_INT16  ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
 
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A1  * x(n-1)L
+            ynL = pBiquadState->coefs[0] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            templ = pBiquadState->coefs[1] * (*pDataIn);
+            ynL += templ;
+
+            // ynL+=  (-B1  * y(n-1)L
+            templ = pBiquadState->coefs[2] * pBiquadState->pDelays[1];
+            ynL += templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
+        }
+
+    }
+#else
 void FO_1I_D32F32C31_TRC_WRA_01( Biquad_Instance_t       *pInstance,
                                  LVM_INT32               *pDataIn,
                                  LVM_INT32               *pDataOut,
@@ -71,4 +111,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c
index 136e4f6..f33d24d 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c
@@ -37,6 +37,23 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_FLOAT_Instance_t         *pInstance,
+                                      Biquad_1I_Order1_FLOAT_Taps_t   *pTaps,
+                                      FO_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)  pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *)    pTaps;
+
+    temp = pCoef->A1;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[2] = temp;
+}
+#else
 void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_Instance_t         *pInstance,
                                       Biquad_1I_Order1_Taps_t   *pTaps,
                                       FO_C32_Coefs_t            *pCoef)
@@ -52,6 +69,7 @@
   temp=pCoef->B1;
   pBiquadState->coefs[2]=temp;
 }
+#endif
 /*------------------------------------------------*/
 /* End Of File: FO_1I_D32F32Cll_TRC_WRA_01_Init.c */
 
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
index 94ad48c..fdb528b 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
@@ -29,4 +29,13 @@
 
 typedef Filter_State * PFilter_State ;
 
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_FLOAT_
+{
+    LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+    LVM_FLOAT         coefs[3];       /* pointer to the filter coefficients */
+}Filter_State_FLOAT;
+
+typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
+#endif
 #endif /* _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
index 8388050..192927c 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
@@ -32,7 +32,92 @@
 pBiquadState->pDelays[2] is x(n-1)R in Q15 format
 pBiquadState->pDelays[3] is y(n-1)R in Q30 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t       *pInstance,
+                                     LVM_FLOAT               *pDataIn,
+                                     LVM_FLOAT               *pDataOut,
+                                     LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT   ynL,ynR;
+        LVM_FLOAT   Temp;
+        LVM_FLOAT   NegSatValue;
+        LVM_INT16   ii;
 
+        PFilter_Float_State pBiquadState = (PFilter_Float_State) pInstance;
+
+        NegSatValue = -1.0f;
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+
+            // ynL =A1  * x(n-1)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
+            // ynR =A1  * x(n-1)R
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
+            // ynR+=A0  * x(n)L
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * (*(pDataIn+1));
+
+
+            // ynL +=  (-B1  * y(n-1)L  )
+            Temp = pBiquadState->pDelays[1] * pBiquadState->coefs[2];
+            ynL += Temp;
+            // ynR +=  (-B1  * y(n-1)R ) )
+            Temp = pBiquadState->pDelays[3] * pBiquadState->coefs[2];
+            ynR += Temp;
+
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            pBiquadState->pDelays[3] = ynR; // Update y(n-1)R
+            pBiquadState->pDelays[2] = (*pDataIn++); // Update x(n-1)R
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+
+            /*Saturate results*/
+            if(ynL > 1.0f)
+            {
+                ynL = 1.0f;
+            }
+            else
+            {
+                if(ynL < NegSatValue)
+                {
+                    ynL = NegSatValue;
+                }
+            }
+
+            if(ynR > 1.0f)
+            {
+                ynR = 1.0f;
+            }
+            else
+            {
+                if(ynR < NegSatValue)
+                {
+                    ynR = NegSatValue;
+                }
+            }
+
+            *pDataOut++ = (LVM_FLOAT)ynL;
+            *pDataOut++ = (LVM_FLOAT)ynR;
+        }
+
+    }
+#else
 void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_Instance_t       *pInstance,
                                      LVM_INT16               *pDataIn,
                                      LVM_INT16               *pDataOut,
@@ -125,4 +210,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c
index a19c32c..33ca6cf 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c
@@ -37,6 +37,23 @@
 /* RETURNS:                                                                */
 /*   void return code                                                      */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t         *pInstance,
+                                          Biquad_2I_Order1_FLOAT_Taps_t   *pTaps,
+                                          FO_FLOAT_LShx_Coefs_t        *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_Float_State pBiquadState = (PFilter_Float_State) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps            ;
+
+    temp = pCoef->A1;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[2] = temp;
+}
+#else
 void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_Instance_t         *pInstance,
                                           Biquad_2I_Order1_Taps_t   *pTaps,
                                           FO_C16_LShx_Coefs_t        *pCoef)
@@ -55,6 +72,7 @@
   temp=pCoef->Shift;
   pBiquadState->Shift = temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c                     */
 
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
index 4640743..368bfce 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
@@ -20,6 +20,15 @@
 
 /* The internal state variables are implemented in a (for the user)  hidden structure */
 /* In this (private) file, the internal structure is declared fro private use.        */
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_
+{
+    LVM_FLOAT     *pDelays;       /* pointer to the delayed samples (data of 32 bits)   */
+    LVM_FLOAT     coefs[3];       /* pointer to the filter coefficients */
+}Filter_Float_State;
+
+typedef Filter_Float_State * PFilter_Float_State ;
+#else
 typedef struct _Filter_State_
 {
   LVM_INT32     *pDelays;       /* pointer to the delayed samples (data of 32 bits)   */
@@ -28,5 +37,5 @@
 }Filter_State;
 
 typedef Filter_State * PFilter_State ;
-
+#endif
 #endif /* _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/Filters.h b/media/libeffects/lvm/lib/Common/src/Filters.h
index 4d32df1..b1fde0c 100644
--- a/media/libeffects/lvm/lib/Common/src/Filters.h
+++ b/media/libeffects/lvm/lib/Common/src/Filters.h
@@ -34,6 +34,7 @@
  * Biquad with coefficients A0, A1, A2, B1 and B2 coefficients
  */
 /* Single precision (16-bit) Biquad section coefficients */
+#ifndef BUILD_FLOAT
 typedef struct
 {
         LVM_INT16   A0;
@@ -43,12 +44,22 @@
         LVM_INT16   B2;
         LVM_UINT16  Scale;
 } BiquadA012B12CoefsSP_t;
-
-
+#else
+typedef struct
+{
+    LVM_FLOAT   A0;
+    LVM_FLOAT   A1;
+    LVM_FLOAT   A2;
+    LVM_FLOAT   B1;
+    LVM_FLOAT   B2;
+    LVM_UINT16  Scale;
+} BiquadA012B12CoefsSP_t;
+#endif
 /*
  * Biquad with coefficients A0, A1 and B1 coefficients
  */
 /* Single precision (16-bit) Biquad section coefficients */
+#ifndef BUILD_FLOAT
 typedef struct
 {
         LVM_INT16   A0;
@@ -56,8 +67,15 @@
         LVM_INT16   B1;
         LVM_UINT16  Scale;
 } BiquadA01B1CoefsSP_t;
-
-
+#else
+typedef struct
+{
+    LVM_FLOAT   A0;
+    LVM_FLOAT   A1;
+    LVM_FLOAT   B1;
+    LVM_UINT16  Scale;
+} BiquadA01B1CoefsSP_t;
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c
index 7975e8b..2c6e6c3 100644
--- a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c
@@ -53,5 +53,34 @@
 
     return;
 }
+#ifdef BUILD_FLOAT
+void From2iToMS_Float( const LVM_FLOAT  *src,
+                             LVM_FLOAT  *dstM,
+                             LVM_FLOAT  *dstS,
+                             LVM_INT16  n )
+{
+    LVM_FLOAT temp1,left,right;
+    LVM_INT16 ii;
+    for (ii = n; ii != 0; ii--)
+    {
+        left = (LVM_FLOAT)*src;
+        src++;
 
+        right = (LVM_FLOAT)*src;
+        src++;
+
+        /* Compute M signal*/
+        temp1 =  (left + right) / 2.0f;
+        *dstM = (LVM_FLOAT)temp1;
+        dstM++;
+
+        /* Compute S signal*/
+        temp1 =  (left - right) / 2.0f;
+        *dstS = (LVM_FLOAT)temp1;
+        dstS++;
+    }
+
+    return;
+}
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
index 8bb292f..ac1eea8 100644
--- a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
@@ -46,5 +46,27 @@
 
     return;
 }
+#ifdef BUILD_FLOAT
+void From2iToMono_Float( const LVM_FLOAT *src,
+                         LVM_FLOAT *dst,
+                         LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_FLOAT Temp;
 
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = (*src);
+        src++;
+
+        Temp += (*src);
+        src++;
+
+        *dst = Temp / 2.0f;
+        dst++;
+    }
+
+    return;
+}
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
index 9b938bd..ebc477e 100644
--- a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
+++ b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
@@ -49,6 +49,31 @@
 
     return;
 }
+#ifdef BUILD_FLOAT
+void JoinTo2i_Float( const LVM_FLOAT    *srcL,
+                     const LVM_FLOAT    *srcR,
+                           LVM_FLOAT    *dst,
+                           LVM_INT16    n )
+{
+    LVM_INT16 ii;
 
+    srcL += n - 1;
+    srcR += n - 1;
+    dst  += ((2 * n) - 1);
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = *srcR;
+        dst--;
+        srcR--;
+
+        *dst = *srcL;
+        dst--;
+        srcL--;
+    }
+
+    return;
+}
+#endif
 /**********************************************************************************/
 
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
index 3d39b93..eb5755e 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
@@ -27,7 +27,39 @@
 /**********************************************************************************
    FUNCTION LVC_Core_MixHard_1St_2i_D16C31_SAT
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_FLOAT_st        *ptrInstance1,
+                                         LVMixer3_FLOAT_st        *ptrInstance2,
+                                         const LVM_FLOAT    *src,
+                                         LVM_FLOAT          *dst,
+                                         LVM_INT16          n)
+{
+    LVM_FLOAT  Temp;
+    LVM_INT16 ii;
+    Mix_Private_FLOAT_st  *pInstance1 = (Mix_Private_FLOAT_st *)(ptrInstance1->PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = (Mix_Private_FLOAT_st *)(ptrInstance2->PrivateParams);
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = ((LVM_FLOAT)*(src++) * (LVM_FLOAT)pInstance1->Current);
+        if (Temp > 1.0f)
+            *dst++ = 1.0f;
+        else if (Temp < -1.0f)
+            *dst++ = -1.0f;
+        else
+            *dst++ = (LVM_FLOAT)Temp;
 
+        Temp = ((LVM_FLOAT)*(src++) * (LVM_FLOAT)pInstance2->Current);
+        if (Temp > 1.0f)
+            *dst++ = 1.0f;
+        else if (Temp < -1.0f)
+            *dst++ = -1.0f;
+        else
+            *dst++ = (LVM_FLOAT)Temp;
+    }
+
+
+}
+#else
 void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_st        *ptrInstance1,
                                          LVMixer3_st        *ptrInstance2,
                                          const LVM_INT16    *src,
@@ -66,4 +98,5 @@
 
 
 }
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c
index 2daf74a..ec0baaf 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c
@@ -24,7 +24,37 @@
 /**********************************************************************************
    FUNCTION LVCore_MIXHARD_2ST_D16C31_SAT
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_FLOAT_st *ptrInstance1,
+                                    LVMixer3_FLOAT_st         *ptrInstance2,
+                                    const LVM_FLOAT     *src1,
+                                    const LVM_FLOAT     *src2,
+                                          LVM_FLOAT     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_FLOAT  Temp;
+    LVM_INT16 ii;
+    LVM_FLOAT Current1;
+    LVM_FLOAT Current2;
+    Mix_Private_FLOAT_st  *pInstance1 = (Mix_Private_FLOAT_st *)(ptrInstance1->PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = (Mix_Private_FLOAT_st *)(ptrInstance2->PrivateParams);
 
+
+    Current1 = (pInstance1->Current);
+    Current2 = (pInstance2->Current);
+
+    for (ii = n; ii != 0; ii--){
+        Temp = (((LVM_FLOAT)*(src1++) * (LVM_FLOAT)Current1)) +
+               (((LVM_FLOAT)*(src2++) * (LVM_FLOAT)Current2));
+        if (Temp > 1.0f)
+            *dst++ = 1.0f;
+        else if (Temp < -1.0f)
+            *dst++ = -1.0f;
+        else
+            *dst++ = Temp;
+    }
+}
+#else
 void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_st *ptrInstance1,
                                     LVMixer3_st         *ptrInstance2,
                                     const LVM_INT16     *src1,
@@ -54,6 +84,5 @@
             *dst++ = (LVM_INT16)Temp;
     }
 }
-
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
index caa0951..d2694cc 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
@@ -25,7 +25,96 @@
 /**********************************************************************************
    FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_FLOAT_st *ptrInstance,
+                                    const LVM_FLOAT     *src,
+                                          LVM_FLOAT     *dst,
+                                          LVM_INT16     n)
+{
 
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT32   ii,jj;
+    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
+    LVM_FLOAT   Delta = pInstance->Delta;
+    LVM_FLOAT   Current = pInstance->Current;
+    LVM_FLOAT   Target = pInstance->Target;
+    LVM_FLOAT   Temp;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    if(Current < Target){
+        if (OutLoop){
+            Temp = Current + Delta;
+            Current = Temp;
+            if (Current > Target)
+                Current = Target;
+
+           for (ii = OutLoop; ii != 0; ii--){
+                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = (LVM_FLOAT)Temp;
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            Temp = Current + Delta;
+            Current = Temp;
+            if (Current > Target)
+                Current = Target;
+
+            for (jj = 4; jj != 0 ; jj--){
+                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = (LVM_FLOAT)Temp;
+            }
+        }
+    }
+    else{
+        if (OutLoop){
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (ii = OutLoop; ii != 0; ii--){
+                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = (LVM_FLOAT)Temp;
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (jj = 4; jj != 0 ; jj--){
+                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = (LVM_FLOAT)Temp;
+            }
+        }
+    }
+    pInstance->Current = Current;
+}
+#else
 void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *ptrInstance,
                                     const LVM_INT16     *src,
                                           LVM_INT16     *dst,
@@ -123,6 +212,5 @@
     }
     pInstance->Current=Current;
 }
-
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
index 09ec427..656a117 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
@@ -26,7 +26,127 @@
 /**********************************************************************************
    FUNCTION LVC_Core_MixSoft_1St_2i_D16C31_WRA
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+static LVM_FLOAT ADD2_SAT_FLOAT(LVM_FLOAT a,
+                                LVM_FLOAT b,
+                                LVM_FLOAT c)
+{
+    LVM_FLOAT temp;
+    temp = a + b ;
+    if (temp < -1.0f)
+        c = -1.0f;
+    else if (temp > 1.0f)
+        c = 1.0f;
+    else
+        c = temp;
+    return c;
+}
+void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_FLOAT_st        *ptrInstance1,
+                                         LVMixer3_FLOAT_st        *ptrInstance2,
+                                         const LVM_FLOAT    *src,
+                                         LVM_FLOAT          *dst,
+                                         LVM_INT16          n)
+{
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT32   ii;
+    Mix_Private_FLOAT_st  *pInstanceL = (Mix_Private_FLOAT_st *)(ptrInstance1->PrivateParams);
+    Mix_Private_FLOAT_st  *pInstanceR = (Mix_Private_FLOAT_st *)(ptrInstance2->PrivateParams);
 
+    LVM_FLOAT   DeltaL = pInstanceL->Delta;
+    LVM_FLOAT   CurrentL = pInstanceL->Current;
+    LVM_FLOAT   TargetL = pInstanceL->Target;
+
+    LVM_FLOAT   DeltaR = pInstanceR->Delta;
+    LVM_FLOAT   CurrentR = pInstanceR->Current;
+    LVM_FLOAT   TargetR = pInstanceR->Target;
+
+    LVM_FLOAT   Temp = 0;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    if (OutLoop)
+    {
+        if(CurrentL < TargetL)
+        {
+            ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
+            CurrentL = Temp;
+            if (CurrentL > TargetL)
+                CurrentL = TargetL;
+        }
+        else
+        {
+            CurrentL -= DeltaL;
+            if (CurrentL < TargetL)
+                CurrentL = TargetL;
+        }
+
+        if(CurrentR < TargetR)
+        {
+            ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
+            CurrentR = Temp;
+            if (CurrentR > TargetR)
+                CurrentR = TargetR;
+        }
+        else
+        {
+            CurrentR -= DeltaR;
+            if (CurrentR < TargetR)
+                CurrentR = TargetR;
+        }
+
+        for (ii = OutLoop * 2; ii != 0; ii -= 2)
+        {
+            *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+            *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+        }
+    }
+
+    for (ii = InLoop * 2; ii != 0; ii-=2)
+    {
+        if(CurrentL < TargetL)
+        {
+            ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
+            CurrentL = Temp;
+            if (CurrentL > TargetL)
+                CurrentL = TargetL;
+        }
+        else
+        {
+            CurrentL -= DeltaL;
+            if (CurrentL < TargetL)
+                CurrentL = TargetL;
+        }
+
+        if(CurrentR < TargetR)
+        {
+            ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
+            CurrentR = Temp;
+            if (CurrentR > TargetR)
+                CurrentR = TargetR;
+        }
+        else
+        {
+            CurrentR -= DeltaR;
+            if (CurrentR < TargetR)
+                CurrentR = TargetR;
+        }
+
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+    }
+    pInstanceL->Current = CurrentL;
+    pInstanceR->Current = CurrentR;
+
+}
+#else
 void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_st        *ptrInstance1,
                                          LVMixer3_st        *ptrInstance2,
                                          const LVM_INT16    *src,
@@ -140,4 +260,5 @@
     pInstanceR->Current=CurrentR;
 
 }
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
index f1a9ca3..b5e7f5c 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
@@ -26,7 +26,86 @@
 /**********************************************************************************
    FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_FLOAT_st *ptrInstance,
+                                    const LVM_FLOAT     *src,
+                                          LVM_FLOAT     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT32   ii;
+    Mix_Private_FLOAT_st  *pInstance=(Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
+    LVM_FLOAT   Delta= (LVM_FLOAT)pInstance->Delta;
+    LVM_FLOAT   Current = (LVM_FLOAT)pInstance->Current;
+    LVM_FLOAT   Target= (LVM_FLOAT)pInstance->Target;
+    LVM_FLOAT   Temp;
 
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    if(Current<Target){
+        if (OutLoop){
+
+            Temp = Current + Delta;
+            if (Temp > 1.0f)
+                Temp = 1.0f;
+            else if (Temp < -1.0f)
+                Temp = -1.0f;
+
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            for (ii = OutLoop; ii != 0; ii--){
+                *(dst++) = (((LVM_FLOAT)*(src++) * (LVM_FLOAT)Current));
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+
+            Temp = Current + Delta;
+
+            if (Temp > 1.0f)
+                Temp = 1.0f;
+            else if (Temp < -1.0f)
+                Temp = -1.0f;
+
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
+        }
+    }
+    else{
+        if (OutLoop){
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (ii = OutLoop; ii != 0; ii--){
+                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+        }
+    }
+    pInstance->Current=Current;
+}
+#else
 void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *ptrInstance,
                                     const LVM_INT16     *src,
                                           LVM_INT16     *dst,
@@ -101,6 +180,5 @@
     }
     pInstance->Current=Current;
 }
-
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
index 0052dd7..192f126 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
@@ -33,7 +33,80 @@
 /**********************************************************************************
    FUNCTION MIXINSOFT_D16C31_SAT
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_FLOAT_st *ptrInstance,
+                               LVM_FLOAT             *src,
+                               LVM_FLOAT             *dst,
+                               LVM_INT16             n)
+{
+    char        HardMixing = TRUE;
+    LVM_FLOAT   TargetGain;
+    Mix_Private_FLOAT_st  *pInstance = \
+                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
 
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Delta == 1.0f){
+            pInstance->Current = pInstance->Target;
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            LVC_Core_MixInSoft_D16C31_SAT(&(ptrInstance->MixerStream[0]), src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
+            if ((pInstance->Target) == 1.0f){
+                Add2_Sat_Float(src, dst, n);
+            }
+            else{
+                Mac3s_Sat_Float(src, (pInstance->Target), dst, n);
+                /* In case the LVCore function would have changed the Current value */
+                pInstance->Current = pInstance->Target;
+            }
+        }
+    }
+
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet){
+        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0){
+                (*ptrInstance->MixerStream[0].pCallBack) ( \
+                                                ptrInstance->MixerStream[0].pCallbackHandle,
+                                                ptrInstance->MixerStream[0].pGeneralPurpose,
+                                                ptrInstance->MixerStream[0].CallbackParam );
+            }
+        }
+    }
+
+}
+#else
 void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
                                     LVM_INT16             *src,
                                     LVM_INT16             *dst,
@@ -108,5 +181,5 @@
     }
 
 }
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
index f443c8f..bd5a925 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
@@ -33,7 +33,138 @@
 /**********************************************************************************
    FUNCTION LVC_MixSoft_1St_2i_D16C31_SAT
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_FLOAT_st *ptrInstance,
+                                    const LVM_FLOAT             *src,
+                                    LVM_FLOAT             *dst,
+                                    LVM_INT16             n)
+{
+    char        HardMixing = TRUE;
+    LVM_FLOAT   TargetGain;
+    Mix_Private_FLOAT_st  *pInstance1 = \
+                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = \
+                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
 
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance1->Current != pInstance1->Target) || (pInstance2->Current != pInstance2->Target))
+    {
+        if(pInstance1->Delta == 1.0f)
+        {
+            pInstance1->Current = pInstance1->Target;
+            TargetGain = pInstance1->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }
+        else if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
+        {
+            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
+                                                         Make them equal. */
+            TargetGain = pInstance1->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }
+        else
+        {
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+        }
+
+        if(HardMixing == TRUE)
+        {
+            if(pInstance2->Delta == 1.0f)
+            {
+                pInstance2->Current = pInstance2->Target;
+                TargetGain = pInstance2->Target;
+                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
+            }
+            else if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
+            {
+                pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore. \
+                                                             Make them equal. */
+                TargetGain = pInstance2->Target;
+                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
+            }
+            else
+            {
+                /* Soft mixing has to be applied */
+                HardMixing = FALSE;
+            }
+        }
+
+        if(HardMixing == FALSE)
+        {
+             LVC_Core_MixSoft_1St_2i_D16C31_WRA( &(ptrInstance->MixerStream[0]),
+                                                 &(ptrInstance->MixerStream[1]),
+                                                 src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing)
+    {
+        if ((pInstance1->Target == 1.0f) && (pInstance2->Target == 1.0f))
+        {
+            if(src != dst)
+            {
+                Copy_Float(src, dst, n);
+            }
+        }
+        else
+        {
+            LVC_Core_MixHard_1St_2i_D16C31_SAT(&(ptrInstance->MixerStream[0]),
+                                               &(ptrInstance->MixerStream[1]),
+                                               src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet)
+    {
+        if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
+        {
+            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
+                                                         Make them equal. */
+            TargetGain = pInstance1->Target;
+            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0], TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0)
+            {
+                (*ptrInstance->MixerStream[0].pCallBack) ( \
+                                                ptrInstance->MixerStream[0].pCallbackHandle,
+                                                ptrInstance->MixerStream[0].pGeneralPurpose,
+                                                ptrInstance->MixerStream[0].CallbackParam );
+            }
+        }
+    }
+    if (ptrInstance->MixerStream[1].CallbackSet)
+    {
+        if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
+        {
+            pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
+                                                         Make them equal. */
+            TargetGain = pInstance2->Target;
+            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1], TargetGain);
+            ptrInstance->MixerStream[1].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[1].pCallBack != 0)
+            {
+                (*ptrInstance->MixerStream[1].pCallBack) (
+                                                ptrInstance->MixerStream[1].pCallbackHandle,
+                                                ptrInstance->MixerStream[1].pGeneralPurpose,
+                                                ptrInstance->MixerStream[1].CallbackParam );
+            }
+        }
+    }
+}
+#else
 void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_st *ptrInstance,
                                   const LVM_INT16             *src,
                                         LVM_INT16             *dst,
@@ -148,5 +279,5 @@
         }
     }
 }
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
index c8dcad7..1017de3 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
@@ -33,7 +33,77 @@
 /**********************************************************************************
    FUNCTION LVMixer3_MIXSOFT_1ST_D16C31_SAT
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_FLOAT_st *ptrInstance,
+                                  const LVM_FLOAT             *src,
+                                        LVM_FLOAT             *dst,
+                                        LVM_INT16             n)
+{
+    char        HardMixing = TRUE;
+    LVM_FLOAT   TargetGain;
+    Mix_Private_FLOAT_st  *pInstance = \
+                          (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
 
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Delta == 1.0f){
+            pInstance->Current = pInstance->Target;
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            LVC_Core_MixSoft_1St_D16C31_WRA(&(ptrInstance->MixerStream[0]), src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target == 0)
+            LoadConst_Float(0.0, dst, n);
+        else {
+            if ((pInstance->Target) != 1.0f)
+                Mult3s_Float(src, (pInstance->Target), dst, n);
+            else if(src != dst)
+                Copy_Float(src, dst, n);
+        }
+
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet){
+        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0){
+                (*ptrInstance->MixerStream[0].pCallBack) ( \
+                                                ptrInstance->MixerStream[0].pCallbackHandle,
+                                                ptrInstance->MixerStream[0].pGeneralPurpose,
+                                                ptrInstance->MixerStream[0].CallbackParam );
+            }
+        }
+    }
+}
+#else
 void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
                                   const LVM_INT16             *src,
                                         LVM_INT16             *dst,
@@ -107,5 +177,5 @@
         }
     }
 }
-
+#endif/*BUILD_FLOAT*/
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
index 7240705..3c90071 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
@@ -25,7 +25,49 @@
 /**********************************************************************************
    FUNCTION LVC_MixSoft_2St_D16C31_SAT.c
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_FLOAT_st *ptrInstance,
+                                 const   LVM_FLOAT       *src1,
+                                 LVM_FLOAT       *src2,
+                                 LVM_FLOAT       *dst,
+                                 LVM_INT16       n)
+{
+    Mix_Private_FLOAT_st  *pInstance1 = \
+                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = \
+                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
 
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance1->Current == pInstance1->Target) && (pInstance1->Current == 0)){
+        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
+                                    src2, dst, n);
+    }
+    else if ((pInstance2->Current == pInstance2->Target) && (pInstance2->Current == 0)){
+        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
+                                    src1, dst, n);
+    }
+    else if ((pInstance1->Current != pInstance1->Target) || \
+                                    (pInstance2->Current != pInstance2->Target))
+    {
+        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
+                                   src1, dst, n);
+        LVC_MixInSoft_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
+                                  src2, dst, n);
+    }
+    else{
+        /******************************************************************************
+           HARD MIXING
+        *******************************************************************************/
+        LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0],
+                                         &ptrInstance->MixerStream[1],
+                                         src1, src2, dst, n);
+    }
+}
+#else
 void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *ptrInstance,
                                     const   LVM_INT16       *src1,
                                             LVM_INT16       *src2,
@@ -66,5 +108,5 @@
             LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0], &ptrInstance->MixerStream[1], src1, src2, dst, n);
     }
 }
-
+#endif /*BUILD_FLOAT*/
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
index 980c783..f904915 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
@@ -31,6 +31,19 @@
 ***********************************************************************************/
 
 /* LVMixer3_st structure stores Instance parameters for one audio stream */
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT       PrivateParams[3];   /* Private Instance params for \
+                                           Audio Stream shift parameter */
+    LVM_INT16       CallbackSet;        /* Boolean.  Should be set by calling application \
+                                           each time the target value is updated */
+    LVM_INT16       CallbackParam;      /* Parameter that will be used in the calback function */
+    void            *pCallbackHandle;   /* Pointer to the instance of the callback function */
+    void            *pGeneralPurpose;   /* Pointer for general purpose usage */
+    LVM_Callback    pCallBack;          /* Pointer to the callback function */
+} LVMixer3_FLOAT_st;
+#else
 typedef struct
 {
     LVM_INT32       PrivateParams[4];   /* Private Instance params for Audio Stream */
@@ -40,22 +53,35 @@
     void            *pGeneralPurpose;   /* Pointer for general purpose usage */
     LVM_Callback    pCallBack;          /* Pointer to the callback function */
 } LVMixer3_st;
-
+#endif
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVMixer3_FLOAT_st     MixerStream[1];    /* Instance Params for one Audio Stream */
+} LVMixer3_1St_FLOAT_st;
+#else
 typedef struct
 {
     LVMixer3_st     MixerStream[1];    /* Instance Params for one Audio Stream */
 } LVMixer3_1St_st;
-
+#endif
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVMixer3_FLOAT_st     MixerStream[2];    /* Instance Params for two Audio Streams */
+} LVMixer3_2St_FLOAT_st;
+#else
 typedef struct
 {
     LVMixer3_st     MixerStream[2];    /* Instance Params for two Audio Streams */
 } LVMixer3_2St_st;
-
+#endif
+#ifndef BUILD_FLOAT
 typedef struct
 {
     LVMixer3_st     MixerStream[3];    /* Instance Params for three Audio Streams */
 } LVMixer3_3St_st;
-
+#endif
 /**********************************************************************************
    FUNCTION PROTOTYPES (HIGH LEVEL FUNCTIONS)
 ***********************************************************************************/
@@ -75,57 +101,115 @@
 /* then the calculation will give an incorrect value for alpha, see the mixer     */
 /* documentation for further details.                                             */
 /* ********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_Mixer_SetTarget( LVMixer3_FLOAT_st *pStream,
+                          LVM_FLOAT        TargetGain);
+#else
 void LVC_Mixer_SetTarget( LVMixer3_st *pStream,
                                 LVM_INT32           TargetGain);
-
+#endif
+#ifdef BUILD_FLOAT
+LVM_FLOAT LVC_Mixer_GetTarget( LVMixer3_FLOAT_st *pStream);
+#else
 LVM_INT32 LVC_Mixer_GetTarget( LVMixer3_st *pStream);
+#endif
 
+#ifdef BUILD_FLOAT
+LVM_FLOAT LVC_Mixer_GetCurrent( LVMixer3_FLOAT_st *pStream);
+#else
 LVM_INT32 LVC_Mixer_GetCurrent( LVMixer3_st *pStream);
+#endif
 
+#ifdef BUILD_FLOAT
+void LVC_Mixer_Init( LVMixer3_FLOAT_st *pStream,
+                     LVM_FLOAT           TargetGain,
+                     LVM_FLOAT           CurrentGain);
+#else
 void LVC_Mixer_Init( LVMixer3_st *pStream,
                                 LVM_INT32           TargetGain,
                                 LVM_INT32           CurrentGain);
+#endif
 
+#ifdef BUILD_FLOAT
+void LVC_Mixer_SetTimeConstant( LVMixer3_FLOAT_st *pStream,
+                                LVM_INT32           Tc_millisec,
+                                LVM_Fs_en           Fs,
+                                LVM_INT16           NumChannels);
+#else
 void LVC_Mixer_SetTimeConstant( LVMixer3_st *pStream,
                                 LVM_INT32           Tc_millisec,
                                 LVM_Fs_en           Fs,
                                 LVM_INT16           NumChannels);
+#endif
 
+#ifdef BUILD_FLOAT
+void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_FLOAT_st *pStream,
+                                         LVM_INT32           Tc_millisec,
+                                         LVM_Fs_en           Fs,
+                                         LVM_INT16           NumChannels);
+#else
 void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_st *pStream,
                                         LVM_INT32           Tc_millisec,
                                         LVM_Fs_en           Fs,
                                         LVM_INT16           NumChannels);
+#endif
 
 /*** 16 bit functions *************************************************************/
 
+#ifdef BUILD_FLOAT
+void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_FLOAT_st *pInstance,
+                                 const LVM_FLOAT           *src,
+                                 LVM_FLOAT           *dst,
+                                 LVM_INT16           n);
+#else
 void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *pInstance,
                                   const LVM_INT16           *src,
                                         LVM_INT16           *dst,
                                         LVM_INT16           n);
+#endif
 
+#ifdef BUILD_FLOAT
+void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_FLOAT_st *pInstance,
+                               LVM_FLOAT           *src,
+                               LVM_FLOAT           *dst,
+                               LVM_INT16           n);
+#else
 void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *pInstance,
                                         LVM_INT16           *src,
                                         LVM_INT16           *dst,
                                         LVM_INT16           n);
+#endif
 
+#ifdef BUILD_FLOAT
+void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_FLOAT_st *pInstance,
+                                 const LVM_FLOAT             *src1,
+                                 LVM_FLOAT             *src2,
+                                 LVM_FLOAT             *dst,  /* dst cannot be equal to src2 */
+                                 LVM_INT16             n);
+#else
 void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *pInstance,
                                 const LVM_INT16             *src1,
                                       LVM_INT16             *src2,
                                       LVM_INT16             *dst,  /* dst cannot be equal to src2 */
                                       LVM_INT16             n);
-
+#endif
 /**********************************************************************************/
 /* For applying different gains to Left and right chennals                        */
 /* MixerStream[0] applies to Left channel                                         */
 /* MixerStream[1] applies to Right channel                                        */
 /* Gain values should not be more that 1.0                                        */
 /**********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_FLOAT_st         *pInstance,
+                                    const   LVM_FLOAT           *src,
+                                    LVM_FLOAT           *dst,   /* dst can be equal to src */
+                                    LVM_INT16           n);     /* Number of stereo samples */
+#else
 void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_st         *pInstance,
                                 const   LVM_INT16           *src,
                                         LVM_INT16           *dst,   /* dst can be equal to src */
                                         LVM_INT16           n);     /* Number of stereo samples */
-
-
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
index b5ae264..5990412 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
@@ -31,7 +31,15 @@
 /*  CurrentGain      - CurrentGain value in Q 16.15 format              */
 /*                                                                      */
 /************************************************************************/
-
+#ifdef BUILD_FLOAT
+LVM_FLOAT LVC_Mixer_GetCurrent( LVMixer3_FLOAT_st *pStream)
+{
+    LVM_FLOAT       CurrentGain;
+    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    CurrentGain = pInstance->Current;  // CurrentGain
+    return CurrentGain;
+}
+#else
 LVM_INT32 LVC_Mixer_GetCurrent( LVMixer3_st *pStream)
 {
     LVM_INT32       CurrentGain;
@@ -39,3 +47,4 @@
     CurrentGain=pInstance->Current>>(16-pInstance->Shift);  // CurrentGain in Q16.15 format
     return CurrentGain;
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
index dc2f8e9..c67455a 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
@@ -30,7 +30,16 @@
 /*  TargetGain      - TargetGain value in Q 16.15 format                */
 /*                                                                      */
 /************************************************************************/
-
+#ifdef BUILD_FLOAT
+LVM_FLOAT LVC_Mixer_GetTarget( LVMixer3_FLOAT_st *pStream)
+{
+    LVM_FLOAT       TargetGain;
+    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    
+    TargetGain = pInstance->Target;  // TargetGain
+    return TargetGain;
+}
+#else
 LVM_INT32 LVC_Mixer_GetTarget( LVMixer3_st *pStream)
 {
     LVM_INT32       TargetGain;
@@ -40,3 +49,4 @@
 
     return TargetGain;
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c
index 449e7b1..737e26b 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c
@@ -44,7 +44,19 @@
 /*  void                                                                */
 /*                                                                      */
 /************************************************************************/
-
+#ifdef BUILD_FLOAT
+void LVC_Mixer_Init( LVMixer3_FLOAT_st *pStream,
+                     LVM_FLOAT           TargetGain,
+                     LVM_FLOAT           CurrentGain)
+{
+    LVM_FLOAT MaxGain = TargetGain;
+    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    if(CurrentGain > MaxGain)
+        MaxGain = CurrentGain;
+    pInstance->Target = TargetGain;   // Update fractional gain Target
+    pInstance->Current = CurrentGain; // Update fractional gain Current
+}
+#else
 void LVC_Mixer_Init( LVMixer3_st *pStream,
                     LVM_INT32           TargetGain,
                     LVM_INT32           CurrentGain)
@@ -64,4 +76,4 @@
     pInstance->Current=CurrentGain<<(16-Shift); // Update fractional gain Current
     pInstance->Shift=Shift;                     // Update Shift
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
index 294e05c..d0d0e1f 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -26,6 +26,15 @@
 #include "VectorArithmetic.h"
 
 /* Instance parameter structure */
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    /* General */
+    LVM_FLOAT                       Target;           /*number specifying value of Target Gain */
+    LVM_FLOAT                       Current;          /*number specifying value of Current Gain */
+    LVM_FLOAT                       Delta;            /*number specifying value of Delta Gain */
+} Mix_Private_FLOAT_st;
+#else
 typedef struct
 {
     /* General */
@@ -34,8 +43,7 @@
     LVM_INT32                       Shift;                  /* Left Shift for Integer part of Gain */
     LVM_INT32                       Delta;                  /* 32 bit number specifying the fractional value of Delta Gain */
 } Mix_Private_st;
-
-
+#endif
 
 /**********************************************************************************
    DEFINITIONS
@@ -49,23 +57,43 @@
 ***********************************************************************************/
 
 /*** 16 bit functions *************************************************************/
-
+#ifdef BUILD_FLOAT
+void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_FLOAT_st *ptrInstance,
+                                    const LVM_FLOAT     *src,
+                                    LVM_FLOAT     *dst,
+                                    LVM_INT16     n);
+#else
 void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *pInstance,
                                     const LVM_INT16     *src,
                                           LVM_INT16     *dst,
                                           LVM_INT16     n);
-
+#endif
+#ifdef BUILD_FLOAT
+void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_FLOAT_st *ptrInstance,
+                                      const LVM_FLOAT     *src,
+                                      LVM_FLOAT     *dst,
+                                      LVM_INT16     n);
+#else
 void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *pInstance,
                                     const LVM_INT16     *src,
                                           LVM_INT16     *dst,
                                           LVM_INT16     n);
-
+#endif
+#ifdef BUILD_FLOAT
+void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_FLOAT_st *pInstance1,
+                                      LVMixer3_FLOAT_st         *pInstance2,
+                                      const LVM_FLOAT     *src1,
+                                      const LVM_FLOAT     *src2,
+                                      LVM_FLOAT     *dst,
+                                      LVM_INT16     n);
+#else
 void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_st *pInstance1,
                                     LVMixer3_st         *pInstance2,
                                     const LVM_INT16     *src1,
                                     const LVM_INT16     *src2,
                                           LVM_INT16     *dst,
                                           LVM_INT16     n);
+#endif
 
 /**********************************************************************************/
 /* For applying different gains to Left and right chennals                        */
@@ -73,12 +101,19 @@
 /* ptrInstance2 applies to Right channel                                          */
 /* Gain values should not be more that 1.0                                        */
 /**********************************************************************************/
-
+#ifdef BUILD_FLOAT
+void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_FLOAT_st        *ptrInstance1,
+                                         LVMixer3_FLOAT_st        *ptrInstance2,
+                                         const LVM_FLOAT    *src,
+                                         LVM_FLOAT          *dst,
+                                         LVM_INT16          n);
+#else
 void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_st        *ptrInstance1,
                                          LVMixer3_st        *ptrInstance2,
                                          const LVM_INT16    *src,
                                          LVM_INT16          *dst,   /* dst can be equal to src */
                                          LVM_INT16          n);     /* Number of stereo samples */
+#endif
 
 /**********************************************************************************/
 /* For applying different gains to Left and right chennals                        */
@@ -86,16 +121,22 @@
 /* ptrInstance2 applies to Right channel                                          */
 /* Gain values should not be more that 1.0                                        */
 /**********************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_FLOAT_st        *ptrInstance1,
+                                         LVMixer3_FLOAT_st        *ptrInstance2,
+                                         const LVM_FLOAT    *src,
+                                         LVM_FLOAT          *dst,
+                                         LVM_INT16          n);
+#else
 void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_st        *ptrInstance1,
                                          LVMixer3_st        *ptrInstance2,
                                          const LVM_INT16    *src,
                                          LVM_INT16          *dst,    /* dst can be equal to src */
                                          LVM_INT16          n);      /* Number of stereo samples */
-
-
+#endif
 
 /*** 32 bit functions *************************************************************/
-
+#ifndef BUILD_FLOAT
 void LVC_Core_MixInSoft_D32C31_SAT( LVMixer3_st *pInstance,
                                     const LVM_INT32     *src,
                                           LVM_INT32     *dst,
@@ -112,7 +153,7 @@
                                     const LVM_INT32     *src2,
                                           LVM_INT32     *dst,
                                           LVM_INT16     n);
-
+#endif
 /**********************************************************************************/
 
 #endif //#ifndef __LVC_MIXER_PRIVATE_H__
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c
index 5efa501..577179d 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c
@@ -43,7 +43,14 @@
 /*  void                                                                */
 /*                                                                      */
 /************************************************************************/
-
+#ifdef BUILD_FLOAT
+void LVC_Mixer_SetTarget(LVMixer3_FLOAT_st *pStream,
+                         LVM_FLOAT         TargetGain)
+{
+    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    pInstance->Target = TargetGain;               // Update gain Target
+}
+#else
 void LVC_Mixer_SetTarget(LVMixer3_st *pStream,
                         LVM_INT32           TargetGain)
 {
@@ -64,3 +71,4 @@
     pInstance->Current=CurrentGain<<(16-Shift);             // Update fractional gain Current
     pInstance->Shift=Shift;                                 // Update Shift
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c
index 4c1c8b2..48f5d54 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c
@@ -44,7 +44,51 @@
 /* RETURNS:                                                             */
 /*  void                                                                */
 /************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_Mixer_SetTimeConstant(LVMixer3_FLOAT_st *pStream,
+                               LVM_INT32           Tc_millisec,
+                               LVM_Fs_en           Fs,
+                               LVM_INT16           NumChannels)
+{
+#ifdef HIGHER_FS
+    LVM_FLOAT   DeltaTable[11] = {0.500000f,/*8000*/
+                                  0.362812f,/*11025*/
+                                  0.333333f,/*12000*/
+                                  0.250000f,/*16000*/
+                                  0.181406f,/*22050*/
+                                  0.166666f,/*24000*/
+                                  0.125000f,/*32000*/
+                                  0.090703f,/*44100*/
+                                  0.083333f,/*48000*/
+                                  0.041667f,/*96000*/
+                                  0.020833f};/*192000*/
+#else
+    LVM_FLOAT   DeltaTable[9] = {0.500000f,/*8000*/
+                                 0.362812f,/*11025*/
+                                 0.333333f,/*12000*/
+                                 0.250000f,/*16000*/
+                                 0.181406f,/*22050*/
+                                 0.166666f,/*24000*/
+                                 0.125000f,/*32000*/
+                                 0.090703f,/*44100*/
+                                 0.083333f};/*48000*/
+#endif
 
+    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    LVM_FLOAT Delta = DeltaTable[Fs];
+    Delta = Delta / (NumChannels);
+
+    if(Tc_millisec == 0)
+        Delta = 1.000000f;
+    else
+        Delta = Delta / Tc_millisec;
+
+    if(Delta == 0)
+        Delta = 0.0000000005f;  /* If Time Constant is so large that Delta is 0, \
+                                  assign minimum value to Delta */
+    pInstance->Delta = Delta;  // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)
+}
+#else
 void LVC_Mixer_SetTimeConstant(LVMixer3_st *pStream,
                             LVM_INT32           Tc_millisec,
                             LVM_Fs_en           Fs,
@@ -73,3 +117,4 @@
 
     pInstance->Delta=Delta;     // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) in Q 0.31 format
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
index 8d5304e..9dc7d21 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
@@ -45,7 +45,72 @@
 /* RETURNS:                                                             */
 /*  void                                                                */
 /************************************************************************/
+#ifdef BUILD_FLOAT
+void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_FLOAT_st *pStream,
+                                         LVM_INT32           Tc_millisec,
+                                         LVM_Fs_en           Fs,
+                                         LVM_INT16           NumChannels)
+{
+#ifdef HIGHER_FS
+     LVM_FLOAT   DeltaTable[11] = {0.500000f,/*8000*/
+                                   0.362812f,/*11025*/
+                                   0.333333f,/*12000*/
+                                   0.250000f,/*16000*/
+                                   0.181406f,/*22050*/
+                                   0.166666f,/*24000*/
+                                   0.125000f,/*32000*/
+                                   0.090703f,/*44100*/
+                                   0.083333f,/*48000*/
+                                   0.041666f,/*96000*/
+                                   0.020833f};/*192000*/
+#else
+    LVM_FLOAT   DeltaTable[9] = {0.500000f,/*8000*/
+                                 0.362812f,/*11025*/
+                                 0.333333f,/*12000*/
+                                 0.250000f,/*16000*/
+                                 0.181406f,/*22050*/
+                                 0.166666f,/*24000*/
+                                 0.125000f,/*32000*/
+                                 0.090703f,/*44100*/
+                                 0.083333f};/*48000*/
+#endif
+    LVM_FLOAT Tc_millisec_float;
+    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    LVM_FLOAT Delta = DeltaTable[Fs];
 
+    LVM_FLOAT   Current;
+    LVM_FLOAT   Target;
+
+    Delta=Delta / (NumChannels);
+
+    /*  Get gain values  */
+    Current = pInstance->Current;
+    Target = pInstance->Target;
+
+    if (Current != Target)
+    {
+        Tc_millisec_float = (LVM_FLOAT)(Tc_millisec) / (Current - Target);
+        if (Tc_millisec_float < 0)
+            Tc_millisec_float = -Tc_millisec_float;
+
+        if(Tc_millisec == 0)
+            Delta = 1.000000f;
+        else
+            Delta = Delta / Tc_millisec_float;
+
+        if(Delta == 0)
+            Delta = 0.0000000005f; /* If Time Constant is so large that Delta is 0, \
+                                      assign minimum value to Delta */
+    }
+    else
+    {
+        Delta = 0.0000000005f;  /* Minimum value for proper call-backs \
+                             (setting it to zero has some problems, to be corrected) */
+    }
+
+    pInstance->Delta = Delta;     // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)
+}
+#else
 void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_st *pStream,
                                         LVM_INT32           Tc_millisec,
                                         LVM_Fs_en           Fs,
@@ -93,3 +158,4 @@
 
     pInstance->Delta=Delta;     // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) in Q 0.31 format
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
index 6d8fe46..9094622 100644
--- a/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
@@ -53,7 +53,7 @@
 /*   A9             194669577                                              */
 /*   A10            8                                                      */
 /*                                                                         */
-/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + Â….. + AN*xN) << AN+1                  */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
 /*                                                                         */
 /*                                                                         */
 /* PARAMETERS:                                                             */
@@ -68,7 +68,36 @@
 /* RETURNS:                                                                */
 /*                                                                         */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+LVM_FLOAT LVM_FO_HPF(   LVM_FLOAT       w,
+                        FO_FLOAT_Coefs_t  *pCoeffs)
+{
+    LVM_FLOAT Y,Coefficients[13] = {-0.999996f,
+                                    0.999801f,
+                                    -0.497824f,
+                                    0.322937f,
+                                    -0.180880f,
+                                    0.087658f,
+                                    -0.032102f,
+                                    0.008163f,
+                                    -0.001252f,
+                                    0.000089f,
+                                    0,
+                                    0,
+                                    0};
+    Y=LVM_Polynomial((LVM_UINT16)9, Coefficients, w);
 
+    pCoeffs->B1 = -Y;         /* Store -B1 in filter structure instead of B1!*/
+                            /* A0=(1-B1)/2= B1/2 - 0.5*/
+    Y = Y / 2.0f;                 /* A0=Y=B1/2*/
+    Y = Y - 0.5f;         /* A0=Y=(B1/2 - 0.5)*/
+
+    pCoeffs->A0 = Y * FILTER_LOSS_FLOAT;                  /* Apply loss to avoid overflow*/
+    pCoeffs->A1 = -pCoeffs->A0;                           /* Store A1=-A0*/
+
+    return 1;
+}
+#else
 LVM_INT32 LVM_FO_HPF(   LVM_INT32       w,
                         FO_C32_Coefs_t  *pCoeffs)
 {
@@ -97,4 +126,4 @@
 
     return 1;
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
index 86ec951..9fe67f8 100644
--- a/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
@@ -53,7 +53,7 @@
 /*   A9             194669577                                              */
 /*   A10            8                                                      */
 /*                                                                         */
-/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + Â….. + AN*xN) << AN+1                  */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
 /*                                                                         */
 /*                                                                         */
 /* PARAMETERS:                                                             */
@@ -68,7 +68,33 @@
 /* RETURNS:                                                                */
 /*                                                                         */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+LVM_FLOAT LVM_FO_LPF(   LVM_FLOAT       w,
+                        FO_FLOAT_Coefs_t  *pCoeffs)
+{
+    LVM_FLOAT Y,Coefficients[13] = {-0.999996f,
+                                    0.999801f,
+                                    -0.497824f,
+                                    0.322937f,
+                                    -0.180880f,
+                                    0.087658f,
+                                    -0.032102f,
+                                    0.008163f,
+                                    -0.001252f,
+                                    0.000089f,
+                                    0};
+    Y=LVM_Polynomial((LVM_UINT16)9, Coefficients, w);
+    pCoeffs->B1 = -Y;     // Store -B1 in filter structure instead of B1!
+                        // A0=(1+B1)/2= B1/2 + 0.5
+    Y = Y / 2.0f;             // A0=Y=B1/2
+    Y = Y + 0.5f;     // A0=Y=(B1/2 + 0.5)
 
+    pCoeffs->A0 = Y * FILTER_LOSS_FLOAT;
+    pCoeffs->A1 = pCoeffs->A0;
+
+    return 1;
+}
+#else
 LVM_INT32 LVM_FO_LPF(   LVM_INT32       w,
                         FO_C32_Coefs_t  *pCoeffs)
 {
@@ -94,4 +120,4 @@
     pCoeffs->A1=pCoeffs->A0;
     return 1;
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
index f3b9b3c..7846ca0 100644
--- a/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
+++ b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
@@ -32,16 +32,45 @@
 #define LVVDL_2PiByFs_SHIFT1    12          /* Qformat shift for 8kHz, 11.025kHz and 12kHz i.e. 12=41-29 */
 #define LVVDL_2PiByFs_SHIFT2    13          /* Qformat shift for 16kHz, 22.050kHz and 24kHz i.e. 13=42-29 */
 #define LVVDL_2PiByFs_SHIFT3    14          /* Qformat shift for 32kHz, 44.1kHz and 48kHz i.e. 14=43-29 */
-
+#ifndef BUILD_FLOAT
 const LVM_INT32     LVVDL_2PiOnFsTable[] =  {LVVDL_2PiBy_8000 , /* 8kHz in Q41, 16kHz in Q42, 32kHz in Q43 */
                                             LVVDL_2PiBy_11025,  /* 11025 Hz in Q41, 22050Hz in Q42, 44100 Hz in Q43*/
                                             LVVDL_2PiBy_12000}; /* 12kHz in Q41, 24kHz in Q42, 48kHz in Q43 */
-
+#endif
 
 const LVM_INT32     LVVDL_2PiOnFsShiftTable[]={LVVDL_2PiByFs_SHIFT1 ,         /* 8kHz, 11025Hz, 12kHz */
                                                LVVDL_2PiByFs_SHIFT2,          /* 16kHz, 22050Hz, 24kHz*/
                                                LVVDL_2PiByFs_SHIFT3};         /* 32kHz, 44100Hz, 48kHz */
+#ifdef BUILD_FLOAT
+#define LVVDL_2PiBy_8000_f        0.000785398f
+#define LVVDL_2PiBy_11025_f       0.000569903f
+#define LVVDL_2PiBy_12000_f       0.000523599f
+#define LVVDL_2PiBy_16000_f       0.000392700f
+#define LVVDL_2PiBy_22050_f       0.000284952f
+#define LVVDL_2PiBy_24000_f       0.000261800f
+#define LVVDL_2PiBy_32000_f       0.000196350f
+#define LVVDL_2PiBy_44100_f       0.000142476f
+#define LVVDL_2PiBy_48000_f       0.000130900f
 
+#ifdef HIGHER_FS
+#define LVVDL_2PiBy_96000_f       0.000065450f
+#define LVVDL_2PiBy_192000_f      0.000032725f
+#endif
+const LVM_FLOAT     LVVDL_2PiOnFsTable[] =  {LVVDL_2PiBy_8000_f,
+                                             LVVDL_2PiBy_11025_f,
+                                             LVVDL_2PiBy_12000_f,
+                                             LVVDL_2PiBy_16000_f,
+                                             LVVDL_2PiBy_22050_f,
+                                             LVVDL_2PiBy_24000_f,
+                                             LVVDL_2PiBy_32000_f,
+                                             LVVDL_2PiBy_44100_f,
+                                             LVVDL_2PiBy_48000_f
+#ifdef HIGHER_FS
+                                            ,LVVDL_2PiBy_96000_f
+                                            ,LVVDL_2PiBy_192000_f
+#endif
+                                           };
+#endif
 /*-------------------------------------------------------------------------*/
 /* FUNCTION:                                                               */
 /*   LVM_GetOmega                                                          */
@@ -59,7 +88,20 @@
 /* RETURNS:                                                                */
 /*   w=2*pi*Fc/Fs in Q2.29 format                                          */
 /*-------------------------------------------------------------------------*/
-
+#ifdef BUILD_FLOAT
+#ifdef HIGHER_FS
+LVM_FLOAT LVM_GetOmega(LVM_UINT32                  Fc,
+                       LVM_Fs_en                   Fs)
+#else
+LVM_FLOAT LVM_GetOmega(LVM_UINT16                  Fc,
+                       LVM_Fs_en                   Fs)
+#endif
+{
+    LVM_FLOAT   w;
+    w = (LVM_FLOAT)Fc * LVVDL_2PiOnFsTable[Fs];
+    return w;
+}
+#else
 LVM_INT32 LVM_GetOmega(LVM_UINT16                  Fc,
                        LVM_Fs_en                   Fs)
 {
@@ -67,4 +109,4 @@
     MUL32x32INTO32((LVM_INT32)Fc,LVVDL_2PiOnFsTable[Fs%3],w,LVVDL_2PiOnFsShiftTable[Fs/3])
     return w;
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
index 6846d49..f1e45fa 100644
--- a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
@@ -87,5 +87,58 @@
 #define ALPHA_49                                0      /* Floating point Alpha = 0.000000 */
 #define ALPHA_50                                0      /* Floating point Alpha = 0.000000 */
 
+#ifdef BUILD_FLOAT /* BUILD_FLOAT */
+#define ALPHA_Float_0                        0.999999f
+#define ALPHA_Float_1                        0.999998f
+#define ALPHA_Float_2                        0.999997f
+#define ALPHA_Float_3                        0.999996f
+#define ALPHA_Float_4                        0.999995f
+#define ALPHA_Float_5                        0.999992f
+#define ALPHA_Float_6                        0.999989f
+#define ALPHA_Float_7                        0.999985f
+#define ALPHA_Float_8                        0.999979f
+#define ALPHA_Float_9                        0.999970f
+#define ALPHA_Float_10                       0.999957f
+#define ALPHA_Float_11                       0.999939f
+#define ALPHA_Float_12                       0.999914f
+#define ALPHA_Float_13                       0.999879f
+#define ALPHA_Float_14                       0.999829f
+#define ALPHA_Float_15                       0.999758f
+#define ALPHA_Float_16                       0.999658f
+#define ALPHA_Float_17                       0.999516f
+#define ALPHA_Float_18                       0.999316f
+#define ALPHA_Float_19                       0.999033f
+#define ALPHA_Float_20                       0.998633f
+#define ALPHA_Float_21                       0.998067f
+#define ALPHA_Float_22                       0.997268f
+#define ALPHA_Float_23                       0.996139f
+#define ALPHA_Float_24                       0.994545f
+#define ALPHA_Float_25                       0.992295f
+#define ALPHA_Float_26                       0.989123f
+#define ALPHA_Float_27                       0.984654f
+#define ALPHA_Float_28                       0.978370f
+#define ALPHA_Float_29                       0.969553f
+#define ALPHA_Float_30                       0.957221f
+#define ALPHA_Float_31                       0.940051f
+#define ALPHA_Float_32                       0.916297f
+#define ALPHA_Float_33                       0.883729f
+#define ALPHA_Float_34                       0.839645f
+#define ALPHA_Float_35                       0.781036f
+#define ALPHA_Float_36                       0.705078f
+#define ALPHA_Float_37                       0.610108f
+#define ALPHA_Float_38                       0.497239f
+#define ALPHA_Float_39                       0.372343f
+#define ALPHA_Float_40                       0.247351f
+#define ALPHA_Float_41                       0.138722f
+#define ALPHA_Float_42                       0.061234f
+#define ALPHA_Float_43                       0.019267f
+#define ALPHA_Float_44                       0.003756f
+#define ALPHA_Float_45                       0.000372f
+#define ALPHA_Float_46                       0.000014f
+#define ALPHA_Float_47                       0.000000f
+#define ALPHA_Float_48                       0.000000f
+#define ALPHA_Float_49                       0.000000f
+#define ALPHA_Float_50                       0.000000f
+#endif
 
 #endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
index 809d904..18b2782 100644
--- a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
@@ -57,7 +57,110 @@
 /*  Alpha   - the filter coefficient Q31 format                         */
 /*                                                                      */
 /************************************************************************/
+#ifdef BUILD_FLOAT
+LVM_FLOAT LVM_Mixer_TimeConstant(LVM_UINT32   tc,
+#ifdef HIGHER_FS
+                                  LVM_UINT32   Fs,
+#else
+                                  LVM_UINT16   Fs,
+#endif
+                                  LVM_UINT16   NumChannels)
+{
 
+    LVM_UINT32  Product;
+    LVM_FLOAT  ProductFloat;
+    LVM_INT16   InterpolateShort;
+    LVM_FLOAT   Interpolate;
+    LVM_UINT16  Shift;
+    LVM_FLOAT   Diff;
+    LVM_FLOAT  Table[] = {ALPHA_Float_0,             /* Log spaced look-up table */
+                          ALPHA_Float_1,
+                          ALPHA_Float_2,
+                          ALPHA_Float_3,
+                          ALPHA_Float_4,
+                          ALPHA_Float_5,
+                          ALPHA_Float_6,
+                          ALPHA_Float_7,
+                          ALPHA_Float_8,
+                          ALPHA_Float_9,
+                          ALPHA_Float_10,
+                          ALPHA_Float_11,
+                          ALPHA_Float_12,
+                          ALPHA_Float_13,
+                          ALPHA_Float_14,
+                          ALPHA_Float_15,
+                          ALPHA_Float_16,
+                          ALPHA_Float_17,
+                          ALPHA_Float_18,
+                          ALPHA_Float_19,
+                          ALPHA_Float_20,
+                          ALPHA_Float_21,
+                          ALPHA_Float_22,
+                          ALPHA_Float_23,
+                          ALPHA_Float_24,
+                          ALPHA_Float_25,
+                          ALPHA_Float_26,
+                          ALPHA_Float_27,
+                          ALPHA_Float_28,
+                          ALPHA_Float_29,
+                          ALPHA_Float_30,
+                          ALPHA_Float_31,
+                          ALPHA_Float_32,
+                          ALPHA_Float_33,
+                          ALPHA_Float_34,
+                          ALPHA_Float_35,
+                          ALPHA_Float_36,
+                          ALPHA_Float_37,
+                          ALPHA_Float_38,
+                          ALPHA_Float_39,
+                          ALPHA_Float_40,
+                          ALPHA_Float_41,
+                          ALPHA_Float_42,
+                          ALPHA_Float_43,
+                          ALPHA_Float_44,
+                          ALPHA_Float_45,
+                          ALPHA_Float_46,
+                          ALPHA_Float_47,
+                          ALPHA_Float_48,
+                          ALPHA_Float_49,
+                          ALPHA_Float_50};
+
+    /* Calculate the product of the time constant and the sample rate */
+    Product = ((tc >> 16) * (LVM_UINT32)Fs) << 13;  /* Stereo value */
+    Product = Product + (((tc & 0x0000FFFF) * (LVM_UINT32)Fs) >> 3);
+
+    if (NumChannels == 1)
+    {
+        Product = Product >> 1;   /* Mono value */
+    }
+
+    /* Normalize to get the table index and interpolation factor */
+    for (Shift = 0; Shift < ((Alpha_TableSize - 1) / 2); Shift++)
+    {
+        if ((Product & 0x80000000) != 0)
+        {
+            break;
+        }
+
+        Product = Product << 1;
+    }
+    Shift = (LVM_UINT16)((Shift << 1));
+
+    if ((Product & 0x40000000)==0)
+    {
+        Shift++;
+    }
+
+    InterpolateShort = (LVM_INT16)((Product >> 15) & 0x00007FFF);
+    Interpolate = (LVM_FLOAT)InterpolateShort / 32768.0f;
+
+    Diff = (Table[Shift] - Table[Shift + 1]);
+    Diff = Diff * Interpolate;
+    ProductFloat = Table[Shift + 1] + Diff;
+
+    return ProductFloat;
+}
+#else
 LVM_UINT32 LVM_Mixer_TimeConstant(LVM_UINT32   tc,
                                   LVM_UINT16   Fs,
                                   LVM_UINT16   NumChannels)
@@ -154,3 +257,4 @@
 
     return Product;
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
index a6d7db2..cd57767 100644
--- a/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
@@ -25,7 +25,7 @@
 /*                                                                         */
 /* DESCRIPTION:                                                            */
 /*   This function performs polynomial expansion                           */
-/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + Â….. + AN*xN) << AN+1                  */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
 /*                                                                         */
 /*  LVM_INT32 LVM_Polynomial(LVM_UINT16    N,                              */
 /*                           LVM_INT32    *pCoefficients,                  */
@@ -40,7 +40,48 @@
 /* RETURNS:                                                                */
 /*   The result of the polynomial expansion in Q1.31 format                */
 /*-------------------------------------------------------------------------*/
+#ifdef BUILD_FLOAT
+LVM_FLOAT LVM_Polynomial(LVM_UINT16    N,
+                         LVM_FLOAT    *pCoefficients,
+                         LVM_FLOAT    X)
+{
+    LVM_INT32 i;
+    LVM_FLOAT Y,A,XTemp,Temp,sign;
 
+    Y = *pCoefficients; /* Y=A0*/
+    pCoefficients++;
+
+    if(X == -1.0f)
+    {
+        Temp = -1;
+        sign = Temp;
+        for(i = 1; i <= N; i++)
+        {
+            Y += ((*pCoefficients) * sign);
+            pCoefficients++;
+            sign *= Temp;
+        }
+
+
+    }
+    else
+    {
+        XTemp = X;
+        for(i = N-1; i >= 0; i--)
+        {
+            A = *pCoefficients;
+            pCoefficients++;
+
+            Temp = A * XTemp;
+            Y += Temp;
+
+            Temp = XTemp * X;
+            XTemp = Temp;
+        }
+    }
+    return Y;
+}
+#else
 LVM_INT32 LVM_Polynomial(LVM_UINT16    N,
                          LVM_INT32    *pCoefficients,
                          LVM_INT32    X)
@@ -93,4 +134,4 @@
     }
     return Y;
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Power10.c b/media/libeffects/lvm/lib/Common/src/LVM_Power10.c
index 6ca1077..8785594 100644
--- a/media/libeffects/lvm/lib/Common/src/LVM_Power10.c
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Power10.c
@@ -44,7 +44,7 @@
 /*   A11            50477244                                               */
 /*   A12            -2                                                     */
 /*                                                                         */
-/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + Â….. + AN*xN) << AN+1                  */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
 /*                                                                         */
 /*                                                                         */
 /* PARAMETERS:                                                             */
@@ -54,7 +54,28 @@
 /* RETURNS:                                                                */
 /*   The result of the 10x expansion in Q8.24 format                       */
 /*-------------------------------------------------------------------------*/
-
+#ifdef BUILD_FLOAT
+LVM_FLOAT LVM_Power10(LVM_FLOAT     X)
+{
+    LVM_FLOAT Y,Coefficients[13]={0.999906f,
+                                  2.302475f,
+                                  2.652765f,
+                                  2.035494f,
+                                  1.165667f,
+                                  0.537676f,
+                                  0.213192f,
+                                  0.069603f,
+                                  0.016553f,
+                                  0.004373f,
+                                  0.001817f,
+                                  0.000367f,
+                                  0};
+    Y=LVM_Polynomial((LVM_UINT16)11,
+                     Coefficients,
+                     X);
+    return Y;
+}
+#else
 LVM_INT32 LVM_Power10(LVM_INT32     X)
 {
     LVM_INT32 Y,Coefficients[13]={  16775636,
@@ -75,4 +96,4 @@
                         X);
     return Y;
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_32.c b/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
index 2f1e591..9e14c3b 100644
--- a/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
+++ b/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
@@ -24,7 +24,22 @@
 /**********************************************************************************
    FUNCTION LoadConst_32
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void LoadConst_Float(const LVM_FLOAT   val,
+                     LVM_FLOAT  *dst,
+                     LVM_INT16 n )
+{
+    LVM_INT16 ii;
 
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = val;
+        dst++;
+    }
+
+    return;
+}
+#else
 void LoadConst_32(const LVM_INT32   val,
                         LVM_INT32  *dst,
                         LVM_INT16 n )
@@ -39,5 +54,6 @@
 
     return;
 }
+#endif
 
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c
index 26297e7..02c906a 100644
--- a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c
+++ b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c
@@ -77,4 +77,58 @@
 
     return;
 }
+#ifdef BUILD_FLOAT
+void MSTo2i_Sat_Float(const LVM_FLOAT  *srcM,
+                      const LVM_FLOAT  *srcS,
+                      LVM_FLOAT  *dst,
+                      LVM_INT16  n )
+{
+    LVM_FLOAT temp,mVal,sVal;
+    LVM_INT16 ii;
+
+
+    for (ii = n; ii != 0; ii--)
+    {
+        mVal = (LVM_FLOAT)*srcM;
+        srcM++;
+
+        sVal = (LVM_FLOAT)*srcS;
+        srcS++;
+
+        temp = mVal + sVal;
+
+        if (temp > 1.0f)
+        {
+            *dst = 1.0f;
+        }
+        else if (temp < -1.0f)
+        {
+            *dst = -1.0f;
+        }
+        else
+        {
+            *dst = (LVM_FLOAT)temp;
+        }
+        dst++;
+
+        temp = mVal - sVal;
+
+        if (temp > 1.0f)
+        {
+            *dst = 1.0f;
+        }
+        else if (temp < -1.0f)
+        {
+            *dst = - 1.0f;
+        }
+        else
+        {
+            *dst = (LVM_FLOAT)temp;
+        }
+        dst++;
+    }
+
+    return;
+}
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
index f28f366..e3fb40d 100644
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
@@ -64,7 +64,44 @@
 
     return;
 }
+#ifdef BUILD_FLOAT
+void Mac3s_Sat_Float(const LVM_FLOAT *src,
+                     const LVM_FLOAT val,
+                     LVM_FLOAT *dst,
+                     LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_FLOAT srcval;
+    LVM_FLOAT Temp,dInVal;
 
+    for (ii = n; ii != 0; ii--)
+    {
+        srcval = *src;
+        src++;
+
+        Temp = srcval * val;
+
+        dInVal  = (LVM_FLOAT)*dst;
+        Temp = Temp + dInVal;
+
+        if (Temp > 1.000000f)
+        {
+            *dst = 1.000000f;
+        }
+        else if (Temp < -1.000000f)
+        {
+            *dst = -1.000000f;
+        }
+        else
+        {
+            *dst = Temp;
+        }
+        dst++;
+    }
+
+    return;
+}
+#endif
 /**********************************************************************************/
 
 
diff --git a/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
index 73c26ed..16e367b 100644
--- a/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
@@ -32,7 +32,71 @@
 /**********************************************************************************
    FUNCTION MIXINSOFT_D32C31_SAT
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void MixInSoft_D32C31_SAT( Mix_1St_Cll_FLOAT_t        *pInstance,
+                           const LVM_FLOAT      *src,
+                           LVM_FLOAT      *dst,
+                           LVM_INT16      n)
+{
+    char HardMixing = TRUE;
 
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Alpha == 0){
+            pInstance->Current = pInstance->Target;
+        }else if ((pInstance->Current-pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
+                 (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            Core_MixInSoft_D32C31_SAT(pInstance, src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
+            if ((pInstance->Target) == 1.0f)
+                Add2_Sat_Float(src, dst, n);
+            else{
+                Core_MixInSoft_D32C31_SAT(pInstance, src, dst, n);
+                pInstance->Current = pInstance->Target; /* In case the core function would \
+                                                           have changed the Current value */
+            }
+        }
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+    /* Call back before the hard mixing, because in this case, hard mixing makes
+       use of the core soft mix function which can change the Current value!      */
+
+    if (pInstance->CallbackSet){
+        if ((pInstance->Current - pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
+            (pInstance->Current - pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            pInstance->CallbackSet = FALSE;
+            if (pInstance->pCallBack != 0){
+                (*pInstance->pCallBack) ( pInstance->pCallbackHandle,
+                                          pInstance->pGeneralPurpose,
+                                          pInstance->CallbackParam );
+            }
+        }
+    }
+}
+#else
 void MixInSoft_D32C31_SAT( Mix_1St_Cll_t        *pInstance,
                            const LVM_INT32      *src,
                                  LVM_INT32      *dst,
@@ -91,5 +155,5 @@
         }
     }
 }
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
index ca88b04..869293b 100644
--- a/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
@@ -34,7 +34,68 @@
 /**********************************************************************************
    FUNCTION MIXSOFT_1ST_D32C31_WRA
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_FLOAT_t       *pInstance,
+                                const LVM_FLOAT     *src,
+                                      LVM_FLOAT     *dst,
+                                      LVM_INT16     n)
+{
+    char HardMixing = TRUE;
 
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Alpha == 0){
+            pInstance->Current = pInstance->Target;
+        }else if ((pInstance->Current - pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
+                 (pInstance->Current - pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            Core_MixSoft_1St_D32C31_WRA(pInstance, src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target == 0)
+            LoadConst_Float(0, dst, n);
+        else if ((pInstance->Target) == 1.0f){
+            if (src != dst)
+                Copy_Float((LVM_FLOAT*)src, (LVM_FLOAT*)dst, (LVM_INT16)(n));
+        }
+        else
+            Mult3s_Float(src, pInstance->Current, dst, n);
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (pInstance->CallbackSet){
+        if ((pInstance->Current - pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
+            (pInstance->Current - pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            pInstance->CallbackSet = FALSE;
+            if (pInstance->pCallBack != 0){
+                (*pInstance->pCallBack) ( pInstance->pCallbackHandle,
+                                          pInstance->pGeneralPurpose,
+                                          pInstance->CallbackParam );
+            }
+        }
+    }
+}
+#else
 void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_t       *pInstance,
                                 const LVM_INT32     *src,
                                       LVM_INT32     *dst,
@@ -91,5 +152,5 @@
         }
     }
 }
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c
index 2e0a099..6fc1b92 100644
--- a/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c
@@ -26,7 +26,44 @@
 /**********************************************************************************
    FUNCTION MIXSOFT_2ST_D32C31_SAT
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void MixSoft_2St_D32C31_SAT(    Mix_2St_Cll_FLOAT_t       *pInstance,
+                                const LVM_FLOAT     *src1,
+                                const LVM_FLOAT     *src2,
+                                      LVM_FLOAT     *dst,
+                                      LVM_INT16     n)
+{
 
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance->Current1 != pInstance->Target1) || (pInstance->Current2 != pInstance->Target2))
+    {
+        MixSoft_1St_D32C31_WRA((Mix_1St_Cll_FLOAT_t*)pInstance, src1, dst, n);
+        MixInSoft_D32C31_SAT((void *)&pInstance->Alpha2, /* Cast to void: \
+                                                              no dereferencing in function*/
+                              src2, dst, n);
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    else
+    {
+        if (pInstance->Current1 == 0)
+            MixSoft_1St_D32C31_WRA((void *) &pInstance->Alpha2, /* Cast to void: no \
+                                                             dereferencing in function*/
+                                    src2, dst, n);
+        else if (pInstance->Current2 == 0)
+            MixSoft_1St_D32C31_WRA((Mix_1St_Cll_FLOAT_t*) pInstance, src1, dst, n);
+        else
+            Core_MixHard_2St_D32C31_SAT(pInstance, src1, src2, dst, n);
+    }
+}
+#else
 void MixSoft_2St_D32C31_SAT(    Mix_2St_Cll_t       *pInstance,
                                 const LVM_INT32     *src1,
                                 const LVM_INT32     *src2,
@@ -61,5 +98,6 @@
             Core_MixHard_2St_D32C31_SAT( pInstance, src1, src2, dst, n);
     }
 }
-
+#endif
 /**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/Mixer_private.h b/media/libeffects/lvm/lib/Common/src/Mixer_private.h
index 607073c..00d55ed 100644
--- a/media/libeffects/lvm/lib/Common/src/Mixer_private.h
+++ b/media/libeffects/lvm/lib/Common/src/Mixer_private.h
@@ -26,6 +26,10 @@
 
 #define POINT_ZERO_ONE_DB 2473805 /* 0.01 dB on a full scale signal = (10^(0.01/20) -1) * 2^31 */
 
+#ifdef BUILD_FLOAT
+#define POINT_ZERO_ONE_DB_FLOAT 0.001152 /* 0.01 dB on a full scale \
+                                            signal = (10^(0.01/20) -1) * 2^31 */
+#endif
 /**********************************************************************************
    DEFINITIONS
 ***********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
index c09ec0f..796a15c 100644
--- a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
@@ -45,5 +45,26 @@
 
     return;
 }
+#ifdef BUILD_FLOAT
+void MonoTo2I_Float( const LVM_FLOAT  *src,
+                     LVM_FLOAT  *dst,
+                     LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    src += (n - 1);
+    dst += ((n * 2) - 1);
 
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = *src;
+        dst--;
+
+        *dst = *src;
+        dst--;
+        src--;
+    }
+
+    return;
+}
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c
index a5dc50f..c758560 100644
--- a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c
+++ b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c
@@ -47,5 +47,23 @@
 
     return;
 }
+#ifdef BUILD_FLOAT
+void Mult3s_Float( const LVM_FLOAT *src,
+                   const LVM_FLOAT val,
+                   LVM_FLOAT *dst,
+                   LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_FLOAT temp;
 
+    for (ii = n; ii != 0; ii--)
+    {
+        temp = (*src) * val;
+        src++;
+        *dst = temp;
+        dst++;
+    }
+    return;
+}
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
index 73343cd..5156edc 100644
--- a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
+++ b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
@@ -114,4 +114,54 @@
     }
 
 }
+#ifdef BUILD_FLOAT
+void NonLinComp_Float(LVM_FLOAT        Gain,
+                      LVM_FLOAT        *pDataIn,
+                      LVM_FLOAT        *pDataOut,
+                      LVM_INT32        BlockLength)
+{
 
+    LVM_FLOAT            Sample;                    /* Input samples */
+    LVM_INT32            SampleNo;                /* Sample index */
+    LVM_FLOAT            Temp;
+
+
+    /*
+     * Process a block of samples
+     */
+    for(SampleNo = 0; SampleNo < BlockLength; SampleNo++)
+    {
+        /*
+         * Read the input
+         */
+        Sample = *pDataIn;
+        pDataIn++;
+
+
+        /*
+         * Apply the compander, this compresses the signal at the expense of
+         * harmonic distortion. The amount of compression is control by the
+         * gain factor
+         */
+        if (Sample != -1.0f)
+        {
+            Temp = ((Sample * Sample));
+            if(Sample > 0)
+            {
+                Sample = (Sample + ((Gain * (Sample - Temp)) ));
+            }
+            else
+            {
+                Sample = (Sample + ((Gain * (Sample + Temp)) ));
+            }
+        }
+
+
+        /*
+         * Save the output
+         */
+        *pDataOut = Sample;
+        pDataOut++;
+    }
+}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
index c8c1527..9c17a05 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
@@ -38,6 +38,88 @@
  pBiquadState->pDelays[6] is y(n-2)L in Q0 format
  pBiquadState->pDelays[7] is y(n-2)R in Q0 format
 ***************************************************************************/
+#ifdef BUILD_FLOAT
+void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                     LVM_FLOAT               *pDataIn,
+                                     LVM_FLOAT               *pDataOut,
+                                     LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT ynL,ynR,ynLO,ynRO,templ;
+        LVM_INT16 ii;
+        PFilter_State_Float pBiquadState = (PFilter_State_Float) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL= (A0  * (x(n)L - x(n-2)L  ) )*/
+            templ = (*pDataIn) - pBiquadState->pDelays[2];
+            ynL = templ * pBiquadState->coefs[0];
+
+            /* ynL+= ((-B2  * y(n-2)L  )) */
+            templ = pBiquadState->pDelays[6] * pBiquadState->coefs[1];
+            ynL += templ;
+
+            /* ynL+= ((-B1 * y(n-1)L  ) ) */
+            templ = pBiquadState->pDelays[4] * pBiquadState->coefs[2];
+            ynL += templ;
+
+            /* ynLO= ((Gain * ynL )) */
+            ynLO = ynL * pBiquadState->coefs[3];
+
+            /* ynLO=( ynLO + x(n)L  )*/
+            ynLO += (*pDataIn);
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR= (A0  * (x(n)R  - x(n-2)R  ) ) */
+            templ = (*(pDataIn + 1)) - pBiquadState->pDelays[3];
+            ynR = templ * pBiquadState->coefs[0];
+
+            /* ynR+= ((-B2  * y(n-2)R  ) )  */
+            templ = pBiquadState->pDelays[7] * pBiquadState->coefs[1];
+            ynR += templ;
+
+            /* ynR+= ((-B1  * y(n-1)R  ) )   */
+            templ = pBiquadState->pDelays[5] * pBiquadState->coefs[2];
+            ynR += templ;
+
+            /* ynRO= ((Gain  * ynR )) */
+            ynRO = ynR * pBiquadState->coefs[3];
+
+            /* ynRO=( ynRO + x(n)R  )*/
+            ynRO += (*(pDataIn+1));
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R */
+            pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L */
+            pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = ynLO; /* Write Left output*/
+            pDataOut++;
+            *pDataOut = ynRO; /* Write Right ouput*/
+            pDataOut++;
+
+        }
+
+    }
+#else
 void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
                                      LVM_INT32               *pDataIn,
                                      LVM_INT32               *pDataOut,
@@ -118,4 +200,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c
index 67a570b..f705cbf 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c
@@ -38,6 +38,7 @@
  pBiquadState->pDelays[6] is y(n-2)L in Q0 format
  pBiquadState->pDelays[7] is y(n-2)R in Q0 format
 ***************************************************************************/
+#ifndef BUILD_FLOAT
 void PK_2I_D32F32C30G11_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
                                      LVM_INT32               *pDataIn,
                                      LVM_INT32               *pDataOut,
@@ -116,4 +117,4 @@
         }
 
     }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
index 1d6142c..65475a3 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
@@ -18,7 +18,7 @@
 #include "BIQUAD.h"
 #include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
 
-
+#ifndef BUILD_FLOAT
 void  PK_2I_D32F32CllGss_TRC_WRA_01_Init(Biquad_Instance_t         *pInstance,
                                          Biquad_2I_Order2_Taps_t   *pTaps,
                                          PK_C32_Coefs_t            *pCoef)
@@ -35,4 +35,4 @@
   pBiquadState->coefs[3]=pCoef->G;
 
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
index b9f64e6..a36330e 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
@@ -17,7 +17,23 @@
 
 #include "BIQUAD.h"
 #include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
+#ifdef BUILD_FLOAT
+void  PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         PK_FLOAT_Coefs_t            *pCoef)
+{
+    PFilter_State_Float pBiquadState = (PFilter_State_Float) pInstance;
+    pBiquadState->pDelays       = (LVM_FLOAT *) pTaps;
 
+    pBiquadState->coefs[0] = pCoef->A0;
+
+    pBiquadState->coefs[1] = pCoef->B2;
+
+    pBiquadState->coefs[2] = pCoef->B1;
+
+    pBiquadState->coefs[3] = pCoef->G;
+}
+#else
 void  PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_Instance_t         *pInstance,
                                          Biquad_2I_Order2_Taps_t   *pTaps,
                                          PK_C16_Coefs_t            *pCoef)
@@ -34,4 +50,4 @@
   pBiquadState->coefs[3]=pCoef->G;
 
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
index e2050e0..1e32062 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
@@ -21,6 +21,16 @@
 
 /* The internal state variables are implemented in a (for the user)  hidden structure */
 /* In this (private) file, the internal structure is declared fro private use.        */
+
+#ifdef BUILD_FLOAT
+typedef struct _Filter_State_Float_
+{
+    LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+    LVM_FLOAT         coefs[5];       /* pointer to the filter coefficients */
+}Filter_State_Float;
+
+typedef Filter_State_Float * PFilter_State_Float ;
+#endif
 typedef struct _Filter_State_
 {
   LVM_INT32 *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c
index 8363270..28fea65 100644
--- a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c
@@ -24,7 +24,7 @@
 /**********************************************************************************
    FUNCTION Shift_Sat_v16xv16
 ***********************************************************************************/
-
+#ifndef BUILD_FLOAT
 void Shift_Sat_v16xv16 (const   LVM_INT16   val,
                         const   LVM_INT16   *src,
                         LVM_INT16   *dst,
@@ -77,5 +77,5 @@
     }
     return;
 }
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c
index fbd132e..fac9de7 100644
--- a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c
@@ -24,7 +24,62 @@
 /**********************************************************************************
    FUNCTION Shift_Sat_v32xv32
 ***********************************************************************************/
+#ifdef BUILD_FLOAT
+void Shift_Sat_Float (const   LVM_INT16   val,
+                      const   LVM_FLOAT   *src,
+                      LVM_FLOAT   *dst,
+                      LVM_INT16   n)
+{
+    LVM_FLOAT   temp;
+    LVM_INT32   ii,ij;
+    LVM_INT16   RShift;
 
+    if(val > 0)
+    {
+        for (ii = n; ii != 0; ii--)
+        {
+            temp = (LVM_FLOAT)*src;
+            src++;
+            for(ij = 0; ij < val; ij++)
+            {
+                temp = temp * 2;
+            }
+
+            if(temp > 1.0)
+                temp = 1.0;
+            if(temp < -1.0)
+                temp = -1.0;
+
+            *dst = (LVM_FLOAT)temp;
+            dst++;
+        }
+    }
+    else if(val < 0)
+    {
+        RShift=(LVM_INT16)(-val);
+
+        for (ii = n; ii != 0; ii--)
+        {
+            temp = (LVM_FLOAT)*src;
+            src++;
+            for(ij = 0; ij < RShift; ij++)
+            {
+                temp = temp / 2;
+            }
+            *dst = (LVM_FLOAT)temp;
+            dst++;
+        }
+    }
+    else
+    {
+        if(src != dst)
+        {
+            Copy_Float(src, dst, n);
+        }
+    }
+    return;
+}
+#else
 void Shift_Sat_v32xv32 (const   LVM_INT16   val,
                         const   LVM_INT32   *src,
                         LVM_INT32   *dst,
@@ -79,5 +134,5 @@
     }
     return;
 }
-
+#endif
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c b/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c
index ac0343f..9a726f2 100644
--- a/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c
+++ b/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c
@@ -29,6 +29,9 @@
 /*######################################################################################*/
 
 #include "ScalarArithmetic.h"
+#ifdef BUILD_FLOAT
+#include <math.h>
+#endif
 
 
 /****************************************************************************************
@@ -64,6 +67,18 @@
 #define SECOND_COEF      38836
 #define MAX_VALUE        1536                   /* 96 * 16 */
 
+#ifdef BUILD_FLOAT
+LVM_FLOAT   dB_to_LinFloat(LVM_INT16    db_fix)
+{
+    LVM_FLOAT    dB_Float;
+    LVM_FLOAT    LinFloat;
+
+    dB_Float = (LVM_FLOAT)((LVM_FLOAT)db_fix / 16.0f);
+    LinFloat = pow(10, dB_Float / 20.0);
+
+    return LinFloat;
+}
+#else
 LVM_INT32   dB_to_Lin32(LVM_INT16    db_fix)
 {
     LVM_INT32 Lin_val_32;
@@ -106,4 +121,4 @@
 
     return Lin_val_32;  /* format 1.16.15 */
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
index db6aabe..8e0b738 100644
--- a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
+++ b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
@@ -200,6 +200,10 @@
 #define LVEQNB_CAP_FS_32000                64
 #define LVEQNB_CAP_FS_44100                128
 #define LVEQNB_CAP_FS_48000                256
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+#define LVEQNB_CAP_FS_96000                512
+#define LVEQNB_CAP_FS_192000               1024
+#endif
 
 typedef enum
 {
@@ -212,6 +216,10 @@
     LVEQNB_FS_32000 = 6,
     LVEQNB_FS_44100 = 7,
     LVEQNB_FS_48000 = 8,
+#ifdef HIGHER_FS
+    LVEQNB_FS_96000 = 9,
+    LVEQNB_FS_192000 = 10,
+#endif
     LVEQNB_FS_MAX   = LVM_MAXINT_32
 } LVEQNB_Fs_en;
 
@@ -268,6 +276,7 @@
 {
     /* General parameters */
     LVM_UINT16                  SampleRate;
+
     LVM_UINT16                  SourceFormat;
     LVM_UINT16                  MaxBlockSize;
     LVM_UINT16                  MaxBands;
@@ -460,11 +469,17 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
-
+#ifdef BUILD_FLOAT
+LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
+                                      const LVM_FLOAT       *pInData,
+                                      LVM_FLOAT             *pOutData,
+                                      LVM_UINT16            NumSamples);
+#else
 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
                                       const LVM_INT16       *pInData,
                                       LVM_INT16             *pOutData,
                                       LVM_UINT16            NumSamples);
+#endif
 
 
 
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
index fddedb9..ff52b7f 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
@@ -22,7 +22,9 @@
 /****************************************************************************************/
 
 #include "LVEQNB_Private.h"
-
+#ifdef BUILD_FLOAT
+#include <math.h>
+#endif
 
 /****************************************************************************************/
 /*                                                                                      */
@@ -77,6 +79,7 @@
 /****************************************************************************************/
 
 
+#ifndef BUILD_FLOAT
 LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16        Fs,
                                               LVEQNB_BandDef_t  *pFilterDefinition,
                                               PK_C32_Coefs_t    *pCoefficients)
@@ -168,7 +171,7 @@
     return(LVEQNB_SUCCESS);
 
 }
-
+#endif
 
 /****************************************************************************************/
 /*                                                                                      */
@@ -205,7 +208,67 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifdef BUILD_FLOAT
+LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
+                                              LVEQNB_BandDef_t  *pFilterDefinition,
+                                              PK_FLOAT_Coefs_t  *pCoefficients)
+{
 
+    extern LVM_FLOAT    LVEQNB_GainTable[];
+    extern LVM_FLOAT    LVEQNB_TwoPiOnFsTable[];
+    extern LVM_FLOAT    LVEQNB_DTable[];
+
+
+    /*
+     * Get the filter definition
+     */
+    LVM_INT16           Gain        = pFilterDefinition->Gain;
+    LVM_UINT16          Frequency   = pFilterDefinition->Frequency;
+    /* As mentioned in effectbundle.h */
+    LVM_FLOAT           QFactor     = (LVM_FLOAT)pFilterDefinition->QFactor / 100.0f;
+
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_FLOAT           T0;
+    LVM_FLOAT           D;
+    LVM_FLOAT           A0;
+    LVM_FLOAT           B1;
+    LVM_FLOAT           B2;
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = Frequency * LVEQNB_TwoPiOnFsTable[Fs];        /* T0 = 2 * Pi * Fc / Fs */
+    if (Gain >= 0)
+    {
+        D = LVEQNB_DTable[15];                         /* D = 1            if GaindB >= 0 */
+    }
+    else
+    {
+        D = LVEQNB_DTable[Gain + 15];                    /* D = 1 / (1 + G)  if GaindB <  0 */
+    }
+
+    /*
+     * Calculate the B2,B1,A0 coefficients
+     */
+    B2 = -0.5 * (2 * QFactor - D * T0) / (2 * QFactor + D * T0);
+    B1 = (0.5 - B2) * cos(T0);
+    A0 = (0.5 + B2) / 2.0;
+
+    /*
+     * Write coeff into the data structure
+     */
+    /* all the coefficients are multiplied with 2 to make them align with fixed point values*/
+    pCoefficients->A0 = 2 * A0;
+    pCoefficients->B1 = 2 * B1;
+    pCoefficients->B2 = 2 * B2;
+    pCoefficients->G  = LVEQNB_GainTable[Gain + 15];
+
+    return(LVEQNB_SUCCESS);
+}
+#else
 LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
                                               LVEQNB_BandDef_t  *pFilterDefinition,
                                               PK_C16_Coefs_t    *pCoefficients)
@@ -296,3 +359,4 @@
     return(LVEQNB_SUCCESS);
 
 }
+#endif
\ No newline at end of file
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
index 95212f2..f0deb6c 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
@@ -25,7 +25,39 @@
 /* Gain table for (10^(Gain/20) - 1)                                                */
 /*                                                                                  */
 /************************************************************************************/
-
+#ifdef BUILD_FLOAT
+#define LVEQNB_Gain_Neg15_dB                             -0.822172f
+#define LVEQNB_Gain_Neg14_dB                             -0.800474f
+#define LVEQNB_Gain_Neg13_dB                             -0.776128f
+#define LVEQNB_Gain_Neg12_dB                             -0.748811f
+#define LVEQNB_Gain_Neg11_dB                             -0.718162f
+#define LVEQNB_Gain_Neg10_dB                             -0.683772f
+#define LVEQNB_Gain_Neg9_dB                              -0.645187f
+#define LVEQNB_Gain_Neg8_dB                              -0.601893f
+#define LVEQNB_Gain_Neg7_dB                              -0.553316f
+#define LVEQNB_Gain_Neg6_dB                              -0.498813f
+#define LVEQNB_Gain_Neg5_dB                              -0.437659f
+#define LVEQNB_Gain_Neg4_dB                              -0.369043f
+#define LVEQNB_Gain_Neg3_dB                              -0.292054f
+#define LVEQNB_Gain_Neg2_dB                              -0.205672f
+#define LVEQNB_Gain_Neg1_dB                              -0.108749f
+#define LVEQNB_Gain_0_dB                                  0.000000f
+#define LVEQNB_Gain_1_dB                                  0.122018f
+#define LVEQNB_Gain_2_dB                                  0.258925f
+#define LVEQNB_Gain_3_dB                                  0.412538f
+#define LVEQNB_Gain_4_dB                                  0.584893f
+#define LVEQNB_Gain_5_dB                                  0.778279f
+#define LVEQNB_Gain_6_dB                                  0.995262f
+#define LVEQNB_Gain_7_dB                                  1.238721f
+#define LVEQNB_Gain_8_dB                                  1.511886f
+#define LVEQNB_Gain_9_dB                                  1.818383f
+#define LVEQNB_Gain_10_dB                                 2.162278f
+#define LVEQNB_Gain_11_dB                                 2.548134f
+#define LVEQNB_Gain_12_dB                                 2.981072f
+#define LVEQNB_Gain_13_dB                                 3.466836f
+#define LVEQNB_Gain_14_dB                                 4.011872f
+#define LVEQNB_Gain_15_dB                                 4.623413f
+#else
 #define LVEQNB_GAINSHIFT                                   11         /* As a power of 2 */
 #define LVEQNB_Gain_Neg15_dB                           (-1684)        /* Floating point value -0.822172 */
 #define LVEQNB_Gain_Neg14_dB                           (-1639)        /* Floating point value -0.800474 */
@@ -58,14 +90,30 @@
 #define LVEQNB_Gain_13_dB                                7100         /* Floating point value 3.466836 */
 #define LVEQNB_Gain_14_dB                                8216         /* Floating point value 4.011872 */
 #define LVEQNB_Gain_15_dB                                9469         /* Floating point value 4.623413 */
-
+#endif
 
 /************************************************************************************/
 /*                                                                                  */
 /* Frequency table for 2*Pi/Fs                                                      */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+#define LVEQNB_2PiOn_8000                                0.000785f
+#define LVEQNB_2PiOn_11025                               0.000570f
+#define LVEQNB_2PiOn_12000                               0.000524f
+#define LVEQNB_2PiOn_16000                               0.000393f
+#define LVEQNB_2PiOn_22050                               0.000285f
+#define LVEQNB_2PiOn_24000                               0.000262f
+#define LVEQNB_2PiOn_32000                               0.000196f
+#define LVEQNB_2PiOn_44100                               0.000142f
+#define LVEQNB_2PiOn_48000                               0.000131f
 
+#ifdef HIGHER_FS
+#define LVEQNB_2PiOn_96000                               0.000065f
+#define LVEQNB_2PiOn_192000                              0.000033f
+#endif
+
+#else
 #define LVEQNB_FREQSHIFT                                   25         /* As a power of 2 */
 #define LVEQNB_2PiOn_8000                               26354         /* Floating point value 0.000785 */
 #define LVEQNB_2PiOn_11025                              19123         /* Floating point value 0.000570 */
@@ -76,14 +124,31 @@
 #define LVEQNB_2PiOn_32000                               6588         /* Floating point value 0.000196 */
 #define LVEQNB_2PiOn_44100                               4781         /* Floating point value 0.000142 */
 #define LVEQNB_2PiOn_48000                               4392         /* Floating point value 0.000131 */
-
+#endif
 
 /************************************************************************************/
 /*                                                                                  */
 /* 50D table for 50 / ( 1 + Gain )                                                  */
 /*                                                                                  */
 /************************************************************************************/
-
+#ifdef BUILD_FLOAT
+#define LVEQNB_100D_Neg15_dB                             5.623413f
+#define LVEQNB_100D_Neg14_dB                             5.011872f
+#define LVEQNB_100D_Neg13_dB                             4.466836f
+#define LVEQNB_100D_Neg12_dB                             3.981072f
+#define LVEQNB_100D_Neg11_dB                             3.548134f
+#define LVEQNB_100D_Neg10_dB                             3.162278f
+#define LVEQNB_100D_Neg9_dB                              2.818383f
+#define LVEQNB_100D_Neg8_dB                              2.511886f
+#define LVEQNB_100D_Neg7_dB                              2.238721f
+#define LVEQNB_100D_Neg6_dB                              1.995262f
+#define LVEQNB_100D_Neg5_dB                              1.778279f
+#define LVEQNB_100D_Neg4_dB                              1.584893f
+#define LVEQNB_100D_Neg3_dB                              1.412538f
+#define LVEQNB_100D_Neg2_dB                              1.258925f
+#define LVEQNB_100D_Neg1_dB                              1.122018f
+#define LVEQNB_100D_0_dB                                 1.000000f
+#else
 #define LVEQNB_100DSHIFT                                    5         /* As a power of 2 */
 #define LVEQNB_100D_Neg15_dB                            17995         /* Floating point value 5.623413 */
 #define LVEQNB_100D_Neg14_dB                            16038         /* Floating point value 5.011872 */
@@ -101,6 +166,6 @@
 #define LVEQNB_100D_Neg2_dB                              4029         /* Floating point value 1.258925 */
 #define LVEQNB_100D_Neg1_dB                              3590         /* Floating point value 1.122018 */
 #define LVEQNB_100D_0_dB                                 3200         /* Floating point value 1.000000 */
-
+#endif
 
 #endif
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
index 10e7d74..c290aec 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
@@ -140,8 +140,12 @@
 void    LVEQNB_SetFilters(LVEQNB_Instance_t     *pInstance,
                           LVEQNB_Params_t       *pParams)
 {
-
+#ifdef HIGHER_FS
+    extern const LVM_UINT32   LVEQNB_SampleRateTab[];           /* Sample rate table */
+#else
     extern const LVM_UINT16   LVEQNB_SampleRateTab[];           /* Sample rate table */
+#endif
+
     LVM_UINT16          i;                                      /* Filter band index */
     LVM_UINT32          fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate];  /* Sample rate */
     LVM_UINT32          fc;                                     /* Filter centre frequency */
@@ -158,11 +162,15 @@
         fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency;     /* Get the band centre frequency */
         QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor;   /* Get the band Q factor */
 
-
+#ifdef BUILD_FLOAT
+        pInstance->pBiquadType[i] = LVEQNB_SinglePrecision_Float; /* Default to single precision */
+#else
         /*
          * For each filter set the type of biquad required
          */
         pInstance->pBiquadType[i] = LVEQNB_SinglePrecision;         /* Default to single precision */
+#endif
+#ifndef BUILD_FLOAT
         if ((fc << 15) <= (LOW_FREQ * fs))
         {
             /*
@@ -177,7 +185,7 @@
              */
             pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
         }
-
+#endif
 
         /*
          * Check for out of range frequencies
@@ -230,6 +238,25 @@
         BiquadType = pInstance->pBiquadType[i];
         switch  (BiquadType)
         {
+#ifdef BUILD_FLOAT
+            case    LVEQNB_SinglePrecision_Float:
+            {
+                PK_FLOAT_Coefs_t      Coefficients;
+                /*
+                 * Calculate the single precision coefficients
+                 */
+                LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
+                                       &pInstance->pBandDefinitions[i],
+                                       &Coefficients);
+                /*
+                 * Set the coefficients
+                 */
+                PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
+                                                   &pInstance->pEQNB_Taps_Float[i],
+                                                   &Coefficients);
+                break;
+            }
+#else
             case    LVEQNB_DoublePrecision:
             {
                 PK_C32_Coefs_t      Coefficients;
@@ -269,6 +296,7 @@
                                                    &Coefficients);
                 break;
             }
+#endif
             default:
                 break;
         }
@@ -288,7 +316,7 @@
 /*  pInstance           Pointer to the instance                                     */
 /*                                                                                  */
 /************************************************************************************/
-
+#ifndef BUILD_FLOAT
 void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t     *pInstance)
 {
     LVM_INT16       *pTapAddress;
@@ -305,8 +333,24 @@
                      NumTaps);                          /* Number of words */
     }
 }
+#else
+void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t     *pInstance)
+{
+    LVM_FLOAT       *pTapAddress;
+    LVM_INT16       NumTaps;
 
+    pTapAddress = (LVM_FLOAT *)pInstance->pEQNB_Taps_Float;
+    NumTaps     = (LVM_INT16)((pInstance->Capabilities.MaxBands * \
+                                    sizeof(Biquad_2I_Order2_FLOAT_Taps_t)) / sizeof(LVM_FLOAT));
 
+    if (NumTaps != 0)
+    {
+        LoadConst_Float(0,                                 /* Clear the history, value 0 */
+                        pTapAddress,                       /* Destination */
+                        NumTaps);                          /* Number of words */
+    }
+}
+#endif
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVEQNB_Control                                              */
@@ -422,9 +466,13 @@
         {
             if(pParams->OperatingMode == LVEQNB_ON)
             {
+#ifdef BUILD_FLOAT
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 1.0f);
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 0.0f);
+#else
                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16);
                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0);
-
+#endif
                 pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
                 pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
             }
@@ -432,15 +480,18 @@
             {
                 /* Stay on the ON operating mode until the transition is done */
                 pInstance->Params.OperatingMode = LVEQNB_ON;
-
+#ifdef BUILD_FLOAT
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 0.0f);
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 1.0f);
+#else
                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0);
                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16);
+#endif
                 pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
                 pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
             }
             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
-
             pInstance->bInOperatingModeTransition = LVM_TRUE;
         }
 
@@ -470,8 +521,13 @@
      /*
       * Send an ALGOFF event if the ON->OFF switch transition is finished
       */
+#ifdef BUILD_FLOAT
+    if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0) &&
+       (CallbackParam == 0)){
+#else
     if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) &&
        (CallbackParam == 0)){
+#endif
         pInstance->Params.OperatingMode = LVEQNB_BYPASS;
         if (CallBack != LVM_NULL){
             CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF);
@@ -485,9 +541,3 @@
 
     return 1;
 }
-
-
-
-
-
-
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
index e01c1c5..de1bbb7 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
@@ -97,6 +97,21 @@
          */
         InstAlloc_Init(&AllocMem,
                        LVM_NULL);
+#ifdef BUILD_FLOAT
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
+        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
+                            sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
+        /* Equaliser Biquad Taps */
+        InstAlloc_AddMember(&AllocMem,
+                            (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t)));
+        /* Filter definitions */
+        InstAlloc_AddMember(&AllocMem,
+                            (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)));
+        /* Biquad types */
+        InstAlloc_AddMember(&AllocMem,
+                            (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)));
+#else
         InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
                             sizeof(Biquad_2I_Order2_Taps_t));
         InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
@@ -107,6 +122,7 @@
                             (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)));        /* Filter definitions */
         InstAlloc_AddMember(&AllocMem,
                             (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)));    /* Biquad types */
+#endif
         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size         = InstAlloc_GetTotal(&AllocMem);
         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Alignment    = LVEQNB_DATA_ALIGN;
         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Type         = LVEQNB_PERSISTENT_DATA;
@@ -117,12 +133,22 @@
          */
         InstAlloc_Init(&AllocMem,
                        LVM_NULL);
+#ifdef BUILD_FLOAT
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            sizeof(Biquad_FLOAT_Instance_t));
+        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
+                            sizeof(Biquad_FLOAT_Instance_t));
+        /* Equaliser Biquad Instance */
+        InstAlloc_AddMember(&AllocMem,
+                            pCapabilities->MaxBands * sizeof(Biquad_FLOAT_Instance_t));
+#else
         InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
                             sizeof(Biquad_Instance_t));
         InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
                             sizeof(Biquad_Instance_t));
         InstAlloc_AddMember(&AllocMem,
                             pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
+#endif
         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size         = InstAlloc_GetTotal(&AllocMem);
         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Alignment    = LVEQNB_COEF_ALIGN;
         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Type         = LVEQNB_PERSISTENT_COEF;
@@ -133,8 +159,14 @@
          */
         InstAlloc_Init(&AllocMem,
                        LVM_NULL);
+#ifdef BUILD_FLOAT
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            LVEQNB_SCRATCHBUFFERS * sizeof(LVM_FLOAT) * \
+                                             pCapabilities->MaxBlockSize);
+#else
         InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
                             LVEQNB_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
+#endif
         pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Size              = InstAlloc_GetTotal(&AllocMem);
         pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Alignment         = LVEQNB_SCRATCH_ALIGN;
         pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Type              = LVEQNB_SCRATCH;
@@ -248,8 +280,15 @@
     InstAlloc_Init(&AllocMem,
                    pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress);
 
+#ifdef BUILD_FLOAT
+    /* Equaliser Biquad Instance */
+    pInstance->pEQNB_FilterState_Float = InstAlloc_AddMember(&AllocMem,
+                                                             pCapabilities->MaxBands * \
+                                                             sizeof(Biquad_FLOAT_Instance_t));
+#else
     pInstance->pEQNB_FilterState = InstAlloc_AddMember(&AllocMem,
                                                        pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
+#endif
 
 
 
@@ -259,9 +298,15 @@
     InstAlloc_Init(&AllocMem,
                    pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress);
 
+#ifdef BUILD_FLOAT
+    MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
+    pInstance->pEQNB_Taps_Float = (Biquad_2I_Order2_FLOAT_Taps_t *)InstAlloc_AddMember(&AllocMem,
+                                                                                       MemSize);
+#else
     MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t));
     pInstance->pEQNB_Taps = (Biquad_2I_Order2_Taps_t *)InstAlloc_AddMember(&AllocMem,
                                                                            MemSize);
+#endif
     MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t));
     pInstance->pBandDefinitions  = (LVEQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem,
                                                                            MemSize);
@@ -279,8 +324,13 @@
     InstAlloc_Init(&AllocMem,
                    pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress);
 
+#ifdef BUILD_FLOAT
+    pInstance->pFastTemporary = (LVM_FLOAT *)InstAlloc_AddMember(&AllocMem,
+                                                                 sizeof(LVM_FLOAT));
+#else
     pInstance->pFastTemporary = (LVM_INT16 *)InstAlloc_AddMember(&AllocMem,
                                                                  sizeof(LVM_INT16));
+#endif
 
     /*
      * Update the instance parameters
@@ -308,15 +358,22 @@
     pInstance->BypassMixer.MixerStream[0].CallbackParam      = 0;
     pInstance->BypassMixer.MixerStream[0].pCallbackHandle    = (void*)pInstance;
     pInstance->BypassMixer.MixerStream[0].pCallBack          = LVEQNB_BypassMixerCallBack;
+
     LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[0],0,0);
     LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],0,LVM_FS_8000,2);
 
+
     pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
     pInstance->BypassMixer.MixerStream[1].CallbackParam      = 0;
     pInstance->BypassMixer.MixerStream[1].pCallbackHandle    = LVM_NULL;
     pInstance->BypassMixer.MixerStream[1].pCallBack          = LVM_NULL;
+#ifdef BUILD_FLOAT
+    LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1], 0, 1.0f);
+    LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1], 0, LVM_FS_8000, 2);
+#else
     LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1],0,LVM_MAXINT_16);
     LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],0,LVM_FS_8000,2);
+#endif
 
     pInstance->bInOperatingModeTransition      = LVM_FALSE;
 
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
index 9df980c..56b02e0 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -60,6 +60,9 @@
 /* Filter biquad types */
 typedef enum
 {
+#ifdef BUILD_FLOAT
+    LVEQNB_SinglePrecision_Float = -1,
+#endif
     LVEQNB_SinglePrecision = 0,
     LVEQNB_DoublePrecision = 1,
     LVEQNB_OutOfRange      = 2,
@@ -84,11 +87,20 @@
     LVEQNB_Capabilities_t           Capabilities;       /* Instance capabilities */
 
     /* Aligned memory pointers */
+#ifdef BUILD_FLOAT
+    LVM_FLOAT                      *pFastTemporary;        /* Fast temporary data base address */
+#else
     LVM_INT16                      *pFastTemporary;        /* Fast temporary data base address */
+#endif
 
+#ifdef BUILD_FLOAT
+    Biquad_2I_Order2_FLOAT_Taps_t   *pEQNB_Taps_Float;        /* Equaliser Taps */
+    Biquad_FLOAT_Instance_t         *pEQNB_FilterState_Float; /* State for each filter band */
+#else
     /* Process variables */
     Biquad_2I_Order2_Taps_t         *pEQNB_Taps;        /* Equaliser Taps */
     Biquad_Instance_t               *pEQNB_FilterState; /* State for each filter band */
+#endif
 
     /* Filter definitions and call back */
     LVM_UINT16                      NBands;             /* Number of bands */
@@ -96,7 +108,12 @@
     LVEQNB_BiquadType_en            *pBiquadType;       /* Filter biquad types */
 
     /* Bypass variable */
+#ifdef BUILD_FLOAT
+    LVMixer3_2St_FLOAT_st     BypassMixer;
+#else
     LVMixer3_2St_st           BypassMixer;              /* Bypass mixer used in transitions */
+#endif
+
     LVM_INT16               bInOperatingModeTransition; /* Operating mode transition flag */
 
 } LVEQNB_Instance_t;
@@ -114,7 +131,11 @@
 void    LVEQNB_SetCoefficients(LVEQNB_Instance_t    *pInstance);
 
 void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance);
-
+#ifdef BUILD_FLOAT
+LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
+                                              LVEQNB_BandDef_t  *pFilterDefinition,
+                                              PK_FLOAT_Coefs_t    *pCoefficients);
+#else
 LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
                                               LVEQNB_BandDef_t  *pFilterDefinition,
                                               PK_C16_Coefs_t    *pCoefficients);
@@ -122,6 +143,7 @@
 LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16        Fs,
                                               LVEQNB_BandDef_t  *pFilterDefinition,
                                               PK_C32_Coefs_t    *pCoefficients);
+#endif
 
 LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance, void *pGeneralPurpose, LVM_INT16 CallbackParam);
 
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
index 58f58ed..6328181 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
@@ -57,7 +57,121 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
+                                      const LVM_FLOAT       *pInData,
+                                      LVM_FLOAT             *pOutData,
+                                      LVM_UINT16            NumSamples)
+{
 
+    LVM_UINT16          i;
+    Biquad_FLOAT_Instance_t   *pBiquad;
+    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t  *)hInstance;
+    LVM_FLOAT           *pScratch;
+
+
+     /* Check for NULL pointers */
+    if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    /* Check if the input and output data buffers are 32-bit aligned */
+    if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
+    {
+        return LVEQNB_ALIGNMENTERROR;
+    }
+
+    pScratch  = (LVM_FLOAT *)pInstance->pFastTemporary;
+
+    /*
+    * Check the number of samples is not too large
+    */
+    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+    {
+        return(LVEQNB_TOOMANYSAMPLES);
+    }
+
+    if (pInstance->Params.OperatingMode == LVEQNB_ON)
+    {
+        /*
+         * Copy input data in to scratch buffer
+         */
+
+        Copy_Float((LVM_FLOAT *)pInData,      /* Source */
+                   pScratch,                  /* Destination */
+                   (LVM_INT16)(2 * NumSamples)); /* Left and Right */
+        /*
+         * For each section execte the filter unless the gain is 0dB
+         */
+        if (pInstance->NBands != 0)
+        {
+            for (i = 0; i < pInstance->NBands; i++)
+            {
+                /*
+                 * Check if band is non-zero dB gain
+                 */
+                if (pInstance->pBandDefinitions[i].Gain != 0)
+                {
+                    /*
+                     * Get the address of the biquad instance
+                     */
+                    pBiquad = &pInstance->pEQNB_FilterState_Float[i];
+
+
+                    /*
+                     * Select single or double precision as required
+                     */
+                    switch (pInstance->pBiquadType[i])
+                    {
+                        case LVEQNB_SinglePrecision_Float:
+                        {
+                            PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
+                                                          (LVM_FLOAT *)pScratch,
+                                                          (LVM_FLOAT *)pScratch,
+                                                          (LVM_INT16)NumSamples);
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                }
+            }
+        }
+
+
+        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
+            LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
+                                       (LVM_FLOAT *)pScratch,
+                                       (LVM_FLOAT *)pInData,
+                                       (LVM_FLOAT *)pScratch,
+                                       (LVM_INT16)(2 * NumSamples));
+            Copy_Float((LVM_FLOAT*)pScratch,                           /* Source */
+                       pOutData,                                       /* Destination */
+                       (LVM_INT16)(2 * NumSamples));                     /* Left and Right samples */
+        }
+        else{
+            Copy_Float(pScratch,              /* Source */
+                       pOutData,              /* Destination */
+                       (LVM_INT16 )(2 * NumSamples)); /* Left and Right */
+        }
+    }
+    else
+    {
+        /*
+         * Mode is OFF so copy the data if necessary
+         */
+        if (pInData != pOutData)
+        {
+            Copy_Float(pInData,                                    /* Source */
+                       pOutData,                                   /* Destination */
+                       (LVM_INT16)(2 * NumSamples));                 /* Left and Right samples */
+        }
+    }
+    return(LVEQNB_SUCCESS);
+
+}
+#else
 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
                                       const LVM_INT16       *pInData,
                                       LVM_INT16             *pOutData,
@@ -198,3 +312,4 @@
     return(LVEQNB_SUCCESS);
 
 }
+#endif
\ No newline at end of file
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
index 8e2e0e8..563181c 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
@@ -36,6 +36,20 @@
  * Sample rate table for converting between the enumerated type and the actual
  * frequency
  */
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+const LVM_UINT32    LVEQNB_SampleRateTab[] = {8000,                    /* 8kS/s  */
+                                              11025,
+                                              12000,
+                                              16000,
+                                              22050,
+                                              24000,
+                                              32000,
+                                              44100,
+                                              48000,
+                                              96000,
+                                              192000
+};
+#else
 const LVM_UINT16    LVEQNB_SampleRateTab[] = {8000,                    /* 8kS/s  */
                                               11025,
                                               12000,
@@ -44,8 +58,9 @@
                                               24000,
                                               32000,
                                               44100,
-                                              48000};                  /* 48kS/s */
-
+                                              48000
+};
+#endif
 
 /************************************************************************************/
 /*                                                                                  */
@@ -56,6 +71,22 @@
 /*
  * Table for 2 * Pi / Fs
  */
+#ifdef BUILD_FLOAT
+const LVM_FLOAT     LVEQNB_TwoPiOnFsTable[] = {LVEQNB_2PiOn_8000,      /* 8kS/s */
+                                               LVEQNB_2PiOn_11025,
+                                               LVEQNB_2PiOn_12000,
+                                               LVEQNB_2PiOn_16000,
+                                               LVEQNB_2PiOn_22050,
+                                               LVEQNB_2PiOn_24000,
+                                               LVEQNB_2PiOn_32000,
+                                               LVEQNB_2PiOn_44100,
+                                               LVEQNB_2PiOn_48000
+#ifdef HIGHER_FS
+                                              ,LVEQNB_2PiOn_96000
+                                              ,LVEQNB_2PiOn_192000
+#endif
+                                               };
+#else
 const LVM_INT16     LVEQNB_TwoPiOnFsTable[] = {LVEQNB_2PiOn_8000,      /* 8kS/s */
                                                LVEQNB_2PiOn_11025,
                                                LVEQNB_2PiOn_12000,
@@ -65,10 +96,44 @@
                                                LVEQNB_2PiOn_32000,
                                                LVEQNB_2PiOn_44100,
                                                LVEQNB_2PiOn_48000};    /* 48kS/s */
+#endif
 
 /*
  * Gain table
  */
+#ifdef BUILD_FLOAT
+const LVM_FLOAT     LVEQNB_GainTable[] = {LVEQNB_Gain_Neg15_dB,        /* -15dB gain */
+                                          LVEQNB_Gain_Neg14_dB,
+                                          LVEQNB_Gain_Neg13_dB,
+                                          LVEQNB_Gain_Neg12_dB,
+                                          LVEQNB_Gain_Neg11_dB,
+                                          LVEQNB_Gain_Neg10_dB,
+                                          LVEQNB_Gain_Neg9_dB,
+                                          LVEQNB_Gain_Neg8_dB,
+                                          LVEQNB_Gain_Neg7_dB,
+                                          LVEQNB_Gain_Neg6_dB,
+                                          LVEQNB_Gain_Neg5_dB,
+                                          LVEQNB_Gain_Neg4_dB,
+                                          LVEQNB_Gain_Neg3_dB,
+                                          LVEQNB_Gain_Neg2_dB,
+                                          LVEQNB_Gain_Neg1_dB,
+                                          LVEQNB_Gain_0_dB,            /* 0dB gain */
+                                          LVEQNB_Gain_1_dB,
+                                          LVEQNB_Gain_2_dB,
+                                          LVEQNB_Gain_3_dB,
+                                          LVEQNB_Gain_4_dB,
+                                          LVEQNB_Gain_5_dB,
+                                          LVEQNB_Gain_6_dB,
+                                          LVEQNB_Gain_7_dB,
+                                          LVEQNB_Gain_8_dB,
+                                          LVEQNB_Gain_9_dB,
+                                          LVEQNB_Gain_10_dB,
+                                          LVEQNB_Gain_11_dB,
+                                          LVEQNB_Gain_12_dB,
+                                          LVEQNB_Gain_13_dB,
+                                          LVEQNB_Gain_14_dB,
+                                          LVEQNB_Gain_15_dB};          /* +15dB gain */
+#else
 const LVM_INT16     LVEQNB_GainTable[] = {LVEQNB_Gain_Neg15_dB,        /* -15dB gain */
                                           LVEQNB_Gain_Neg14_dB,
                                           LVEQNB_Gain_Neg13_dB,
@@ -101,10 +166,28 @@
                                           LVEQNB_Gain_14_dB,
                                           LVEQNB_Gain_15_dB};          /* +15dB gain */
 
-
+#endif
 /*
  * D table for 100 / (Gain + 1)
  */
+#ifdef BUILD_FLOAT
+const LVM_FLOAT    LVEQNB_DTable[] = {LVEQNB_100D_Neg15_dB,            /* -15dB gain */
+                                      LVEQNB_100D_Neg14_dB,
+                                      LVEQNB_100D_Neg13_dB,
+                                      LVEQNB_100D_Neg12_dB,
+                                      LVEQNB_100D_Neg11_dB,
+                                      LVEQNB_100D_Neg10_dB,
+                                      LVEQNB_100D_Neg9_dB,
+                                      LVEQNB_100D_Neg8_dB,
+                                      LVEQNB_100D_Neg7_dB,
+                                      LVEQNB_100D_Neg6_dB,
+                                      LVEQNB_100D_Neg5_dB,
+                                      LVEQNB_100D_Neg4_dB,
+                                      LVEQNB_100D_Neg3_dB,
+                                      LVEQNB_100D_Neg2_dB,
+                                      LVEQNB_100D_Neg1_dB,
+                                      LVEQNB_100D_0_dB};               /* 0dB gain */
+#else
 const LVM_INT16    LVEQNB_DTable[] = {LVEQNB_100D_Neg15_dB,            /* -15dB gain */
                                       LVEQNB_100D_Neg14_dB,
                                       LVEQNB_100D_Neg13_dB,
@@ -122,7 +205,7 @@
                                       LVEQNB_100D_Neg1_dB,
                                       LVEQNB_100D_0_dB};               /* 0dB gain */
 
-
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /*    Filter polynomial coefficients                                                */
diff --git a/media/libeffects/lvm/lib/Reverb/lib/LVREV.h b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
index 28e3369..9c2e297 100644
--- a/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
+++ b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
@@ -107,8 +107,14 @@
 
     /* Parameters for REV */
     LVM_UINT16                  Level;                  /* Level, 0 to 100 representing percentage of reverb */
+#ifndef HIGHER_FS
     LVM_UINT16                  LPF;                    /* Low pass filter, in Hz */
     LVM_UINT16                  HPF;                    /* High pass filter, in Hz */
+#else
+    LVM_UINT32                  LPF;                    /* Low pass filter, in Hz */
+    LVM_UINT32                  HPF;                    /* High pass filter, in Hz */
+#endif
+
     LVM_UINT16                  T60;                    /* Decay time constant, in ms */
     LVM_UINT16                  Density;                /* Echo density, 0 to 100 for minimum to maximum density */
     LVM_UINT16                  Damping;                /* Damping */
@@ -297,11 +303,17 @@
 /*  1. The input and output buffers must be 32-bit aligned                              */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
+                                    const LVM_FLOAT     *pInData,
+                                    LVM_FLOAT           *pOutData,
+                                    const LVM_UINT16          NumSamples);
+#else
 LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
                                     const LVM_INT32     *pInData,
                                     LVM_INT32           *pOutData,
                                     const LVM_UINT16          NumSamples);
-
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
index ac2ef9d..e710844 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
@@ -41,6 +41,7 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifndef BUILD_FLOAT
 LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st     *pPrivate)
 {
 
@@ -593,8 +594,589 @@
 
     return LVREV_SUCCESS;
 }
+#else /* BUILD_FLOAT*/
+LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st     *pPrivate)
+{
+
+    LVM_Mode_en  OperatingMode;
+    LVM_INT32    NumberOfDelayLines;
 
 
+    /* Check for NULL pointer */
+    if(pPrivate == LVM_NULL)
+    {
+        return LVREV_NULLADDRESS;
+    }
+
+    OperatingMode = pPrivate->NewParams.OperatingMode;
+
+    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+    {
+        NumberOfDelayLines = 4;
+    }
+    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+    {
+        NumberOfDelayLines = 2;
+    }
+    else
+    {
+        NumberOfDelayLines = 1;
+    }
+
+    /*
+     * Update the high pass filter coefficients
+     */
+    if((pPrivate->NewParams.HPF        != pPrivate->CurrentParams.HPF)        ||
+       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+       (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+        LVM_FLOAT       Omega;
+        FO_FLOAT_Coefs_t  Coeffs;
+
+        Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
+        LVM_FO_HPF(Omega, &Coeffs);
+        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs,
+                                         &pPrivate->pFastData->HPTaps, &Coeffs);
+        LoadConst_Float(0,
+                        (void *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: \
+                                                                 no dereferencing in function*/
+                        sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+    }
+
+
+    /*
+     * Update the low pass filter coefficients
+     */
+    if((pPrivate->NewParams.LPF        != pPrivate->CurrentParams.LPF)        ||
+       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+       (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+        LVM_FLOAT       Omega;
+        FO_FLOAT_Coefs_t  Coeffs;
+
+        Coeffs.A0 = 1;
+        Coeffs.A1 = 0;
+        Coeffs.B1 = 0;
+        if(pPrivate->NewParams.LPF <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
+        {
+            Omega = LVM_GetOmega(pPrivate->NewParams.LPF, pPrivate->NewParams.SampleRate);
+
+            /*
+             * Do not apply filter if w =2*pi*fc/fs >= 2.9
+             */
+            if(Omega <= (LVM_FLOAT)LVREV_2_9_INQ29)
+            {
+                LVM_FO_LPF(Omega, &Coeffs);
+            }
+        }
+        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs,
+                                         &pPrivate->pFastData->LPTaps, &Coeffs);
+        LoadConst_Float(0,
+                        (void *)&pPrivate->pFastData->LPTaps, /* Destination Cast to void: \
+                                                                 no dereferencing in function*/
+                        sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+    }
+
+
+    /*
+     * Calculate the room size parameter
+     */
+    if( pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize)
+    {
+        /* Room size range is 10ms to 200ms
+         * 0%   -- 10ms
+         * 50%  -- 65ms
+         * 100% -- 120ms
+         */
+        pPrivate->RoomSizeInms = 10 + (((pPrivate->NewParams.RoomSize*11) + 5) / 10);
+    }
+
+
+    /*
+     * Update the T delay number of samples and the all pass delay number of samples
+     */
+    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
+        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+        (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+
+        LVM_UINT32  Temp;
+        LVM_INT32   APDelaySize;
+        LVM_INT32   Fs = LVM_GetFsFromTable(pPrivate->NewParams.SampleRate);
+        LVM_UINT32  DelayLengthSamples = (LVM_UINT32)(Fs * pPrivate->RoomSizeInms);
+        LVM_INT16   i;
+        LVM_FLOAT   ScaleTable[]  = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, \
+                                     LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
+        LVM_INT16   MaxT_Delay[]  = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, \
+                                     LVREV_MAX_T2_DELAY, LVREV_MAX_T3_DELAY};
+        LVM_INT16   MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, \
+                                     LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
+
+
+        /*
+         * For each delay line
+         */
+        for (i = 0; i < NumberOfDelayLines; i++)
+        {
+            if (i != 0)
+            {
+                LVM_FLOAT Temp1;  /* to avoid QAC warning on type conversion */
+
+                Temp1=(LVM_FLOAT)DelayLengthSamples;
+                Temp = (LVM_UINT32)(Temp1 * ScaleTable[i]);
+            }
+            else
+            {
+               Temp = DelayLengthSamples;
+            }
+            APDelaySize = Temp  / 1500;
+
+
+            /*
+             * Set the fixed delay
+             */
+
+#ifdef HIGHER_FS
+            Temp  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 192000;
+#else
+            Temp  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 48000;
+#endif
+            pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
+
+
+            /*
+             * Set the tap selection
+             */
+            if (pPrivate->AB_Selection)
+            {
+                /* Smooth from tap A to tap B */
+                pPrivate->pOffsetB[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - \
+                                                                           Temp - APDelaySize];
+                pPrivate->B_DelaySize[i]          = APDelaySize;
+                pPrivate->Mixer_APTaps[i].Target1 = 0;
+                pPrivate->Mixer_APTaps[i].Target2 = 1.0f;
+            }
+            else
+            {
+                /* Smooth from tap B to tap A */
+                pPrivate->pOffsetA[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - \
+                                                                           Temp - APDelaySize];
+                pPrivate->A_DelaySize[i]          = APDelaySize;
+                pPrivate->Mixer_APTaps[i].Target2 = 0;
+                pPrivate->Mixer_APTaps[i].Target1 = 1.0f;
+            }
+
+            /*
+             * Set the maximum block size to the smallest delay size
+             */
+            pPrivate->MaxBlkLen   = Temp;
+            if (pPrivate->MaxBlkLen > pPrivate->A_DelaySize[i])
+            {
+                pPrivate->MaxBlkLen = pPrivate->A_DelaySize[i];
+            }
+            if (pPrivate->MaxBlkLen > pPrivate->B_DelaySize[i])
+            {
+                pPrivate->MaxBlkLen = pPrivate->B_DelaySize[i];
+            }
+        }
+        if (pPrivate->AB_Selection)
+        {
+            pPrivate->AB_Selection = 0;
+        }
+        else
+        {
+            pPrivate->AB_Selection = 1;
+        }
+
+
+        /*
+         * Limit the maximum block length
+         */
+        /* Just as a precausion, but no problem if we remove this line      */
+        pPrivate->MaxBlkLen = pPrivate->MaxBlkLen - 2;
+        if(pPrivate->MaxBlkLen > pPrivate->InstanceParams.MaxBlockSize)
+        {
+            pPrivate->MaxBlkLen = (LVM_INT32)pPrivate->InstanceParams.MaxBlockSize;
+        }
+    }
+
+
+
+    /*
+     * Update the low pass filter coefficient
+     */
+    if( (pPrivate->NewParams.Damping    != pPrivate->CurrentParams.Damping)    ||
+        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+        (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+
+        LVM_INT32       Temp;
+        LVM_FLOAT       Omega;
+        FO_FLOAT_Coefs_t  Coeffs;
+        LVM_INT16       i;
+        LVM_INT16       Damping      = (LVM_INT16)((pPrivate->NewParams.Damping * 100) + 1000);
+        LVM_FLOAT       ScaleTable[] = {LVREV_T_3_Power_0_on_4, LVREV_T_3_Power_1_on_4,
+                                        LVREV_T_3_Power_2_on_4, LVREV_T_3_Power_3_on_4};
+
+
+        /*
+         * For each filter
+         */
+        for (i = 0; i < NumberOfDelayLines; i++)
+        {
+            if (i != 0)
+            {
+                Temp = (LVM_INT32)(ScaleTable[i] * Damping);
+            }
+            else
+            {
+                Temp = Damping;
+            }
+            if(Temp <= (LVM_INT32)(LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
+            {
+                Omega = LVM_GetOmega(Temp, pPrivate->NewParams.SampleRate);
+                LVM_FO_LPF(Omega, &Coeffs);
+            }
+            else
+            {
+                Coeffs.A0 = 1;
+                Coeffs.A1 = 0;
+                Coeffs.B1 = 0;
+            }
+            FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i],
+                                            &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
+        }
+    }
+
+
+    /*
+     * Update All-pass filter mixer time constants
+     */
+    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
+        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+        (pPrivate->NewParams.Density    != pPrivate->CurrentParams.Density))
+    {
+        LVM_INT16   i;
+        LVM_FLOAT   Alpha;
+        LVM_FLOAT   AlphaTap;
+
+        Alpha = LVM_Mixer_TimeConstant(LVREV_ALLPASS_TC,
+                                       LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
+                                       1);
+
+        AlphaTap = LVM_Mixer_TimeConstant(LVREV_ALLPASS_TAP_TC,
+                                          LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
+                                          1);
+
+        for (i = 0; i < 4; i++)
+        {
+            pPrivate->Mixer_APTaps[i].Alpha1       = AlphaTap;
+            pPrivate->Mixer_APTaps[i].Alpha2       = AlphaTap;
+            pPrivate->Mixer_SGFeedback[i].Alpha    = Alpha;
+            pPrivate->Mixer_SGFeedforward[i].Alpha = Alpha;
+        }
+    }
+
+
+    /*
+     * Update the feed back gain
+     */
+    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
+        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+        (pPrivate->NewParams.T60        != pPrivate->CurrentParams.T60)        ||
+        (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+
+        LVM_FLOAT               G[4];                       /* Feedback gain (Q7.24) */
+
+        if(pPrivate->NewParams.T60 == 0)
+        {
+            G[3] = 0;
+            G[2] = 0;
+            G[1] = 0;
+            G[0] = 0;
+        }
+        else
+        {
+            LVM_FLOAT   Temp1;
+            LVM_FLOAT   Temp2;
+            LVM_INT16   i;
+            LVM_FLOAT   ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4,
+                                        LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
+
+
+            /*
+             * For each delay line
+             */
+            for (i = 0; i < NumberOfDelayLines; i++)
+            {
+                Temp1 = (3 * pPrivate->RoomSizeInms * ScaleTable[i]) / pPrivate->NewParams.T60;
+                if(Temp1 >= (4))
+                {
+                    G[i] = 0;
+                }
+                else if((Temp1 >= (2)))
+                {
+                    Temp2 = LVM_Power10(-(Temp1 / 2.0f));
+                    Temp1 = LVM_Power10(-(Temp1 / 2.0f));
+                    Temp1 = Temp1 * Temp2;
+                }
+                else
+                {
+                    Temp1 = LVM_Power10(-(Temp1));
+                }
+                if (NumberOfDelayLines == 1)
+                {
+                    G[i] = Temp1;
+                }
+                else
+                {
+                    LVM_FLOAT   TempG;
+                    TempG = Temp1 * ONE_OVER_SQRT_TWO;
+                    G[i]=TempG;
+                }
+            }
+        }
+
+        /* Set up the feedback mixers for four delay lines */
+        pPrivate->FeedbackMixer[0].Target=G[0];
+        pPrivate->FeedbackMixer[1].Target=G[1];
+        pPrivate->FeedbackMixer[2].Target=G[2];
+        pPrivate->FeedbackMixer[3].Target=G[3];
+    }
+
+
+    /*
+     * Calculate the gain correction
+     */
+    if((pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+       (pPrivate->NewParams.Level    != pPrivate->CurrentParams.Level)    ||
+       (pPrivate->NewParams.T60      != pPrivate->CurrentParams.T60) )
+    {
+        LVM_INT32 Index=0;
+        LVM_FLOAT Index_FLOAT;
+        LVM_INT32 i=0;
+        LVM_FLOAT Gain=0;
+        LVM_INT32 RoomSize=0;
+        LVM_FLOAT T60;
+        LVM_FLOAT Coefs[5];
+
+
+        if(pPrivate->NewParams.RoomSize == 0)
+        {
+            RoomSize = 1;
+        }
+        else
+        {
+            RoomSize = (LVM_INT32)pPrivate->NewParams.RoomSize;
+        }
+
+
+        if(pPrivate->NewParams.T60 < 100)
+        {
+            T60 = 100 * LVREV_T60_SCALE;
+        }
+        else
+        {
+            T60 = pPrivate->NewParams.T60 * LVREV_T60_SCALE;
+        }
+
+        /* Find the nearest room size in table */
+        for(i = 0; i < 24; i++)
+        {
+            if(RoomSize <= LVREV_GainPolyTable[i][0])
+            {
+                Index = i;
+                break;
+            }
+        }
+
+
+        if(RoomSize == LVREV_GainPolyTable[Index][0])
+        {
+            /* Take table values if the room size is in table */
+            for(i = 1; i < 5; i++)
+            {
+                Coefs[i-1] = LVREV_GainPolyTable[Index][i];
+            }
+            Coefs[4] = 0;
+            Gain = LVM_Polynomial(3, Coefs, T60);       /* Q.24 result */
+        }
+        else
+        {
+            /* Interpolate the gain between nearest room sizes */
+
+            LVM_FLOAT Gain1,Gain2;
+            LVM_INT32 Tot_Dist,Dist;
+
+            Tot_Dist = (LVM_UINT32)LVREV_GainPolyTable[Index][0] - \
+                                            (LVM_UINT32)LVREV_GainPolyTable[Index-1][0];
+            Dist = RoomSize - (LVM_UINT32)LVREV_GainPolyTable[Index - 1][0];
+
+
+            /* Get gain for first */
+            for(i = 1; i < 5; i++)
+            {
+                Coefs[i-1] = LVREV_GainPolyTable[Index-1][i];
+            }
+            Coefs[4] = 0;
+
+            Gain1 = LVM_Polynomial(3, Coefs, T60);      /* Q.24 result */
+
+            /* Get gain for second */
+            for(i = 1; i < 5; i++)
+            {
+                Coefs[i-1] = LVREV_GainPolyTable[Index][i];
+            }
+            Coefs[4] = 0;
+
+            Gain2 = LVM_Polynomial(3, Coefs, T60);      /* Q.24 result */
+
+            /* Linear Interpolate the gain */
+            Gain = Gain1 + (((Gain2 - Gain1) * Dist) / (Tot_Dist));
+        }
+
+
+        /*
+         * Get the inverse of gain: Q.15
+         * Gain is mostly above one except few cases, take only gains above 1
+         */
+        if(Gain < 1)
+        {
+            pPrivate->Gain = 1;
+        }
+        else
+        {
+            pPrivate->Gain = 1 / Gain;
+        }
+
+        Index_FLOAT = 100.0f / (LVM_FLOAT)(100 + pPrivate->NewParams.Level);
+        pPrivate->Gain = pPrivate->Gain * Index_FLOAT;
+        pPrivate->GainMixer.Target = (pPrivate->Gain*Index_FLOAT) / 2;
+    }
+
+
+    /*
+     * Update the all pass comb filter coefficient
+     */
+    if( (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density) ||
+        (pPrivate->bFirstControl     == LVM_TRUE))
+    {
+        LVM_INT16   i;
+        LVM_FLOAT   b = (LVM_FLOAT)pPrivate->NewParams.Density * LVREV_B_8_on_1000;
+
+        for (i = 0; i < 4; i++)
+        {
+            pPrivate->Mixer_SGFeedback[i].Target    = b;
+            pPrivate->Mixer_SGFeedforward[i].Target = b;
+        }
+    }
+
+
+    /*
+     * Update the bypass mixer time constant
+     */
+    if((pPrivate->NewParams.SampleRate   != pPrivate->CurrentParams.SampleRate)   ||
+       (pPrivate->bFirstControl          == LVM_TRUE))
+    {
+        LVM_UINT16   NumChannels = 1;                       /* Assume MONO format */
+        LVM_FLOAT    Alpha;
+
+        Alpha = LVM_Mixer_TimeConstant(LVREV_FEEDBACKMIXER_TC,
+                                       LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
+                                       NumChannels);
+        pPrivate->FeedbackMixer[0].Alpha = Alpha;
+        pPrivate->FeedbackMixer[1].Alpha = Alpha;
+        pPrivate->FeedbackMixer[2].Alpha = Alpha;
+        pPrivate->FeedbackMixer[3].Alpha = Alpha;
+
+        NumChannels = 2;                                    /* Always stereo output */
+        pPrivate->BypassMixer.Alpha1 = LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC,
+                             LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
+        pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
+        pPrivate->GainMixer.Alpha    = pPrivate->BypassMixer.Alpha1;
+    }
+
+
+    /*
+     * Update the bypass mixer targets
+     */
+    if( (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) &&
+        (pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
+    {
+        pPrivate->BypassMixer.Target2 = (LVM_FLOAT)(pPrivate->NewParams.Level ) / 100.0f;
+        pPrivate->BypassMixer.Target1 = 0x00000000;
+        if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
+        {
+            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
+        }
+        if (pPrivate->NewParams.Level != 0)
+        {
+            pPrivate->bDisableReverb = LVM_FALSE;
+        }
+    }
+
+    if(pPrivate->NewParams.OperatingMode != pPrivate->CurrentParams.OperatingMode)
+    {
+        if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
+        {
+            pPrivate->BypassMixer.Target2 = (LVM_FLOAT)(pPrivate->NewParams.Level ) / 100.0f;
+            pPrivate->BypassMixer.Target1 = 0x00000000;
+
+            pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
+            OperatingMode                      = LVM_MODE_ON;
+            if (pPrivate->NewParams.Level == 0)
+            {
+                pPrivate->bDisableReverb = LVM_TRUE;
+            }
+            else
+            {
+                pPrivate->bDisableReverb = LVM_FALSE;
+            }
+        }
+        else if (pPrivate->bFirstControl == LVM_FALSE)
+        {
+            pPrivate->BypassMixer.Target2 = 0x00000000;
+            pPrivate->BypassMixer.Target1 = 0x00000000;
+            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
+            pPrivate->GainMixer.Target    = 0.03125f;
+            OperatingMode = LVM_MODE_ON;
+        }
+        else
+        {
+            OperatingMode = LVM_MODE_OFF;
+        }
+    }
+
+
+    /*  If it is the first call to ApplyNew settings force the current to the target \
+        to begin immediate playback of the effect */
+    if(pPrivate->bFirstControl == LVM_TRUE)
+    {
+        pPrivate->BypassMixer.Current1 = pPrivate->BypassMixer.Target1;
+        pPrivate->BypassMixer.Current2 = pPrivate->BypassMixer.Target2;
+    }
+
+
+    /*
+     * Copy the new parameters
+     */
+    pPrivate->CurrentParams = pPrivate->NewParams;
+    pPrivate->CurrentParams.OperatingMode = OperatingMode;
+
+
+    /*
+     * Update flag
+     */
+    if(pPrivate->bFirstControl == LVM_TRUE)
+    {
+        pPrivate->bFirstControl = LVM_FALSE;
+    }
+
+
+    return LVREV_SUCCESS;
+}
+#endif /*BUILD_FLOAT*/
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                BypassMixer_Callback                                        */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c
index 6bb1e88..9491016 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c
@@ -61,16 +61,26 @@
      * Clear all filter tap data, delay-lines and other signal related data
      */
 
-
+#ifdef BUILD_FLOAT
+    LoadConst_Float(0,
+                    (void *)&pLVREV_Private->pFastData->HPTaps, /* Destination Cast to void: \
+                                                                   no dereferencing in function*/
+                    2);
+    LoadConst_Float(0,
+                    (void *)&pLVREV_Private->pFastData->LPTaps, /* Destination Cast to void: \
+                                                                   no dereferencing in function*/
+                    2);
+#else
     LoadConst_32(0,
         (void *)&pLVREV_Private->pFastData->HPTaps, /* Destination Cast to void: no dereferencing in function*/
         2);
     LoadConst_32(0,
         (void *)&pLVREV_Private->pFastData->LPTaps, /* Destination Cast to void: no dereferencing in function*/
         2);
-
+#endif
     if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
     {
+#ifndef BUILD_FLOAT
         LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
         LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
         LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
@@ -80,24 +90,46 @@
         LoadConst_32(0,pLVREV_Private->pDelay_T[2], (LVM_INT16)LVREV_MAX_T2_DELAY);
         LoadConst_32(0,pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
         LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+#else
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
 
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+#endif
     }
 
     if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_2)
     {
+#ifndef BUILD_FLOAT
         LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
         LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
 
         LoadConst_32(0,pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
         LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+#else
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+#endif
     }
 
     if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_1)
     {
+#ifndef BUILD_FLOAT
         LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
         LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+#else
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+#endif
     }
-
     return LVREV_SUCCESS;
 }
 
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
index ffa5138..3366bcb 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
@@ -108,11 +108,29 @@
     /*
      * Zero all memory regions
      */
-     LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size)/sizeof(LVM_INT16)));
-     LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size)/sizeof(LVM_INT16)));
-     LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size)/sizeof(LVM_INT16)));
-     LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_TEMPORARY_FAST].Size)/sizeof(LVM_INT16)));
-
+#ifdef BUILD_FLOAT
+    LoadConst_Float(0,
+                    (LVM_FLOAT *)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress,
+                    (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size) / \
+                                                    sizeof(LVM_FLOAT)));
+    LoadConst_Float(0,
+                    (LVM_FLOAT *)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress,
+                    (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size) / \
+                                                    sizeof(LVM_FLOAT)));
+    LoadConst_Float(0,
+                    (LVM_FLOAT *)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress,
+                    (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size) / \
+                                                    sizeof(LVM_FLOAT)));
+    LoadConst_Float(0,
+                    (LVM_FLOAT *)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress,
+                    (LVM_INT16)((pMemoryTable->Region[LVM_TEMPORARY_FAST].Size) / \
+                                                    sizeof(LVM_FLOAT)));
+#else
+    LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size)/sizeof(LVM_INT16)));
+    LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size)/sizeof(LVM_INT16)));
+    LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size)/sizeof(LVM_INT16)));
+    LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_TEMPORARY_FAST].Size)/sizeof(LVM_INT16)));
+#endif
     /*
      * Set the instance handle if not already initialised
      */
@@ -146,7 +164,7 @@
      * Set the data, coefficient and temporary memory pointers
      */
     pLVREV_Private->pFastData = InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));                              /* Fast data memory base address */
-
+#ifndef BUILD_FLOAT
     if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
     {
         pLVREV_Private->pDelay_T[3]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY  * sizeof(LVM_INT32));
@@ -190,7 +208,67 @@
 
         LoadConst_32(0,pLVREV_Private->pDelay_T[0]  , (LVM_INT16)LVREV_MAX_T0_DELAY);
     }
+#else
+    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+    {
+        pLVREV_Private->pDelay_T[3]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * \
+                                                              sizeof(LVM_FLOAT));
+        pLVREV_Private->pDelay_T[2]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * \
+                                                              sizeof(LVM_FLOAT));
+        pLVREV_Private->pDelay_T[1]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * \
+                                                              sizeof(LVM_FLOAT));
+        pLVREV_Private->pDelay_T[0]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * \
+                                                              sizeof(LVM_FLOAT));
 
+        for(i = 0; i < 4; i++)
+        {
+            /* Scratch for each delay line output */
+            pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary,
+                                                                       sizeof(LVM_FLOAT) * \
+                                                                       MaxBlockSize);
+        }
+
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+    }
+
+    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+    {
+        pLVREV_Private->pDelay_T[1]  = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * \
+                                                           sizeof(LVM_FLOAT));
+        pLVREV_Private->pDelay_T[0]  = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * \
+                                                           sizeof(LVM_FLOAT));
+
+        for(i = 0; i < 2; i++)
+        {
+            /* Scratch for each delay line output */
+            pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary,
+                                                                       sizeof(LVM_FLOAT) * \
+                                                                       MaxBlockSize);
+        }
+
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+    }
+
+    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+    {
+        pLVREV_Private->pDelay_T[0]  = InstAlloc_AddMember(&FastData,
+                                                           LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+
+        for(i = 0; i < 1; i++)
+        {
+            /* Scratch for each delay line output */
+            pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary,
+                                                                       sizeof(LVM_FLOAT) * \
+                                                                       MaxBlockSize);
+        }
+
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+    }
+#endif
     /* All-pass delay buffer addresses and sizes */
     pLVREV_Private->T[0]         = LVREV_MAX_T0_DELAY;
     pLVREV_Private->T[1]         = LVREV_MAX_T1_DELAY;
@@ -200,10 +278,19 @@
 
 
     pLVREV_Private->pFastCoef       = InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));                        /* Fast coefficient memory base address */
+#ifndef BUILD_FLOAT
     pLVREV_Private->pScratch        = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);                /* General purpose scratch */
     pLVREV_Private->pInputSave      = InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_INT32) * MaxBlockSize);            /* Mono->stereo input save for end mix */
     LoadConst_32(0, pLVREV_Private->pInputSave, (LVM_INT16)(MaxBlockSize*2));
-
+#else
+    /* General purpose scratch */
+    pLVREV_Private->pScratch        = InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * \
+                                                          MaxBlockSize);
+    /* Mono->stereo input save for end mix */
+    pLVREV_Private->pInputSave      = InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * \
+                                                          MaxBlockSize);
+    LoadConst_Float(0, pLVREV_Private->pInputSave, (LVM_INT16)(MaxBlockSize * 2));
+#endif
 
     /*
      * Save the instance parameters in the instance structure
@@ -252,9 +339,13 @@
     pLVREV_Private->GainMixer.pGeneralPurpose    = LVM_NULL;
     pLVREV_Private->GainMixer.pCallBack          = LVM_NULL;
     pLVREV_Private->GainMixer.CallbackSet        = LVM_FALSE;
+#ifndef BUILD_FLOAT
     pLVREV_Private->GainMixer.Current            = 0x03ffffff;
     pLVREV_Private->GainMixer.Target             = 0x03ffffff;
-
+#else
+    pLVREV_Private->GainMixer.Current            = 0.03125f;//0x03ffffff;
+    pLVREV_Private->GainMixer.Target             = 0.03125f;//0x03ffffff;
+#endif
 
     /*
      * Set the All-Pass Filter mixers
@@ -277,7 +368,11 @@
         pLVREV_Private->Mixer_APTaps[i].pCallBack1       = LVM_NULL;
         pLVREV_Private->Mixer_APTaps[i].CallbackSet1     = LVM_FALSE;
         pLVREV_Private->Mixer_APTaps[i].Current1         = 0;
+#ifndef BUILD_FLOAT
         pLVREV_Private->Mixer_APTaps[i].Target1          = 0x7fffffff;
+#else
+        pLVREV_Private->Mixer_APTaps[i].Target1          = 1;
+#endif
         /* Feedforward mixer */
         pLVREV_Private->Mixer_SGFeedforward[i].CallbackParam   = 0;
         pLVREV_Private->Mixer_SGFeedforward[i].pCallbackHandle = LVM_NULL;
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c
index 2012432..f6d446b 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c
@@ -161,21 +161,37 @@
         InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
         if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
         {
+#ifndef BUILD_FLOAT
             InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY  * sizeof(LVM_INT32));
             InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY  * sizeof(LVM_INT32));
             InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
             InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+#else
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+#endif
         }
 
         if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
         {
+#ifndef BUILD_FLOAT
             InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
             InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+#else
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+#endif
         }
 
         if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
         {
+#ifndef BUILD_FLOAT
             InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+#else
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+#endif
         }
 
         pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size         = InstAlloc_GetTotal(&FastData);
@@ -195,14 +211,25 @@
         /*
          * Temporary fast memory
          */
+#ifndef BUILD_FLOAT
         InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);          /* General purpose scratch memory */
         InstAlloc_AddMember(&Temporary, 2*sizeof(LVM_INT32) * MaxBlockSize);        /* Mono->stereo input saved for end mix */
-
+#else
+        /* General purpose scratch memory */
+        InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+        /* Mono->stereo input saved for end mix */
+        InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * MaxBlockSize);
+#endif
         if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
         {
             for(i=0; i<4; i++)
             {
+#ifndef BUILD_FLOAT
                 InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);      /* A Scratch buffer for each delay line */
+#else
+                /* A Scratch buffer for each delay line */
+                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+#endif
             }
         }
 
@@ -210,7 +237,12 @@
         {
             for(i=0; i<2; i++)
             {
+#ifndef BUILD_FLOAT
                 InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);      /* A Scratch buffer for each delay line */
+#else
+                /* A Scratch buffer for each delay line */
+                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+#endif
             }
         }
 
@@ -218,7 +250,12 @@
         {
             for(i=0; i<1; i++)
             {
+#ifndef BUILD_FLOAT
                 InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);      /* A Scratch buffer for each delay line */
+#else
+                /* A Scratch buffer for each delay line */
+                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+#endif
             }
         }
 
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
index fbfa437..ff7475e 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
@@ -42,16 +42,27 @@
 /*  Defines                                                                             */
 /*                                                                                      */
 /****************************************************************************************/
+#ifndef BUILD_FLOAT
 /* General */
 #define ONE_OVER_SQRT_TWO               23170           /* 1/sqrt(2) * 2^15 */
 #define LVREV_B_8_on_1000            17179869           /* 0.8 * 2^31 */
 #define LVREV_HEADROOM                   8192           /* -12dB * 2^15 */
 #define LVREV_2_9_INQ29           1583769190L           /* 2.9 in Q29 format */
 #define LVREV_MIN3DB                   0x5A82           /* -3dB in Q15 format */
+#else
+/* General */
+#define ONE_OVER_SQRT_TWO            0.707107f           /* 1/sqrt(2) * 2^15 */
+#define LVREV_B_8_on_1000               0.008f           /* 0.8 * 2^31 */
+#define LVREV_HEADROOM                   0.25f           /* -12dB * 2^15 */
+#define LVREV_2_9_INQ29                   2.9f           /* 2.9 in Q29 format */
+#define LVREV_MIN3DB                0.7079457f           /* -3dB in Q15 format */
+#endif
 
 /* Intenal constants */
 #define LVREV_LP_Poly_Order                 4
 #define LVREV_LP_Poly_Shift                 5
+
+#ifndef BUILD_FLOAT
 #define LVREV_T_3_Power_0_on_4          32768
 #define LVREV_T_3_Power_1_on_4          43125
 #define LVREV_T_3_Power_2_on_4          56755
@@ -61,14 +72,47 @@
 #define LVREV_T_3_Power_minus1_on_4     24898           /* 3^(-1/4) * 2^15 */
 #define LVREV_T_3_Power_minus2_on_4     18919           /* 3^(-2/4) * 2^15 */
 #define LVREV_T_3_Power_minus3_on_4     14375           /* 3^(-3/4) * 2^15 */
-#define LVREV_MAX_T3_DELAY               2527           /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1000 */
-#define LVREV_MAX_T2_DELAY               3326           /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1000 */
-#define LVREV_MAX_T1_DELAY               4377           /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1000 */
-#define LVREV_MAX_T0_DELAY               5760           /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1000 */
-#define LVREV_MAX_AP3_DELAY              1685           /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1500 */
-#define LVREV_MAX_AP2_DELAY              2218           /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1500 */
-#define LVREV_MAX_AP1_DELAY              2918           /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1500 */
-#define LVREV_MAX_AP0_DELAY              3840           /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1500 */
+#else/*BUILD_FLOAT*/
+#define LVREV_T60_SCALE                0.000142f           /*(1/7000) */
+
+#define LVREV_T_3_Power_0_on_4              1.0f
+#define LVREV_T_3_Power_1_on_4         1.316074f
+#define LVREV_T_3_Power_2_on_4         1.732051f
+#define LVREV_T_3_Power_3_on_4         2.279507f
+#define LVREV_T_3_Power_minus0_on_4         1.0f        /* 3^(-0/4) * 2^15 */
+#define LVREV_T_3_Power_minus1_on_4    0.759836f        /* 3^(-1/4) * 2^15 */
+#define LVREV_T_3_Power_minus2_on_4    0.577350f        /* 3^(-2/4) * 2^15 */
+#define LVREV_T_3_Power_minus3_on_4    0.438691f        /* 3^(-3/4) * 2^15 */
+#endif
+
+#ifndef HIGHER_FS
+#define LVREV_MAX_T3_DELAY                2527           /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T2_DELAY                3326           /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T1_DELAY                4377           /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T0_DELAY                5760           /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1000 */
+#define LVREV_MAX_AP3_DELAY               1685           /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP2_DELAY               2218           /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP1_DELAY               2918           /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP0_DELAY               3840           /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1500 */
+#else
+    /* ((192000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T3_DELAY               10108
+    /* ((192000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T2_DELAY               13304
+    /* ((192000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T1_DELAY               17508
+    /* ((192000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T0_DELAY               23040
+    /* ((192000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP3_DELAY               6740
+    /* ((192000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP2_DELAY               8872
+    /* ((192000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP1_DELAY              11672
+    /* ((192000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP0_DELAY              15360
+#endif
+
 #define LVREV_BYPASSMIXER_TC             1000           /* Bypass mixer time constant*/
 #define LVREV_ALLPASS_TC                 1000           /* All-pass filter time constant */
 #define LVREV_ALLPASS_TAP_TC             10000           /* All-pass filter dely tap change */
@@ -76,7 +120,12 @@
 #define LVREV_OUTPUTGAIN_SHIFT              5           /* Bits shift for output gain correction */
 
 /* Parameter limits */
+#ifndef HIGHER_FS
 #define LVREV_NUM_FS                        9           /* Number of supported sample rates */
+#else
+#define LVREV_NUM_FS                       11           /* Number of supported sample rates */
+#endif
+
 #define LVREV_MAXBLKSIZE_LIMIT             64           /* Maximum block size low limit */
 #define LVREV_MAX_LEVEL                   100           /* Maximum level, 100% */
 #define LVREV_MIN_LPF_CORNER               50           /* Low pass filter limits */
@@ -95,6 +144,7 @@
 /*  Structures                                                                          */
 /*                                                                                      */
 /****************************************************************************************/
+#ifndef BUILD_FLOAT
 /* Fast data structure */
 typedef struct
 {
@@ -161,7 +211,81 @@
 
 } LVREV_Instance_st;
 
+#else /* BUILD_FLOAT */
 
+/* Fast data structure */
+typedef struct
+{
+    Biquad_1I_Order1_FLOAT_Taps_t HPTaps;                     /* High pass filter taps */
+    Biquad_1I_Order1_FLOAT_Taps_t LPTaps;                     /* Low pass filter taps */
+    Biquad_1I_Order1_FLOAT_Taps_t RevLPTaps[4];               /* Reverb low pass filters taps */
+
+} LVREV_FastData_st;
+
+
+/* Fast coefficient structure */
+typedef struct
+{
+
+    Biquad_FLOAT_Instance_t       HPCoefs;              /* High pass filter coefficients */
+    Biquad_FLOAT_Instance_t       LPCoefs;              /* Low pass filter coefficients */
+    Biquad_FLOAT_Instance_t       RevLPCoefs[4];        /* Reverb low pass filters coefficients */
+
+} LVREV_FastCoef_st;
+typedef struct
+{
+    /* General */
+    LVREV_InstanceParams_st InstanceParams;           /* Initialisation time instance parameters */
+    LVREV_MemoryTable_st    MemoryTable;              /* Memory table */
+    LVREV_ControlParams_st  CurrentParams;            /* Parameters being used */
+    LVREV_ControlParams_st  NewParams;                /* New parameters from the \
+                                                         calling application */
+    LVM_CHAR                bControlPending;          /* Flag to indicate new parameters \
+                                                         are available */
+    LVM_CHAR                bFirstControl;            /* Flag to indicate that the control \
+                                                         function is called for the first time */
+    LVM_CHAR                bDisableReverb;           /* Flag to indicate that the mix level is
+                                                         0% and the reverb can be disabled */
+    LVM_INT32               RoomSizeInms;             /* Room size in msec */
+    LVM_INT32               MaxBlkLen;                /* Maximum block size for internal
+                                                         processing */
+
+    /* Aligned memory pointers */
+    LVREV_FastData_st       *pFastData;               /* Fast data memory base address */
+    LVREV_FastCoef_st       *pFastCoef;               /* Fast coefficient memory base address */
+    LVM_FLOAT               *pScratchDelayLine[4];    /* Delay line scratch memory */
+    LVM_FLOAT               *pScratch;                /* Multi ussge scratch */
+    LVM_FLOAT               *pInputSave;              /* Reverb block input save for dry/wet
+                                                         mixing*/
+
+    /* Feedback matrix */
+    Mix_1St_Cll_FLOAT_t     FeedbackMixer[4];         /* Mixer for Pop and Click Supression \
+                                                         caused by feedback Gain */
+
+
+    /* All-Pass Filter */
+    LVM_INT32               T[4];                     /* Maximum delay size of buffer */
+    LVM_FLOAT               *pDelay_T[4];             /* Pointer to delay buffers */
+    LVM_INT32               Delay_AP[4];              /* Offset to AP delay buffer start */
+    LVM_INT16               AB_Selection;             /* Smooth from tap A to B when 1 \
+                                                         otherwise B to A */
+    LVM_INT32               A_DelaySize[4];           /* A delay length in samples */
+    LVM_INT32               B_DelaySize[4];           /* B delay length in samples */
+    LVM_FLOAT               *pOffsetA[4];             /* Offset for the A delay tap */
+    LVM_FLOAT               *pOffsetB[4];             /* Offset for the B delay tap */
+    Mix_2St_Cll_FLOAT_t     Mixer_APTaps[4];          /* Smoothed AP delay mixer */
+    Mix_1St_Cll_FLOAT_t     Mixer_SGFeedback[4];      /* Smoothed SAfeedback gain */
+    Mix_1St_Cll_FLOAT_t     Mixer_SGFeedforward[4];   /* Smoothed AP feedforward gain */
+
+    /* Output gain */
+    Mix_2St_Cll_FLOAT_t     BypassMixer;              /* Dry/wet mixer */
+    LVM_FLOAT               Gain;                     /* Gain applied to output to maintain
+                                                         average signal power */
+    Mix_1St_Cll_FLOAT_t     GainMixer;                /* Gain smoothing */
+
+} LVREV_Instance_st;
+
+#endif
 /****************************************************************************************/
 /*                                                                                      */
 /*  Function prototypes                                                                 */
@@ -169,12 +293,17 @@
 /****************************************************************************************/
 
 LVREV_ReturnStatus_en   LVREV_ApplyNewSettings(LVREV_Instance_st     *pPrivate);
-
+#ifdef BUILD_FLOAT
+void                    ReverbBlock(LVM_FLOAT           *pInput,
+                                    LVM_FLOAT           *pOutput,
+                                    LVREV_Instance_st   *pPrivate,
+                                    LVM_UINT16          NumSamples);
+#else
 void                    ReverbBlock(LVM_INT32           *pInput,
                                     LVM_INT32           *pOutput,
                                     LVREV_Instance_st   *pPrivate,
                                     LVM_UINT16          NumSamples);
-
+#endif
 LVM_INT32               BypassMixer_Callback(void       *pCallbackData,
                                              void       *pGeneralPurpose,
                                              LVM_INT16  GeneralPurpose );
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
index 5c7a8a0..566d84f 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
@@ -46,14 +46,26 @@
 /*  1. The input and output buffers must be 32-bit aligned                              */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
+                                    const LVM_FLOAT     *pInData,
+                                    LVM_FLOAT           *pOutData,
+                                    const LVM_UINT16    NumSamples)
+#else
 LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
                                     const LVM_INT32     *pInData,
                                     LVM_INT32           *pOutData,
                                     const LVM_UINT16    NumSamples)
+#endif
 {
    LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+#ifdef BUILD_FLOAT
+   LVM_FLOAT             *pInput  = (LVM_FLOAT *)pInData;
+   LVM_FLOAT             *pOutput = pOutData;
+#else
    LVM_INT32             *pInput  = (LVM_INT32 *)pInData;
    LVM_INT32             *pOutput = pOutData;
+#endif
    LVM_INT32             SamplesToProcess, RemainingSamples;
    LVM_INT32             format = 1;
 
@@ -105,7 +117,7 @@
             /*
              * Copy the data to the output buffer, convert to stereo is required
              */
-
+#ifndef BUILD_FLOAT
             if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){
                 MonoTo2I_32(pInput, pOutput, NumSamples);
             } else {
@@ -113,6 +125,15 @@
                         (LVM_INT16 *)pOutput,
                         (LVM_INT16)(NumSamples << 2)); // 32 bit data, stereo
             }
+#else
+            if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){
+                MonoTo2I_Float(pInput, pOutput, NumSamples);
+            } else {
+                Copy_Float(pInput,
+                           pOutput,
+                           (LVM_INT16)(NumSamples << 1)); // 32 bit data, stereo
+            }
+#endif
         }
 
         return LVREV_SUCCESS;
@@ -143,9 +164,13 @@
         }
 
         ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess);
-
+#ifdef BUILD_FLOAT
+        pInput  = (LVM_FLOAT *)(pInput + (SamplesToProcess * format));
+        pOutput = (LVM_FLOAT *)(pOutput + (SamplesToProcess * 2));      // Always stereo output
+#else
         pInput  = (LVM_INT32 *)(pInput +(SamplesToProcess*format));
-        pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*2));      // Always stereo output
+        pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*2));
+#endif
     }
 
     return LVREV_SUCCESS;
@@ -175,7 +200,7 @@
 /*  1. The input and output buffers must be 32-bit aligned                              */
 /*                                                                                      */
 /****************************************************************************************/
-
+#ifndef BUILD_FLOAT
 void ReverbBlock(LVM_INT32 *pInput, LVM_INT32 *pOutput, LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples)
 {
     LVM_INT16   j, size;
@@ -479,7 +504,322 @@
 
     return;
 }
+#else
+void ReverbBlock(LVM_FLOAT *pInput, LVM_FLOAT *pOutput,
+                 LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples)
+{
+    LVM_INT16   j, size;
+    LVM_FLOAT   *pDelayLine;
+    LVM_FLOAT   *pDelayLineInput = pPrivate->pScratch;
+    LVM_FLOAT   *pScratch = pPrivate->pScratch;
+    LVM_FLOAT   *pIn;
+    LVM_FLOAT   *pTemp = pPrivate->pInputSave;
+    LVM_INT32   NumberOfDelayLines;
+
+    /******************************************************************************
+     * All calculations will go into the buffer pointed to by pTemp, this will    *
+     * then be mixed with the original input to create the final output.          *
+     *                                                                            *
+     * When INPLACE processing is selected this must be a temporary buffer and    *
+     * hence this is the worst case, so for simplicity this will ALWAYS be so     *
+     *                                                                            *
+     * The input buffer will remain untouched until the output of the mixer if    *
+     * INPLACE processing is selected.                                            *
+     *                                                                            *
+     * The temp buffer will always be NumSamples in size regardless of MONO or    *
+     * STEREO input. In the case of stereo input all processing is done in MONO   *
+     * and the final output is converted to STEREO after the mixer                *
+     ******************************************************************************/
+
+    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+    {
+        NumberOfDelayLines = 4;
+    }
+    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+    {
+        NumberOfDelayLines = 2;
+    }
+    else
+    {
+        NumberOfDelayLines = 1;
+    }
+
+    if(pPrivate->CurrentParams.SourceFormat == LVM_MONO)
+    {
+        pIn = pInput;
+    }
+    else
+    {
+        /*
+         *  Stereo to mono conversion
+         */
+
+        From2iToMono_Float(pInput,
+                           pTemp,
+                           (LVM_INT16)NumSamples);
+        pIn = pTemp;
+    }
+
+    Mult3s_Float(pIn,
+                 (LVM_FLOAT)LVREV_HEADROOM,
+                 pTemp,
+                 (LVM_INT16)NumSamples);
+
+    /*
+     *  High pass filter
+     */
+    FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->HPCoefs,
+                               pTemp,
+                               pTemp,
+                               (LVM_INT16)NumSamples);
+    /*
+     *  Low pass filter
+     */
+    FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->LPCoefs,
+                               pTemp,
+                               pTemp,
+                               (LVM_INT16)NumSamples);
+    
+    /*
+     *  Process all delay lines
+     */
+
+    for(j = 0; j < NumberOfDelayLines; j++)
+    {
+        pDelayLine = pPrivate->pScratchDelayLine[j];
+
+        /*
+         * All-pass filter with pop and click suppression
+         */
+        /* Get the smoothed, delayed output. Put it in the output buffer */
+        MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j],
+                               pPrivate->pOffsetA[j],
+                               pPrivate->pOffsetB[j],
+                               pDelayLine,
+                               (LVM_INT16)NumSamples);
+        /* Re-align the all pass filter delay buffer and copying the fixed delay data \
+           to the AP delay in the process */
+        Copy_Float(&pPrivate->pDelay_T[j][NumSamples],
+                   pPrivate->pDelay_T[j],
+                   (LVM_INT16)(pPrivate->T[j] - NumSamples));         /* 32-bit data */
+        /* Apply the smoothed feedback and save to fixed delay input (currently empty) */
+        MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j],
+                               pDelayLine,
+                               &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                               (LVM_INT16)NumSamples);
+        /* Sum into the AP delay line */
+        Mac3s_Sat_Float(&pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                        -1.0f,    /* Invert since the feedback coefficient is negative */
+                        &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j] - NumSamples],
+                        (LVM_INT16)NumSamples);
+        /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */
+        MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j],
+                               &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j] - NumSamples],
+                               &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                               (LVM_INT16)NumSamples);
+        /* Sum into the AP output */
+        Mac3s_Sat_Float(&pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                        1.0f,
+                        pDelayLine,
+                        (LVM_INT16)NumSamples);
+
+        /*
+         *  Feedback gain
+         */
+        MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples);
+
+        /*
+         *  Low pass filter
+         */
+        FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->RevLPCoefs[j],
+                                   pDelayLine,
+                                   pDelayLine,
+                                   (LVM_INT16)NumSamples);
+    }
+
+    /*
+     *  Apply rotation matrix and delay samples
+     */
+    for(j = 0; j < NumberOfDelayLines; j++)
+    {
+
+        Copy_Float(pTemp,
+                   pDelayLineInput,
+                   (LVM_INT16)(NumSamples));
+        /*
+         *  Rotation matrix mix
+         */
+        switch(j)
+        {
+            case 3:
+                /*
+                 *  Add delay line 1 and 2 contribution
+                 */
+                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
+                                 pDelayLineInput, (LVM_INT16)NumSamples);
+                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[2], -1.0f,
+                                 pDelayLineInput, (LVM_INT16)NumSamples);
+
+                break;
+            case 2:
+
+                /*
+                 *  Add delay line 0 and 3 contribution
+                 */
+                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f,
+                                 pDelayLineInput, (LVM_INT16)NumSamples);
+                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[3], -1.0f,
+                                 pDelayLineInput, (LVM_INT16)NumSamples);
+
+                break;
+            case 1:
+                if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+                {
+                    /*
+                     *  Add delay line 0 and 3 contribution
+                     */
+                    Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f,
+                                    pDelayLineInput, (LVM_INT16)NumSamples);
+                    Add2_Sat_Float(pPrivate->pScratchDelayLine[3], pDelayLineInput,
+                                   (LVM_INT16)NumSamples);
+
+                }
+                else
+                {
+                    /*
+                     *  Add delay line 0 and 1 contribution
+                     */
+                     Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f,
+                                     pDelayLineInput, (LVM_INT16)NumSamples);
+                     Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
+                                     pDelayLineInput, (LVM_INT16)NumSamples);
+
+                }
+                break;
+            case 0:
+                if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+                {
+                    /*
+                     *  Add delay line 1 and 2 contribution
+                     */
+                    Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
+                                    pDelayLineInput, (LVM_INT16)NumSamples);
+                    Add2_Sat_Float(pPrivate->pScratchDelayLine[2], pDelayLineInput,
+                                   (LVM_INT16)NumSamples);
+
+                }
+                else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+                {
+                    /*
+                     *  Add delay line 0 and 1 contribution
+                     */
+                    Add2_Sat_Float(pPrivate->pScratchDelayLine[0], pDelayLineInput,
+                                   (LVM_INT16)NumSamples);
+                    Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
+                                    pDelayLineInput, (LVM_INT16)NumSamples);
+
+                }
+                else
+                {
+                    /*
+                     *  Add delay line 0 contribution
+                     */
+
+                    /*             SOURCE                          DESTINATION*/
+                    Add2_Sat_Float(pPrivate->pScratchDelayLine[0], pDelayLineInput,
+                                   (LVM_INT16)NumSamples);
+                }
+                break;
+            default:
+                break;
+        }
+
+        /*
+         *  Delay samples
+         */
+        Copy_Float(pDelayLineInput,
+                   &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                   (LVM_INT16)(NumSamples));              /* 32-bit data */
+    }
 
 
+    /*
+     *  Create stereo output
+     */
+    switch(pPrivate->InstanceParams.NumDelays)
+    {
+        case LVREV_DELAYLINES_4:
+             Add2_Sat_Float(pPrivate->pScratchDelayLine[3],
+                            pPrivate->pScratchDelayLine[0],
+                            (LVM_INT16)NumSamples);
+             Add2_Sat_Float(pPrivate->pScratchDelayLine[2],
+                            pPrivate->pScratchDelayLine[1],
+                            (LVM_INT16)NumSamples);
+
+
+            JoinTo2i_Float(pPrivate->pScratchDelayLine[0],
+                           pPrivate->pScratchDelayLine[1],
+                           pTemp,
+                           (LVM_INT16)NumSamples);
+
+
+            break;
+        case LVREV_DELAYLINES_2:
+
+             Copy_Float(pPrivate->pScratchDelayLine[1],
+                        pScratch,
+                        (LVM_INT16)(NumSamples));
+
+             Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0],
+                            -1.0f,
+                            pScratch,
+                            (LVM_INT16)NumSamples);
+
+             Add2_Sat_Float(pPrivate->pScratchDelayLine[1],
+                            pPrivate->pScratchDelayLine[0],
+                            (LVM_INT16)NumSamples);
+
+
+             JoinTo2i_Float(pPrivate->pScratchDelayLine[0],
+                            pScratch,
+                            pTemp,
+                            (LVM_INT16)NumSamples);
+            break;
+        case LVREV_DELAYLINES_1:
+            MonoTo2I_Float(pPrivate->pScratchDelayLine[0],
+                           pTemp,
+                           (LVM_INT16)NumSamples);
+            break;
+        default:
+            break;
+    }
+
+
+    /*
+     *  Dry/wet mixer
+     */
+
+    size = (LVM_INT16)(NumSamples << 1);
+    MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer,
+                           pTemp,
+                           pTemp,
+                           pOutput,
+                           size);
+
+    /* Apply Gain*/
+
+    Shift_Sat_Float(LVREV_OUTPUTGAIN_SHIFT,
+                    pOutput,
+                    pOutput,
+                    size);
+
+    MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer,
+                           pOutput,
+                           pOutput,
+                           size);
+
+    return;
+}
+#endif
 /* End of file */
 
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
index f5895a7..a719053 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
@@ -61,10 +61,15 @@
      * Check all new control parameters are in range
      */
     if(    ((pNewParams->OperatingMode != LVM_MODE_OFF) && (pNewParams->OperatingMode != LVM_MODE_ON))                                         ||
-        ((pNewParams->SampleRate != LVM_FS_8000) && (pNewParams->SampleRate != LVM_FS_11025) && (pNewParams->SampleRate != LVM_FS_12000)       &&
+        (
+        (pNewParams->SampleRate != LVM_FS_8000) && (pNewParams->SampleRate != LVM_FS_11025) && (pNewParams->SampleRate != LVM_FS_12000)       &&
         (pNewParams->SampleRate != LVM_FS_16000) && (pNewParams->SampleRate != LVM_FS_22050) && (pNewParams->SampleRate != LVM_FS_24000)       &&
-        (pNewParams->SampleRate != LVM_FS_32000) && (pNewParams->SampleRate != LVM_FS_44100) && (pNewParams->SampleRate != LVM_FS_48000))      ||
-        ((pNewParams->SourceFormat != LVM_STEREO) && (pNewParams->SourceFormat != LVM_MONOINSTEREO) && (pNewParams->SourceFormat != LVM_MONO)) )
+        (pNewParams->SampleRate != LVM_FS_32000) && (pNewParams->SampleRate != LVM_FS_44100) && (pNewParams->SampleRate != LVM_FS_48000)      
+#ifdef HIGHER_FS
+        && (pNewParams->SampleRate != LVM_FS_96000) && (pNewParams->SampleRate != LVM_FS_192000)
+#endif
+        )
+        || ((pNewParams->SourceFormat != LVM_STEREO) && (pNewParams->SourceFormat != LVM_MONOINSTEREO) && (pNewParams->SourceFormat != LVM_MONO)) )
     {
         return (LVREV_OUTOFRANGE);
     }
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
index 5a6d43d..b3edc60 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
@@ -29,6 +29,7 @@
 /****************************************************************************************/
 
 /* Table with supported sampling rates.  The table can be indexed using LVM_Fs_en       */
+#ifndef HIGHER_FS
 const LVM_UINT16 LVM_FsTable[] = {
     8000 ,
     11025,
@@ -40,14 +41,37 @@
     44100,
     48000
 };
-
+#else
+const LVM_UINT32 LVM_FsTable[] = {
+    8000 ,
+    11025,
+    12000,
+    16000,
+    22050,
+    24000,
+    32000,
+    44100,
+    48000,
+    96000,
+    192000
+};
+#endif
 /* Table with supported sampling rates.  The table can be indexed using LVM_Fs_en       */
+#ifndef HIGHER_FS
 LVM_UINT16 LVM_GetFsFromTable(LVM_Fs_en FsIndex){
     if (FsIndex > LVM_FS_48000)
         return 0;
 
     return (LVM_FsTable[FsIndex]);
 }
+#else
+LVM_UINT32 LVM_GetFsFromTable(LVM_Fs_en FsIndex){
+    if (FsIndex > LVM_FS_192000)
+        return 0;
+
+    return (LVM_FsTable[FsIndex]);
+}
+#endif
 
 /* In order to maintain consistant input and out put signal strengths
    output gain/attenuation is applied. This gain depends on T60 and Rooms
@@ -69,6 +93,7 @@
   */
 
 /* Normalizing output including Reverb Level part (only shift up)*/
+#ifndef BUILD_FLOAT
 const LVM_INT32 LVREV_GainPolyTable[24][5]={{1,17547434,128867434,-120988896,50761228,},
                                             {2,18256869,172666902,-193169292,88345744,},
                                             {3,16591311,139250151,-149667234,66770059,},
@@ -94,6 +119,32 @@
                                             {90,16003322,48323661,-35607378,13153872,},
                                             {100,15955223,48558201,-33706865,11715792,},
                                             };
-
+#else
+const LVM_FLOAT LVREV_GainPolyTable[24][5]={{1,1.045909f,7.681098f,-7.211500f,3.025605f,},
+                                            {2,1.088194f,10.291749f,-11.513787f,5.265817f,},
+                                            {3,0.988919f,8.299956f,-8.920862f,3.979806f,},
+                                            {4,1.035927f,10.182567f,-10.346134f,4.546533f,},
+                                            {5,1.130313f,12.538727f,-13.627023f,6.165208f,},
+                                            {6,1.060743f,8.091713f,-8.588079f,3.834230f,},
+                                            {7,1.040381f,10.406566f,-11.176650f,5.075132f,},
+                                            {8,1.026944f,8.387302f,-8.689796f,3.895863f,},
+                                            {9,1.013312f,9.727236f,-10.534165f,4.742272f,},
+                                            {10,0.996095f,8.492249f,-7.947677f,3.478917f,},
+                                            {13,1.079346f,8.894425f,-9.641768f,4.434442f,},
+                                            {15,0.994327f,7.441335f,-8.003979f,3.581177f,},
+                                            {17,0.991067f,7.208373f,-7.257859f,3.167774f,},
+                                            {20,1.033445f,7.476371f,-7.546960f,3.369703f,},
+                                            {25,0.982830f,5.913867f,-5.638448f,2.420932f,},
+                                            {30,0.928782f,5.035343f,-4.492104f,1.844904f,},
+                                            {40,0.953714f,5.060232f,-4.472204f,1.829642f,},
+                                            {50,0.899258f,4.273357f,-3.537492f,1.387576f,},
+                                            {60,0.943584f,4.093228f,-3.469658f,1.410911f,},
+                                            {70,0.926021f,3.973125f,-3.331985f,1.344690f,},
+                                            {75,0.894853f,2.871747f,-1.438758f,0.311856f,},
+                                            {80,0.935122f,2.991857f,-2.038882f,0.686395f,},
+                                            {90,0.953872f,2.880315f,-2.122365f,0.784032f,},
+                                            {100,0.951005f,2.894294f,-2.009086f,0.698316f,},
+};
+#endif
 /* End of file */
 
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
index 5f993bd..0658186 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
@@ -37,10 +37,19 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifndef HIGHER_FS
 extern const    LVM_UINT16  LVM_FsTable[];
 extern          LVM_UINT16  LVM_GetFsFromTable(LVM_Fs_en FsIndex);
-extern          LVM_INT32   LVREV_GainPolyTable[24][5];
+#else
+extern const    LVM_UINT32  LVM_FsTable[];
+extern          LVM_UINT32  LVM_GetFsFromTable(LVM_Fs_en FsIndex);
+#endif
 
+#ifndef BUILD_FLOAT
+extern          LVM_INT32   LVREV_GainPolyTable[24][5];
+#else
+extern          LVM_FLOAT   LVREV_GainPolyTable[24][5];
+#endif
 #ifdef __cplusplus
 }
 #endif
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
index a675cb2..2038fbb 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
@@ -216,11 +216,17 @@
 /*  otherwise           Error due to bad parameters                                                                              */
 /*                                                                                                                               */
 /*********************************************************************************************************************************/
+#ifdef BUILD_FLOAT
+LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
+                                       LVM_FLOAT           *pLVPSA_InputSamples,
+                                       LVM_UINT16           InputBlockSize,
+                                       LVPSA_Time           AudioTime             );
+#else
 LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
                                        LVM_INT16           *pLVPSA_InputSamples,
                                        LVM_UINT16           InputBlockSize,
                                        LVPSA_Time           AudioTime             );
-
+#endif
 /*********************************************************************************************************************************/
 /*                                                                                                                               */
 /* FUNCTION:            LVPSA_GetSpectrum                                                                                        */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
index cd5f69c..f6c4ea7 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
@@ -28,6 +28,15 @@
 LVPSA_RETURN LVPSA_SetQPFCoefficients( LVPSA_InstancePr_t        *pInst,
                                        LVPSA_ControlParams_t      *pParams  );
 
+#ifdef BUILD_FLOAT
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs(  LVM_UINT16             Fs,
+                                       LVPSA_FilterParam_t   *pFilterParams,
+                                       BP_FLOAT_Coefs_t        *pCoefficients);
+
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs(  LVM_UINT16            Fs,
+                                       LVPSA_FilterParam_t  *pFilterParams,
+                                       BP_FLOAT_Coefs_t       *pCoefficients);
+#else
 LVPSA_RETURN LVPSA_BPSinglePrecCoefs(  LVM_UINT16             Fs,
                                        LVPSA_FilterParam_t   *pFilterParams,
                                        BP_C16_Coefs_t        *pCoefficients);
@@ -39,7 +48,7 @@
 LVPSA_RETURN LVPSA_BPDoublePrecCoefs(  LVM_UINT16              Fs,
                                        LVPSA_FilterParam_t     *pFilterParams,
                                        BP_C32_Coefs_t          *pCoefficients);
-
+#endif
 LVPSA_RETURN LVPSA_SetBPFCoefficients( LVPSA_InstancePr_t        *pInst,
                                        LVPSA_ControlParams_t      *pParams  );
 
@@ -179,7 +188,11 @@
     LVM_UINT16 Freq;
     LVPSA_ControlParams_t   Params;
     extern LVM_INT16        LVPSA_nSamplesBufferUpdate[];
+#ifndef HIGHER_FS
     extern LVM_UINT16       LVPSA_SampleRateTab[];
+#else
+    extern LVM_UINT32       LVPSA_SampleRateTab[];
+#endif
     extern LVM_UINT16       LVPSA_DownSamplingFactor[];
 
 
@@ -267,8 +280,11 @@
 LVPSA_RETURN LVPSA_SetBPFiltersType (   LVPSA_InstancePr_t        *pInst,
                                         LVPSA_ControlParams_t      *pParams  )
 {
-
+#ifndef HIGHER_FS
     extern LVM_UINT16   LVPSA_SampleRateTab[];                                            /* Sample rate table */
+#else
+    extern LVM_UINT32   LVPSA_SampleRateTab[];                 /* Sample rate table */
+#endif
     LVM_UINT16          ii;                                                         /* Filter band index */
     LVM_UINT32          fs = (LVM_UINT32)LVPSA_SampleRateTab[(LVM_UINT16)pParams->Fs];      /* Sample rate */
     LVM_UINT32          fc;                                                         /* Filter centre frequency */
@@ -342,26 +358,42 @@
         {
             case    LVPSA_DoublePrecisionFilter:
             {
+#ifndef BUILD_FLOAT
                 BP_C32_Coefs_t      Coefficients;
 
                 /*
                  * Calculate the double precision coefficients
                  */
                 LVPSA_BPDoublePrecCoefs((LVM_UINT16)pParams->Fs,
-                                       &pInst->pFiltersParams[ii],
-                                       &Coefficients);
-
+                                        &pInst->pFiltersParams[ii],
+                                        &Coefficients);
                 /*
                  * Set the coefficients
                  */
                 BP_1I_D16F32Cll_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
                                                   &pInst->pBP_Taps[ii],
                                                   &Coefficients);
+#else
+                BP_FLOAT_Coefs_t      Coefficients;
+                /*
+                 * Calculate the double precision coefficients
+                 */
+                LVPSA_BPDoublePrecCoefs((LVM_UINT16)pParams->Fs,
+                                        &pInst->pFiltersParams[ii],
+                                        &Coefficients);
+                /*
+                 * Set the coefficients
+                 */
+                BP_1I_D16F32Cll_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
+                                                  &pInst->pBP_Taps[ii],
+                                                  &Coefficients);
+#endif
                 break;
             }
 
             case    LVPSA_SimplePrecisionFilter:
             {
+#ifndef BUILD_FLOAT
                 BP_C16_Coefs_t      Coefficients;
 
                 /*
@@ -374,9 +406,26 @@
                 /*
                  * Set the coefficients
                  */
-                BP_1I_D16F16Css_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
+                BP_1I_D16F16Css_TRC_WRA_01_Init (&pInst->pBP_Instances[ii],
                                                   &pInst->pBP_Taps[ii],
                                                   &Coefficients);
+#else
+                BP_FLOAT_Coefs_t      Coefficients;
+
+                /*
+                 * Calculate the single precision coefficients
+                 */
+                LVPSA_BPSinglePrecCoefs((LVM_UINT16)pParams->Fs,
+                                        &pInst->pFiltersParams[ii],
+                                        &Coefficients);
+
+                /*
+                 * Set the coefficients
+                 */
+                BP_1I_D16F16Css_TRC_WRA_01_Init (&pInst->pBP_Instances[ii],
+                                                  &pInst->pBP_Taps[ii],
+                                                  &Coefficients);
+#endif
                 break;
             }
         }
@@ -409,18 +458,31 @@
 {
     LVM_UINT16     ii;
     LVM_Fs_en      Fs = pParams->Fs;
+#ifndef BUILD_FLOAT
     QPD_C32_Coefs  *pCoefficients;
     extern         QPD_C32_Coefs     LVPSA_QPD_Coefs[];
 
-
     pCoefficients = &LVPSA_QPD_Coefs[(pParams->LevelDetectionSpeed * LVPSA_NR_SUPPORTED_RATE) + Fs];
+#else
+    QPD_FLOAT_Coefs  *pCoefficients;
+    extern         QPD_FLOAT_Coefs     LVPSA_QPD_Float_Coefs[];
+
+    pCoefficients = &LVPSA_QPD_Float_Coefs[(pParams->LevelDetectionSpeed * \
+                                    LVPSA_NR_SUPPORTED_RATE) + Fs];
+#endif
 
 
     for (ii = 0; ii < pInst->nRelevantFilters; ii++)
     {
-            LVPSA_QPD_Init (&pInst->pQPD_States[ii],
-                            &pInst->pQPD_Taps[ii],
-                            pCoefficients );
+#ifndef BUILD_FLOAT
+        LVPSA_QPD_Init (&pInst->pQPD_States[ii],
+                        &pInst->pQPD_Taps[ii],
+                        pCoefficients );
+#else
+        LVPSA_QPD_Init_Float (&pInst->pQPD_States[ii],
+                              &pInst->pQPD_Taps[ii],
+                              pCoefficients );
+#endif
     }
 
     return(LVPSA_OK);
@@ -460,6 +522,87 @@
 /*     of the n bands equalizer (LVEQNB                                                 */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs(    LVM_UINT16              Fs,
+                                         LVPSA_FilterParam_t     *pFilterParams,
+                                         BP_FLOAT_Coefs_t        *pCoefficients)
+{
+
+    extern LVM_FLOAT    LVPSA_Float_TwoPiOnFsTable[];
+    extern LVM_FLOAT    LVPSA_Float_CosCoef[];
+
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_FLOAT           T0;
+    LVM_FLOAT           D;
+    LVM_FLOAT           A0;
+    LVM_FLOAT           B1;
+    LVM_FLOAT           B2;
+    LVM_FLOAT           Dt0;
+    LVM_FLOAT           B2_Den;
+    LVM_FLOAT           B2_Num;
+    LVM_FLOAT           COS_T0;
+    LVM_FLOAT           coef;
+    LVM_FLOAT           factor;
+    LVM_FLOAT           t0;
+    LVM_INT16           i;
+
+
+    /*
+     * Get the filter definition
+     */
+    LVM_FLOAT          Frequency   = (LVM_FLOAT)(pFilterParams->CenterFrequency);
+    LVM_FLOAT          QFactor     = ((LVM_FLOAT)(pFilterParams->QFactor)) / 100;
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = Frequency * LVPSA_Float_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
+    D = 3200;                 /* Floating point value 1.000000 (1*100*2^5) */
+                    /* Force D = 1 : the function was originally used for a peaking filter.
+                       The D parameter do not exist for a BandPass filter coefficients */
+
+    /*
+     * Calculate the B2 coefficient
+     */
+    Dt0 =  T0 / 2048 ;
+    B2_Den = QFactor + Dt0;
+    B2_Num = Dt0 - QFactor;
+    B2 = B2_Num / (2 * B2_Den);
+
+    /*
+     * Calculate the cosine by a polynomial expansion using the equation:
+     *
+     *  Cos += coef(n) * t0^n                   For n = 0 to 6
+     */
+    T0 = (T0 / 2048) * 0.63658558f;              /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
+    t0 = T0 ;
+    factor = 1.0f;                            /* Initialise to 1.0 for the a0 coefficient */
+    COS_T0 = 0.0f;                                 /* Initialise the error to zero */
+    for (i = 1; i < 7; i++)
+    {
+        coef    = LVPSA_Float_CosCoef[i];                /* Get the nth coefficient */
+        COS_T0 += (factor * coef);         /* The nth partial sum */
+        factor  = (factor * t0) ;           /* Calculate t0^n */
+    }
+    COS_T0 = COS_T0 * 8;    /*LVPSA_CosCoef_float[0]*/      /* Correct the scaling */
+
+
+    B1 = ((LVM_FLOAT)0.5 - B2) * (COS_T0);    /* B1 = (0.5 - b2) * cos(t0) */
+    A0 = ((LVM_FLOAT)0.5 + B2) / 2;                        /* A0 = (0.5 + b2) / 2 */
+
+    /*
+     * Write coeff into the data structure
+     */
+    pCoefficients->A0 = A0 * 2;
+    pCoefficients->B1 = B1 * 2;
+    pCoefficients->B2 = B2 * 2;
+
+    return(LVPSA_OK);
+}
+#else
 LVPSA_RETURN LVPSA_BPSinglePrecCoefs(    LVM_UINT16              Fs,
                                          LVPSA_FilterParam_t    *pFilterParams,
                                          BP_C16_Coefs_t         *pCoefficients)
@@ -541,7 +684,7 @@
 
     return(LVPSA_OK);
 }
-
+#endif
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                 LVPSA_BPDoublePrecCoefs                                    */
@@ -584,6 +727,90 @@
 /*     of the n bands equalizer (LVEQNB                                                 */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BUILD_FLOAT
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs(   LVM_UINT16            Fs,
+                                        LVPSA_FilterParam_t   *pFilterParams,
+                                        BP_FLOAT_Coefs_t      *pCoefficients)
+{
+
+    extern LVM_FLOAT    LVPSA_Float_TwoPiOnFsTable[];
+    extern LVM_FLOAT    LVPSA_Float_DPCosCoef[];
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_FLOAT           T0;
+    LVM_FLOAT           D;
+    LVM_FLOAT           A0;
+    LVM_FLOAT           B1;
+    LVM_FLOAT           B2;
+    LVM_FLOAT           Dt0;
+    LVM_FLOAT           B2_Den;
+    LVM_FLOAT           B2_Num;
+    LVM_FLOAT           CosErr;
+    LVM_FLOAT           coef;
+    LVM_FLOAT           factor;
+    LVM_FLOAT           t0;
+    LVM_INT16           i;
+
+    /*
+     * Get the filter definition
+     */
+    LVM_FLOAT          Frequency   = (LVM_FLOAT)(pFilterParams->CenterFrequency);
+    LVM_FLOAT          QFactor     = ((LVM_FLOAT)(pFilterParams->QFactor)) / 100;
+
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = Frequency * LVPSA_Float_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
+    D = 3200;    /* Floating point value 1.000000 (1*100*2^5) */
+                 /* Force D = 1 : the function was originally used for a peaking filter.
+                    The D parameter do not exist for a BandPass filter coefficients */
+
+    /*
+     * Calculate the B2 coefficient
+     */
+    Dt0 =  T0 / 2048 ;
+    B2_Den = QFactor + Dt0;
+    B2_Num = Dt0 - QFactor;
+    B2 = B2_Num / (2 * B2_Den);
+
+    /*
+     * Calculate the cosine error by a polynomial expansion using the equation:
+     *
+     *  CosErr += coef(n) * t0^n                For n = 0 to 4
+     */
+    T0 = T0 * 0.994750f;                    /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
+    t0 = T0;
+    factor = 1.0f;                            /* Initialise to 1.0 for the a0 coefficient */
+    CosErr = 0.0f;                                 /* Initialise the error to zero */
+    for (i = 1; i < 5; i++)
+    {
+        coef = LVPSA_Float_DPCosCoef[i];              /* Get the nth coefficient */
+        CosErr += factor * coef;         /* The nth partial sum */
+        factor = factor * t0;           /* Calculate t0^n */
+    }
+    CosErr = CosErr * 2;          /* Correct the scaling */
+
+    /*
+     * Calculate the B1 and A0 coefficients
+     */
+    B1 = ((LVM_FLOAT)0.5 - B2);                     /* B1 = (0.5 - b2) */
+    A0 = B1 * CosErr ;    /* Temporary storage for (0.5 - b2) * coserr(t0) */
+    B1 -= A0;                                   /* B1 = (0.5 - b2) * (1 - coserr(t0))  */
+    A0 = ((LVM_FLOAT)0.5  + B2) / 2;                /* A0 = (0.5 + b2) / 2 */
+
+    /*
+     * Write coeff into the data structure
+     */
+    pCoefficients->A0 = A0;
+    pCoefficients->B1 = B1;
+    pCoefficients->B2 = B2;
+
+    return(LVPSA_OK);
+}
+#else
 LVPSA_RETURN LVPSA_BPDoublePrecCoefs(   LVM_UINT16            Fs,
                                         LVPSA_FilterParam_t  *pFilterParams,
                                         BP_C32_Coefs_t       *pCoefficients)
@@ -666,7 +893,7 @@
 
     return(LVPSA_OK);
 }
-
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:            LVPSA_ClearFilterHistory                                    */
@@ -690,11 +917,17 @@
 
     /* Band Pass filters taps */
     pTapAddress = (LVM_INT8 *)pInst->pBP_Taps;
+#ifdef BUILD_FLOAT
+    for(i = 0; i < pInst->nBands * sizeof(Biquad_1I_Order2_FLOAT_Taps_t); i++)
+    {
+        pTapAddress[i] = 0;
+    }
+#else
     for(i = 0; i < pInst->nBands * sizeof(Biquad_1I_Order2_Taps_t); i++)
     {
         pTapAddress[i] = 0;
     }
-
+#endif
     /* Quasi-peak filters taps */
     pTapAddress = (LVM_INT8 *)pInst->pQPD_Taps;
     for(i = 0; i < pInst->nBands * sizeof(QPD_Taps_t); i++)
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
index 27a4bc3..1c26860 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
@@ -47,7 +47,11 @@
     LVPSA_InstancePr_t          *pLVPSA_Inst;
     LVPSA_RETURN                errorCode       = LVPSA_OK;
     LVM_UINT32                  ii;
+#ifndef BUILD_FLOAT
     extern LVM_INT16            LVPSA_GainTable[];
+#else
+    extern LVM_FLOAT            LVPSA_Float_GainTable[];
+#endif
     LVM_UINT32                  BufferLength = 0;
 
     /* Ints_Alloc instances, needed for memory alignment management */
@@ -141,19 +145,37 @@
 
 
     /* Assign the pointers */
-
+#ifndef BUILD_FLOAT
     pLVPSA_Inst->pPostGains                 = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
+#else
+    pLVPSA_Inst->pPostGains             = InstAlloc_AddMember( &Instance, pInitParams->nBands * \
+                                                               sizeof(LVM_FLOAT) );
+#endif
     pLVPSA_Inst->pFiltersParams             = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
     pLVPSA_Inst->pSpectralDataBufferStart   = InstAlloc_AddMember( &Instance, pInitParams->nBands * pLVPSA_Inst->SpectralDataBufferLength * sizeof(LVM_UINT8) );
     pLVPSA_Inst->pPreviousPeaks             = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
     pLVPSA_Inst->pBPFiltersPrecision        = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
-
+#ifndef BUILD_FLOAT
     pLVPSA_Inst->pBP_Instances          = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
     pLVPSA_Inst->pQPD_States            = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
+#else
+    pLVPSA_Inst->pBP_Instances          = InstAlloc_AddMember( &Coef, pInitParams->nBands * \
+                                                               sizeof(Biquad_FLOAT_Instance_t) );
+    pLVPSA_Inst->pQPD_States            = InstAlloc_AddMember( &Coef, pInitParams->nBands * \
+                                                               sizeof(QPD_FLOAT_State_t) );
+#endif
 
+#ifndef BUILD_FLOAT
     pLVPSA_Inst->pBP_Taps               = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
     pLVPSA_Inst->pQPD_Taps              = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
 
+#else
+    pLVPSA_Inst->pBP_Taps               = InstAlloc_AddMember( &Data,
+                                                               pInitParams->nBands * \
+                                                               sizeof(Biquad_1I_Order2_FLOAT_Taps_t));
+    pLVPSA_Inst->pQPD_Taps              = InstAlloc_AddMember( &Data, pInitParams->nBands * \
+                                                               sizeof(QPD_FLOAT_Taps_t) );
+#endif
 
     /* Copy filters parameters in the private instance */
     for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
@@ -164,7 +186,12 @@
     /* Set Post filters gains*/
     for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
     {
+#ifndef BUILD_FLOAT
         pLVPSA_Inst->pPostGains[ii] =(LVM_UINT16) LVPSA_GainTable[pInitParams->pFiltersParams[ii].PostGain + 15];
+#else
+        pLVPSA_Inst->pPostGains[ii] = LVPSA_Float_GainTable[15 + \
+                                                        pInitParams->pFiltersParams[ii].PostGain];
+#endif
     }
     pLVPSA_Inst->pSpectralDataBufferWritePointer = pLVPSA_Inst->pSpectralDataBufferStart;
 
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
index 0984b10..06a8f9d 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
@@ -106,7 +106,11 @@
          */
 
         InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
+#ifdef BUILD_FLOAT
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_FLOAT) );
+#else
         InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
+#endif
         InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
 
         {
@@ -134,7 +138,11 @@
         /*
          * Scratch memory
          */
+#ifndef BUILD_FLOAT
         InstAlloc_AddMember( &Scratch, 2 * pInitParams->MaxInputBlockSize * sizeof(LVM_INT16) );
+#else
+        InstAlloc_AddMember( &Scratch, 2 * pInitParams->MaxInputBlockSize * sizeof(LVM_FLOAT) );
+#endif
         pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Size         = InstAlloc_GetTotal(&Scratch);
         pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Type         = LVPSA_SCRATCH;
         pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
@@ -142,8 +150,13 @@
         /*
          * Persistent coefficients memory
          */
+#ifndef BUILD_FLOAT
         InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
         InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
+#else
+        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_FLOAT_Instance_t) );
+        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_FLOAT_State_t) );
+#endif
         pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Size         = InstAlloc_GetTotal(&Coef);
         pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Type         = LVPSA_PERSISTENT_COEF;
         pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
@@ -151,8 +164,13 @@
         /*
          * Persistent data memory
          */
+#ifndef BUILD_FLOAT
         InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
         InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
+#else
+        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_FLOAT_Taps_t) );
+        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_FLOAT_Taps_t) );
+#endif
         pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Size         = InstAlloc_GetTotal(&Data);
         pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Type         = LVPSA_PERSISTENT_DATA;
         pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
index 03522fb..a750bb0 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -43,8 +43,11 @@
 #define LVPSA_MEMREGION_PERSISTENT_COEF  1      /* Offset to persistent coefficients  memory region in memory table */
 #define LVPSA_MEMREGION_PERSISTENT_DATA  2      /* Offset to persistent taps  memory region in memory table         */
 #define LVPSA_MEMREGION_SCRATCH          3      /* Offset to scratch  memory region in memory table                 */
-
-#define LVPSA_NR_SUPPORTED_RATE          9      /* From 8000Hz to 48000Hz                                           */
+#ifndef HIGHER_FS
+#define LVPSA_NR_SUPPORTED_RATE          9      /* From 8000Hz to 48000Hz*/
+#else
+#define LVPSA_NR_SUPPORTED_RATE          11      /* From 8000Hz to 192000Hz*/
+#endif
 #define LVPSA_NR_SUPPORTED_SPEED         3      /* LOW, MEDIUM, HIGH                                                */
 
 #define LVPSA_MAXBUFFERDURATION          4000   /* Maximum length in ms of the levels buffer                        */
@@ -93,12 +96,27 @@
     LVPSA_MemTab_t              MemoryTable;
 
     LVPSA_BPFilterPrecision_en *pBPFiltersPrecision;                /* Points a nBands elements array that contains the filter precision for each band              */
+#ifndef BUILD_FLOAT
     Biquad_Instance_t          *pBP_Instances;                      /* Points a nBands elements array that contains the band pass filter instance for each band     */
     Biquad_1I_Order2_Taps_t    *pBP_Taps;                           /* Points a nBands elements array that contains the band pass filter taps for each band         */
     QPD_State_t                *pQPD_States;                        /* Points a nBands elements array that contains the QPD filter instance for each band           */
     QPD_Taps_t                 *pQPD_Taps;                          /* Points a nBands elements array that contains the QPD filter taps for each band               */
-    LVM_UINT16                 *pPostGains;                         /* Points a nBands elements array that contains the post-filter gains for each band             */
+#else
+    Biquad_FLOAT_Instance_t          *pBP_Instances;
+    /* Points a nBands elements array that contains the band pass filter taps for each band */
+    Biquad_1I_Order2_FLOAT_Taps_t    *pBP_Taps;
+    /* Points a nBands elements array that contains the QPD filter instance for each band */
+    QPD_FLOAT_State_t                *pQPD_States;
+    /* Points a nBands elements array that contains the QPD filter taps for each band */
+    QPD_FLOAT_Taps_t                 *pQPD_Taps;
+#endif
 
+#ifndef BUILD_FLOAT
+    LVM_UINT16                 *pPostGains;                         /* Points a nBands elements array that contains the post-filter gains for each band             */
+#else
+    /* Points a nBands elements array that contains the post-filter gains for each band */
+    LVM_FLOAT                  *pPostGains;
+#endif
     LVPSA_FilterParam_t        *pFiltersParams;                     /* Copy of the filters parameters from the input parameters                                     */
 
 
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
index 9e29f68..ea5f74a 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
@@ -43,6 +43,96 @@
 /*  otherwise           Error due to bad parameters                                 */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
+                                       LVM_FLOAT           *pLVPSA_InputSamples,
+                                       LVM_UINT16           InputBlockSize,
+                                       LVPSA_Time           AudioTime            )
+
+{
+    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+    LVM_FLOAT               *pScratch;
+    LVM_INT16               ii;
+    LVM_INT32               AudioTimeInc;
+    extern LVM_UINT32       LVPSA_SampleRateInvTab[];
+    LVM_UINT8               *pWrite_Save;         /* Position of the write pointer
+                                                     at the beginning of the process  */
+
+    /******************************************************************************
+       CHECK PARAMETERS
+    *******************************************************************************/
+    if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+    if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
+    {
+        return(LVPSA_ERROR_INVALIDPARAM);
+    }
+
+    pScratch = (LVM_FLOAT*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
+    pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+
+    /******************************************************************************
+       APPLY NEW SETTINGS IF NEEDED
+    *******************************************************************************/
+    if (pLVPSA_Inst->bControlPending == LVM_TRUE)
+    {
+        pLVPSA_Inst->bControlPending = 0;
+        LVPSA_ApplyNewSettings( pLVPSA_Inst);
+    }
+
+    /******************************************************************************
+       PROCESS SAMPLES
+    *******************************************************************************/
+    /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
+    Copy_Float(pLVPSA_InputSamples, pScratch, (LVM_INT16)InputBlockSize);
+    Shift_Sat_Float(-1, pScratch, pScratch, (LVM_INT16)InputBlockSize);
+
+    for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
+    {
+        switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
+        {
+            case LVPSA_SimplePrecisionFilter:
+                BP_1I_D16F16C14_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
+                                              pScratch,
+                                              pScratch + InputBlockSize,
+                                              (LVM_INT16)InputBlockSize);
+                break;
+
+            case LVPSA_DoublePrecisionFilter:
+                BP_1I_D16F32C30_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
+                                              pScratch,
+                                              pScratch + InputBlockSize,
+                                              (LVM_INT16)InputBlockSize);
+                break;
+            default:
+                break;
+        }
+
+
+        LVPSA_QPD_Process_Float   ( pLVPSA_Inst,
+                                    pScratch + InputBlockSize,
+                                    (LVM_INT16)InputBlockSize,
+                                    ii);
+    }
+
+    /******************************************************************************
+       UPDATE SpectralDataBufferAudioTime
+    *******************************************************************************/
+
+    if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
+    {
+        MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)),
+                        (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
+                        AudioTimeInc,
+                        LVPSA_FsInvertShift)
+        pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
+    }
+
+    return(LVPSA_OK);
+}
+#else
 LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
                                        LVM_INT16           *pLVPSA_InputSamples,
                                        LVM_UINT16           InputBlockSize,
@@ -130,7 +220,7 @@
 
     return(LVPSA_OK);
 }
-
+#endif
 
 /************************************************************************************/
 /*                                                                                  */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
index 836bfd7..99d844b 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
@@ -31,6 +31,15 @@
   LVM_INT32                            Coefs[2];       /* pointer to the filter coefficients */
 }QPD_State_t, *pQPD_State_t;
 
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    /* pointer to the delayed samples (data of 32 bits)   */
+    LVM_FLOAT                            *pDelay;
+    LVM_FLOAT                            Coefs[2];       /* pointer to the filter coefficients */
+}QPD_FLOAT_State_t, *pQPD_FLOAT_State_t;
+#endif
+
 typedef struct
 {
     LVM_INT32 KP;    /*should store a0*/
@@ -38,12 +47,30 @@
 
 } QPD_C32_Coefs, *PQPD_C32_Coefs;
 
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT KP;    /*should store a0*/
+    LVM_FLOAT KM;    /*should store b2*/
+
+} QPD_FLOAT_Coefs, *PQPD_FLOAT_Coefs;
+#endif
+
+
 typedef struct
 {
     LVM_INT32 Storage[1];
 
 } QPD_Taps_t, *pQPD_Taps_t;
 
+#ifdef BUILD_FLOAT
+typedef struct
+{
+    LVM_FLOAT Storage[1];
+
+} QPD_FLOAT_Taps_t, *pQPD_FLOAT_Taps_t;
+
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:            LVPSA_QPD_Process                                           */
@@ -62,6 +89,12 @@
                                     LVM_INT16                           numSamples,
                                     LVM_INT16                           BandIndex);
 
+#ifdef BUILD_FLOAT
+void LVPSA_QPD_Process_Float (      void                               *hInstance,
+                                    LVM_FLOAT                          *pInSamps,
+                                    LVM_INT16                           numSamples,
+                                    LVM_INT16                           BandIndex);
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:            LVPSA_QPD_Init                                              */
@@ -80,8 +113,12 @@
 void LVPSA_QPD_Init (   QPD_State_t       *pInstance,
                         QPD_Taps_t        *pTaps,
                         QPD_C32_Coefs     *pCoef     );
+#ifdef BUILD_FLOAT
 
-
+void LVPSA_QPD_Init_Float (   QPD_FLOAT_State_t       *pInstance,
+                              QPD_FLOAT_Taps_t        *pTaps,
+                              QPD_FLOAT_Coefs         *pCoef     );
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
index 50e0a80..2cc32ab 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
@@ -40,3 +40,14 @@
     pQPD_State->Coefs[0]  = pCoef->KP;
     pQPD_State->Coefs[1]  = pCoef->KM;
 }
+
+#ifdef BUILD_FLOAT
+void LVPSA_QPD_Init_Float (   pQPD_FLOAT_State_t       pQPD_State,
+                              QPD_FLOAT_Taps_t         *pTaps,
+                              QPD_FLOAT_Coefs          *pCoef     )
+{
+    pQPD_State->pDelay  = pTaps->Storage;
+    pQPD_State->Coefs[0]  = ((LVM_FLOAT)pCoef->KP);
+    pQPD_State->Coefs[1]  = ((LVM_FLOAT)pCoef->KM);
+}
+#endif
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
index 67197c1..e233172 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
@@ -35,12 +35,16 @@
 /*                                                                                  */
 /************************************************************************************/
 void LVPSA_QPD_WritePeak(   pLVPSA_InstancePr_t       pLVPSA_Inst,
-                            LVM_UINT8             **ppWrite,
-                            LVM_INT16               BandIndex,
-                            LVM_INT16               Value   );
+                            LVM_UINT8                 **ppWrite,
+                            LVM_INT16                 BandIndex,
+                            LVM_INT16                 Value   );
 
-
-
+#ifdef BUILD_FLOAT
+void LVPSA_QPD_WritePeak_Float(   pLVPSA_InstancePr_t       pLVPSA_Inst,
+                                  LVM_UINT8             **ppWrite,
+                                  LVM_INT16               BandIndex,
+                                  LVM_FLOAT               Value   );
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:            LVPSA_QPD_Process                                           */
@@ -54,6 +58,7 @@
 /* RETURNS:             void                                                        */
 /*                                                                                  */
 /************************************************************************************/
+#ifndef BUILD_FLOAT
 void LVPSA_QPD_Process (            void                               *hInstance,
                                     LVM_INT16                          *pInSamps,
                                     LVM_INT16                           numSamples,
@@ -173,7 +178,131 @@
         pLVPSA_Inst->DownSamplingCount = (LVM_UINT16)(-ii);
     }
 }
+#else
+void LVPSA_QPD_Process_Float (      void                               *hInstance,
+                                    LVM_FLOAT                          *pInSamps,
+                                    LVM_INT16                           numSamples,
+                                    LVM_INT16                           BandIndex)
+{
 
+    /******************************************************************************
+       PARAMETERS
+    *******************************************************************************/
+    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+    QPD_FLOAT_State_t *pQPDState =  (QPD_FLOAT_State_t*)&pLVPSA_Inst->pQPD_States[BandIndex];
+
+    /* Pointer to taps */
+    LVM_FLOAT* pDelay  = pQPDState->pDelay;
+
+    /* Parameters needed during quasi peak calculations */
+    LVM_FLOAT   X0;
+    LVM_FLOAT   temp,temp2;
+    LVM_FLOAT   accu;
+    LVM_FLOAT   Xg0;
+    LVM_FLOAT   D0;
+    LVM_FLOAT   V0 = (LVM_FLOAT)(*pDelay);
+
+    /* Filter's coef */
+    LVM_FLOAT   Kp = ((LVM_FLOAT)(pQPDState->Coefs[0]));
+    LVM_FLOAT   Km = ((LVM_FLOAT)(pQPDState->Coefs[1]));
+
+    LVM_INT16   ii = numSamples;
+
+    LVM_UINT8  *pWrite = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+    LVM_INT32   BufferUpdateSamplesCount = pLVPSA_Inst->BufferUpdateSamplesCount;
+    LVM_UINT16  DownSamplingFactor = pLVPSA_Inst->DownSamplingFactor;
+
+    /******************************************************************************
+       INITIALIZATION
+    *******************************************************************************/
+    /* Correct the pointer to take the first down sampled signal sample */
+    pInSamps += pLVPSA_Inst->DownSamplingCount;
+    /* Correct also the number of samples */
+    ii = (LVM_INT16)(ii - (LVM_INT16)pLVPSA_Inst->DownSamplingCount);
+
+    while (ii > 0)
+    {
+        /* Apply post gain */
+        /* - 1 to compensate scaling in process function*/
+        X0 = (*pInSamps) * pLVPSA_Inst->pPostGains[BandIndex];
+        pInSamps = pInSamps + DownSamplingFactor;
+
+        /* Saturate and take absolute value */
+        if(X0 < 0.0f)
+            X0 = -X0;
+        if (X0 > 1.0f)
+            Xg0 = 1.0f;
+        else
+            Xg0 =X0;
+
+
+        /* Quasi peak filter calculation */
+        D0  = Xg0 - V0;
+
+        temp2 = D0;
+
+        accu = temp2 * Kp;
+        D0    = D0 / 2.0f;
+        if (D0 < 0.0f){
+            D0 = -D0;
+        }
+
+        temp2 = D0;
+
+        temp = D0 * Km;
+        accu += temp + Xg0;
+
+        if (accu > 1.0f)
+            accu = 1.0f;
+        else if(accu < 0.0f)
+            accu = 0.0f;
+
+        V0 = accu;
+
+        if(((pLVPSA_Inst->nSamplesBufferUpdate - BufferUpdateSamplesCount) < DownSamplingFactor))
+        {
+            LVPSA_QPD_WritePeak_Float( pLVPSA_Inst,
+                                       &pWrite,
+                                       BandIndex,
+                                       V0);
+
+            BufferUpdateSamplesCount -= pLVPSA_Inst->nSamplesBufferUpdate;
+            pLVPSA_Inst->LocalSamplesCount = (LVM_UINT16)(numSamples - ii);
+        }
+        BufferUpdateSamplesCount += DownSamplingFactor;
+
+        ii = (LVM_INT16)(ii - DownSamplingFactor);
+
+    }
+
+    /* Store last taps in memory */
+    *pDelay = V0;
+
+    /* If this is the last call to the function after last band processing,
+       update the parameters. */
+    if(BandIndex == (pLVPSA_Inst->nRelevantFilters - 1))
+    {
+        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+        /* Adjustment for 11025Hz input, 220,5 is normally
+           the exact number of samples for 20ms.*/
+        if((pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite)&&
+                                        (pLVPSA_Inst->CurrentParams.Fs == LVM_FS_11025))
+        {
+            if(pLVPSA_Inst->nSamplesBufferUpdate == 220)
+            {
+                pLVPSA_Inst->nSamplesBufferUpdate = 221;
+            }
+            else
+            {
+                pLVPSA_Inst->nSamplesBufferUpdate = 220;
+            }
+        }
+        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+        pLVPSA_Inst->BufferUpdateSamplesCount = BufferUpdateSamplesCount;
+        pLVPSA_Inst->DownSamplingCount = (LVM_UINT16)(-ii);
+    }
+}
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:            LVPSA_QPD_WritePeak                                         */
@@ -209,4 +338,23 @@
     *ppWrite = pWrite;
 
 }
+#ifdef BUILD_FLOAT
+void LVPSA_QPD_WritePeak_Float(   pLVPSA_InstancePr_t     pLVPSA_Inst,
+                                  LVM_UINT8               **ppWrite,
+                                  LVM_INT16               BandIndex,
+                                  LVM_FLOAT               Value   )
+{
+    LVM_UINT8 *pWrite = *ppWrite;
 
+    /* Write the value and update the write pointer */
+    *(pWrite + BandIndex) = (LVM_UINT8)(Value * 256);
+    pWrite += pLVPSA_Inst->nBands;
+    if (pWrite == (pLVPSA_Inst->pSpectralDataBufferStart + pLVPSA_Inst->nBands * \
+                                    pLVPSA_Inst->SpectralDataBufferLength))
+    {
+        pWrite = pLVPSA_Inst->pSpectralDataBufferStart;
+    }
+
+    *ppWrite = pWrite;
+}
+#endif
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
index 21a5d8d..1287503 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
@@ -34,6 +34,7 @@
  * Sample rate table for converting between the enumerated type and the actual
  * frequency
  */
+#ifndef HIGHER_FS
 const LVM_UINT16    LVPSA_SampleRateTab[] = {   8000,                    /* 8kS/s  */
                                                 11025,
                                                 12000,
@@ -43,6 +44,19 @@
                                                 32000,
                                                 44100,
                                                 48000};                  /* 48kS/s */
+#else
+const LVM_UINT32    LVPSA_SampleRateTab[] = {   8000,                    /* 8kS/s  */
+                                                11025,
+                                                12000,
+                                                16000,
+                                                22050,
+                                                24000,
+                                                32000,
+                                                44100,
+                                                48000,
+                                                96000,
+                                               192000};                  /* 192kS/s */
+#endif
 
 /************************************************************************************/
 /*                                                                                  */
@@ -62,7 +76,12 @@
                                                     89478,
                                                     67109,
                                                     48696,
-                                                    44739};                  /* 48kS/s */
+                                                    44739
+#ifdef HIGHER_FS
+                                                    ,22369
+                                                    ,11185                  /* 192kS/s */
+#endif
+                                               };
 
 
 
@@ -84,7 +103,12 @@
                                                         480,
                                                         640,
                                                         882,
-                                                        960};                  /* 48kS/s */
+                                                        960
+#ifdef HIGHER_FS
+                                                        ,1920
+                                                        ,3840                  /* 192kS/s */
+#endif
+                                                    };
 /************************************************************************************/
 /*                                                                                  */
 /*  Down sampling factors                                                           */
@@ -102,7 +126,12 @@
                                                         16,                   /* 24000 S/s  */
                                                         21,                   /* 32000 S/s  */
                                                         30,                   /* 44100 S/s  */
-                                                        32};                  /* 48000 S/s  */
+                                                        32                    /* 48000 S/s  */
+#ifdef HIGHER_FS
+                                                       ,64                   /* 96000 S/s  */
+                                                       ,128                  /*192000 S/s  */
+#endif
+                                                  };
 
 
 /************************************************************************************/
@@ -122,8 +151,30 @@
                                                  8785,
                                                  6588,
                                                  4781,
-                                                 4392};    /* 48kS/s */
+                                                 4392
+#ifdef HIGHER_FS
+                                                ,2196
+                                                ,1098    /* 192kS/s */
+#endif
+                                             };
 
+#ifdef BUILD_FLOAT
+const LVM_FLOAT     LVPSA_Float_TwoPiOnFsTable[] = {  0.8042847f,      /* 8kS/s */
+                                                      0.5836054f,
+                                                      0.5361796f,
+                                                      0.4021423f,
+                                                      0.2917874f,
+                                                      0.2681051f,
+                                                      0.2010559f,
+                                                      0.1459089f,
+                                                      0.1340372f
+#ifdef HIGHER_FS
+                                                     ,0.0670186f
+                                                     ,0.0335093f    /* 192kS/s */
+#endif
+                                                   };
+
+#endif
 /*
  * Gain table
  */
@@ -159,6 +210,39 @@
                                             10264,
                                             11576};        /* +15dB gain */
 
+#ifdef BUILD_FLOAT
+const LVM_FLOAT  LVPSA_Float_GainTable[]={  0.177734375f,          /* -15dB gain */
+                                            0.199218750f,
+                                            0.223632812f,
+                                            0.250976562f,
+                                            0.281738281f,
+                                            0.315917968f,
+                                            0.354492187f,
+                                            0.397949218f,
+                                            0.446289062f,
+                                            0.500976562f,
+                                            0.562011718f,
+                                            0.630859375f,
+                                            0.707519531f,
+                                            0.793945312f,
+                                            0.891113281f,
+                                            1.000000000f,         /* 0dB gain */
+                                            1.121582031f,
+                                            1.258789062f,
+                                            1.412109375f,
+                                            1.584472656f,
+                                            1.777832031f,
+                                            2.000000000f,
+                                            2.238281250f,
+                                            2.511718750f,
+                                            2.818359375f,
+                                            3.162109375f,
+                                            3.547851562f,
+                                            3.980957031f,
+                                            4.466796875f,
+                                            5.011718750f,
+                                            5.652343750f};        /* +15dB gain */
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /*  Cosone polynomial coefficients                                                  */
@@ -181,7 +265,15 @@
                                         -2671,                         /* a3 */
                                         23730,                         /* a4 */
                                         -9490};                        /* a5 */
-
+#ifdef BUILD_FLOAT
+const LVM_FLOAT     LVPSA_Float_CosCoef[] = { 3,                             /* Shifts */
+                                              0.1250038f,                          /* a0 */
+                                              -0.0010986f,                           /* a1 */
+                                              -0.6019775f,                        /* a2 */
+                                              -0.0815149f,                         /* a3 */
+                                              0.7242042f,                         /* a4 */
+                                              -0.2896206f};                        /* a5 */
+#endif
 /*
  * Coefficients for calculating the cosine error with the equation:
  *
@@ -201,7 +293,13 @@
                                             -6,                          /* a1 */
                                             16586,                       /* a2 */
                                             -44};                        /* a3 */
-
+#ifdef BUILD_FLOAT
+const LVM_FLOAT    LVPSA_Float_DPCosCoef[] = {1.0f,                        /* Shifts */
+                                              0.0f,                        /* a0 */
+                                              -0.00008311f,                 /* a1 */
+                                              0.50617999f,                 /* a2 */
+                                              -0.00134281f};                /* a3 */
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /*  Quasi peak filter coefficients table                                            */
@@ -239,3 +337,54 @@
                                          {0xA375B2C6,0x1E943BBC},
                                          {0xA2E1E950,0x1E2A532E}}; /* 48kS/s */
 
+#ifdef BUILD_FLOAT
+const QPD_FLOAT_Coefs     LVPSA_QPD_Float_Coefs[] = {
+
+                                         /* 8kS/s  */    /* LVPSA_SPEED_LOW   */
+                                         {-0.9936831989325583f,0.0062135565094650f},
+                                         {-0.9935833332128823f,0.0063115493394434f},
+                                         {-0.9932638457976282f,0.0066249934025109f},
+                                         {-0.9936831989325583f,0.0062135565094650f},
+                                         {-0.9931269618682563f,0.0067592649720609f},
+                                         {-0.9932638457976282f,0.0066249934025109f},
+                                         {-0.9933686633594334f,0.0065221670083702f},
+                                         {-0.9931269618682563f,0.0067592649720609f},
+                                          /* 48kS/s */
+                                         {-0.9932638457976282f,0.0066249934025109f},
+#ifdef HIGHER_FS
+                                         {-0.9932638457976282f,0.0066249934025109f},
+                                         {-0.9932638457976282f,0.0066249934025109f},
+#endif
+                                         /* 8kS/s  */    /* LVPSA_SPEED_MEDIUM      */
+                                         {-0.9568079425953329f,0.0418742666952312f},
+                                         {-0.9561413046903908f,0.0425090822391212f},
+                                         {-0.9540119562298059f,0.0445343819446862f},
+                                         {-0.9568079425953329f,0.0418742666952312f},
+                                         {-0.9531011912040412f,0.0453995238058269f},
+                                         {-0.9540119562298059f,0.0445343819446862f},
+                                         {-0.9547099955379963f,0.0438708555884659f},
+                                          //{0x8600C7B9,0x05CFA6CF},
+                                         {-0.9531011912040412f,0.0453995238058269f},
+                                          /* 48kS/s */
+                                         {-0.9540119562298059f,0.0445343819446862f},
+#ifdef HIGHER_FS
+                                         {-0.9540119562298059f,0.0445343819446862f},
+                                         {-0.9540119562298059f,0.0445343819446862f},
+#endif
+                                          /* 8kS/s  */   /* LVPSA_SPEED_HIGH      */
+                                         {-0.7415186790749431f,0.2254409026354551f},
+                                         {-0.7381451204419136f,0.2279209652915597f},
+                                         {-0.7274807319045067f,0.2356666540727019f},
+                                         {-0.7415186790749431f,0.2254409026354551f},
+                                         {-0.7229706319049001f,0.2388987224549055f},
+                                         {-0.7274807319045067f,0.2356666540727019f},
+                                         {-0.7309581353329122f,0.2331568226218224f},
+                                         {-0.7229706319049001f,0.2388987224549055f},
+                                           /* 48kS/s */
+                                         {-0.7274807319045067f,0.2356666540727019f}
+#ifdef HIGHER_FS
+                                        ,{-0.7274807319045067f,0.2356666540727019f}
+                                        ,{-0.7274807319045067f,0.2356666540727019f}
+#endif
+                                        };
+#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
index 0d62274..e75695e 100644
--- a/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
+++ b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
@@ -374,12 +374,17 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
-
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
+                                  const LVM_FLOAT           *pInData,
+                                  LVM_FLOAT                 *pOutData,
+                                  LVM_UINT16                NumSamples);
+#else
 LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
                                   const LVM_INT16           *pInData,
                                   LVM_INT16                 *pOutData,
                                   LVM_UINT16                NumSamples);
-
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
index 3e48c7e..29e3c9e 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
@@ -70,11 +70,17 @@
 {
 
     LVM_UINT16          Offset;
+#ifndef BUILD_FLOAT
     LVM_UINT32          Gain;
+    LVM_INT32           Current;
+#else
+    LVM_FLOAT           Gain;
+    LVM_FLOAT           Current;
+#endif
     LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
     LVCS_BypassMix_t    *pConfig   = (LVCS_BypassMix_t *)&pInstance->BypassMix;
     const Gain_t        *pOutputGainTable;
-    LVM_INT32           Current;
+
 
 
     /*
@@ -85,7 +91,11 @@
         && (pInstance->MSTarget1 != 0x7FFF) /* this indicates an off->on transtion */
         )
     {
+#ifndef BUILD_FLOAT
         pInstance->TransitionGain = pParams->EffectLevel;
+#else
+        pInstance->TransitionGain = ((LVM_FLOAT)pParams->EffectLevel / 32767);
+#endif
     }
     else
     {
@@ -102,23 +112,46 @@
     /*
      * Setup the mixer gain for the processed path
      */
+#ifndef BUILD_FLOAT
     Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * pInstance->TransitionGain);
+#else
+    Gain =  (LVM_FLOAT)(pOutputGainTable[Offset].Loss * pInstance->TransitionGain);
+#endif
 
     pConfig->Mixer_Instance.MixerStream[0].CallbackParam = 0;
     pConfig->Mixer_Instance.MixerStream[0].pCallbackHandle = LVM_NULL;
     pConfig->Mixer_Instance.MixerStream[0].pCallBack = LVM_NULL;
     pConfig->Mixer_Instance.MixerStream[0].CallbackSet=1;
+
+#ifndef BUILD_FLOAT
     Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[0]);
     LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[0],(LVM_INT32)(Gain >> 15),Current);
     LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+#else
+    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[0]);
+    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[0], (LVM_FLOAT)(Gain), Current);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],
+                                       LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+#endif
+
     /*
      * Setup the mixer gain for the unprocessed path
      */
+#ifndef BUILD_FLOAT
     Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * (0x7FFF - pInstance->TransitionGain));
     Gain = (LVM_UINT32)pOutputGainTable[Offset].UnprocLoss * (Gain >> 15);
     Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[1]);
     LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[1],(LVM_INT32)(Gain >> 15),Current);
     LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+#else
+    Gain = (LVM_FLOAT)(pOutputGainTable[Offset].Loss * (1.0 - \
+                                    (LVM_FLOAT)pInstance->TransitionGain));
+    Gain = (LVM_FLOAT)pOutputGainTable[Offset].UnprocLoss * Gain;
+    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[1]);
+    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[1], (LVM_FLOAT)(Gain), Current);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],
+                                       LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+#endif
     pConfig->Mixer_Instance.MixerStream[1].CallbackParam = 0;
     pConfig->Mixer_Instance.MixerStream[1].pCallbackHandle = hInstance;
     pConfig->Mixer_Instance.MixerStream[1].CallbackSet=1;
@@ -134,7 +167,7 @@
      * Correct gain for the effect level
      */
     {
-
+#ifndef BUILD_FLOAT
         LVM_INT16           GainCorrect;
         LVM_INT32           Gain1;
         LVM_INT32           Gain2;
@@ -172,6 +205,43 @@
         LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
         LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[1],Gain2>>16);
         LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+#else
+        LVM_FLOAT           GainCorrect;
+        LVM_FLOAT           Gain1;
+        LVM_FLOAT           Gain2;
+
+        Gain1 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[0]);
+        Gain2 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[1]);
+        /*
+         * Calculate the gain correction
+         */
+        if (pInstance->Params.CompressorMode == LVM_MODE_ON)
+        {
+        GainCorrect = (LVM_FLOAT)(  pInstance->VolCorrect.GainMin
+                                    - (((LVM_FLOAT)pInstance->VolCorrect.GainMin * \
+                                                         ((LVM_FLOAT)pInstance->TransitionGain)))
+                                    + (((LVM_FLOAT)pInstance->VolCorrect.GainFull * \
+                                                        ((LVM_FLOAT)pInstance->TransitionGain))));
+
+        /*
+         * Apply the gain correction
+         */
+        Gain1 = (Gain1 * GainCorrect);
+        Gain2 = (Gain2 * GainCorrect);
+
+        }
+
+        /*
+         * Set the gain values
+         */
+        pConfig->Output_Shift = pConfig->Output_Shift;
+        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[0],Gain1);
+        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],
+                                           LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[1],Gain2);
+        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],
+                                           LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+#endif
     }
 
     return(LVCS_SUCCESS);
@@ -206,9 +276,15 @@
 /************************************************************************************/
 
 LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
+#ifndef BUILD_FLOAT
                                       const LVM_INT16       *pProcessed,
                                       const LVM_INT16       *pUnprocessed,
                                       LVM_INT16             *pOutData,
+#else
+                                      const LVM_FLOAT       *pProcessed,
+                                      const LVM_FLOAT       *pUnprocessed,
+                                      LVM_FLOAT             *pOutData,
+#endif
                                       LVM_UINT16            NumSamples)
 {
 
@@ -223,6 +299,7 @@
         /*
          * Apply the bypass mix
          */
+#ifndef BUILD_FLOAT
         LVC_MixSoft_2St_D16C31_SAT(&pConfig->Mixer_Instance,
                                         pProcessed,
                                         (LVM_INT16 *) pUnprocessed,
@@ -236,6 +313,20 @@
                           (LVM_INT16*)pOutData,
                           (LVM_INT16*)pOutData,
                           (LVM_INT16)(2*NumSamples));          /* Left and right*/
+#else
+        LVC_MixSoft_2St_D16C31_SAT(&pConfig->Mixer_Instance,
+                                   pProcessed,
+                                   (LVM_FLOAT *) pUnprocessed,
+                                   pOutData,
+                                   (LVM_INT16)(2 * NumSamples));
+        /*
+         * Apply output gain correction shift
+         */
+        Shift_Sat_Float((LVM_INT16)pConfig->Output_Shift,
+                        (LVM_FLOAT*)pOutData,
+                        (LVM_FLOAT*)pOutData,
+                        (LVM_INT16)(2 * NumSamples));          /* Left and right*/
+#endif
     }
 
     return(LVCS_SUCCESS);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
index d1ef70a..f69ba38 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
@@ -42,12 +42,16 @@
 typedef struct
 {
     /* Mixer settings */
+#ifdef BUILD_FLOAT
+    LVMixer3_2St_FLOAT_st   Mixer_Instance;             /* Mixer instance */
+#else
     LVMixer3_2St_st         Mixer_Instance;             /* Mixer instance */
+#endif
     LVM_UINT16              Output_Shift;               /* Correcting gain output shift */
 
 } LVCS_BypassMix_t;
 
-
+#ifndef BUILD_FLOAT
 /* Output gain type */
 typedef struct
 {
@@ -56,8 +60,15 @@
     LVM_UINT16              Loss;                       /* Loss required */
     LVM_UINT16              UnprocLoss;                 /* Unprocessed path loss */
 } Gain_t;
-
-
+#else
+typedef struct
+{
+    /* Output gain settings, Gain = (Loss/32768) * 2^Shift */
+    LVM_UINT16             Shift;                      /* Left shifts required */
+    LVM_FLOAT              Loss;                       /* Loss required */
+    LVM_FLOAT              UnprocLoss;                 /* Unprocessed path loss */
+} Gain_t;
+#endif
 /************************************************************************************/
 /*                                                                                    */
 /*    Function prototypes                                                                */
@@ -67,13 +78,19 @@
 LVCS_ReturnStatus_en LVCS_BypassMixInit(LVCS_Handle_t       hInstance,
                                            LVCS_Params_t    *pParams);
 
-
+#ifndef BUILD_FLOAT
 LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
                                       const LVM_INT16       *pProcessed,
                                       const LVM_INT16       *unProcessed,
-                                            LVM_INT16       *pOutData,
-                                            LVM_UINT16      NumSamples);
-
+                                      LVM_INT16       *pOutData,
+                                      LVM_UINT16      NumSamples);
+#else
+LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
+                                      const LVM_FLOAT       *pProcessed,
+                                      const LVM_FLOAT       *unProcessed,
+                                      LVM_FLOAT       *pOutData,
+                                      LVM_UINT16      NumSamples);
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
index ce6d410..3bf6ec6 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
@@ -120,11 +120,13 @@
         pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
 
         pInstance->CompressGain = pInstance->VolCorrect.CompMin;
-
+#ifdef BUILD_FLOAT
+        LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0], 0, 0);
+#else
         LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
-
-
+#endif
         {
+#ifndef BUILD_FLOAT
             LVM_UINT32          Gain;
             const Gain_t        *pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
             Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * LVM_MAXINT_16);
@@ -140,7 +142,23 @@
                     LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],
                     LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+#else
+            LVM_FLOAT          Gain;
+            const Gain_t        *pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
+            Gain = (LVM_FLOAT)(pOutputGainTable[Offset].Loss);
+            Gain = (LVM_FLOAT)pOutputGainTable[Offset].UnprocLoss * (Gain);
 
+            /*
+             * Apply the gain correction
+             */
+            Gain = (Gain * pInstance->VolCorrect.GainMin);
+
+            LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1], 0, Gain);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],
+                    LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],
+                    LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+#endif
         }
 
 
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
index 25b0d86..ec5312e 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
@@ -53,7 +53,72 @@
 /* NOTES:                                                                           */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t       hInstance,
+                                        LVCS_Params_t       *pParams)
+{
 
+    LVM_UINT16          Offset;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t *)&pInstance->Equaliser;
+    LVCS_Data_t         *pData;
+    LVCS_Coefficient_t  *pCoefficients;
+    BQ_FLOAT_Coefs_t      Coeffs;
+    const BiquadA012B12CoefsSP_t *pEqualiserCoefTable;
+
+    pData = (LVCS_Data_t *) \
+                pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+
+    pCoefficients = (LVCS_Coefficient_t *) \
+                pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+    /*
+     * If the sample rate changes re-initialise the filters
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.SpeakerType != pParams->SpeakerType))
+    {
+        /*
+         * Setup the filter coefficients and clear the history
+         */
+        Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1 + LVM_FS_48000)));
+        pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
+
+        /* Left and right filters */
+        /* Convert incoming coefficients to the required format/ordering */
+        Coeffs.A0 = (LVM_FLOAT) pEqualiserCoefTable[Offset].A0;
+        Coeffs.A1 = (LVM_FLOAT) pEqualiserCoefTable[Offset].A1;
+        Coeffs.A2 = (LVM_FLOAT) pEqualiserCoefTable[Offset].A2;
+        Coeffs.B1 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B1;
+        Coeffs.B2 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B2;
+
+        LoadConst_Float((LVM_INT16)0,                                         /* Value */
+                        (void *)&pData->EqualiserBiquadTaps,   /* Destination Cast to void:\
+                                                                  no dereferencing in function*/
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps) / sizeof(LVM_FLOAT)));
+
+        BQ_2I_D16F32Css_TRC_WRA_01_Init(&pCoefficients->EqualiserBiquadInstance,
+                                        &pData->EqualiserBiquadTaps,
+                                        &Coeffs);
+
+        /* Callbacks */
+        switch(pEqualiserCoefTable[Offset].Scale)
+        {
+            case 13:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F32C13_TRC_WRA_01;
+                break;
+            case 14:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F32C14_TRC_WRA_01;
+                break;
+            case 15:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F32C15_TRC_WRA_01;
+                break;
+        }
+    }
+
+    return(LVCS_SUCCESS);
+}
+#else
 LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t       hInstance,
                                         LVCS_Params_t       *pParams)
 {
@@ -112,7 +177,7 @@
 
     return(LVCS_SUCCESS);
 }
-
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:                LVCS_Equaliser                                          */
@@ -132,7 +197,37 @@
 /*  1.  Always processes in place.                                                  */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t       hInstance,
+                                    LVM_FLOAT           *pInputOutput,
+                                    LVM_UINT16          NumSamples)
+{
 
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t  *)&pInstance->Equaliser;
+    LVCS_Coefficient_t  *pCoefficients;
+
+
+    pCoefficients = (LVCS_Coefficient_t *) \
+                  pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+
+    /*
+     * Check if the equaliser is required
+     */
+    if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0)
+    {
+        /* Apply filter to the left and right channels */
+        (pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*) \
+                                        &pCoefficients->EqualiserBiquadInstance,
+                                        (LVM_FLOAT *)pInputOutput,
+                                        (LVM_FLOAT *)pInputOutput,
+                                        (LVM_INT16)NumSamples);
+    }
+
+    return(LVCS_SUCCESS);
+}
+#else
 LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t       hInstance,
                                     LVM_INT16           *pInputOutput,
                                     LVM_UINT16          NumSamples)
@@ -157,4 +252,4 @@
 
     return(LVCS_SUCCESS);
 }
-
+#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
index cf96f5b..0e756e7 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
@@ -32,8 +32,11 @@
 /* Equaliser structure */
 typedef struct
 {
+#ifndef BUILD_FLOAT
     void (*pBiquadCallBack) (Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
-
+#else
+    void (*pBiquadCallBack) (Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
+#endif
 } LVCS_Equaliser_t;
 
 
@@ -45,12 +48,15 @@
 
 LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t       hInstance,
                                         LVCS_Params_t       *pParams);
-
+#ifndef BUILD_FLOAT
 LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t            hInstance,
                                     LVM_INT16                *pInputOutput,
                                     LVM_UINT16                NumSamples);
-
-
+#else
+LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t            hInstance,
+                                    LVM_FLOAT                *pInputOutput,
+                                    LVM_UINT16                NumSamples);
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
index 3e640cb..4f5221a 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
@@ -24,7 +24,463 @@
 /* The Stereo Enhancer                                                              */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+/* Stereo Enhancer coefficients for 8000 Hz sample rate, scaled with 0.161258 */
+#define CS_MIDDLE_8000_A0                           0.227720
+#define CS_MIDDLE_8000_A1                          -0.215125
+#define CS_MIDDLE_8000_A2                           0.000000
+#define CS_MIDDLE_8000_B1                          -0.921899
+#define CS_MIDDLE_8000_B2                           0.000000
+#define CS_MIDDLE_8000_SCALE                        15
+#define CS_SIDE_8000_A0                             0.611441
+#define CS_SIDE_8000_A1                            -0.380344
+#define CS_SIDE_8000_A2                            -0.231097
+#define CS_SIDE_8000_B1                            -0.622470
+#define CS_SIDE_8000_B2                            -0.130759
+#define CS_SIDE_8000_SCALE                         15
 
+/* Stereo Enhancer coefficients for 11025Hz sample rate, scaled with 0.162943 */
+#define CS_MIDDLE_11025_A0                       0.230838
+#define CS_MIDDLE_11025_A1                      -0.221559
+#define CS_MIDDLE_11025_A2                       0.000000
+#define CS_MIDDLE_11025_B1                      -0.943056
+#define CS_MIDDLE_11025_B2                       0.000000
+#define CS_MIDDLE_11025_SCALE                    15
+#define CS_SIDE_11025_A0                         0.557372
+#define CS_SIDE_11025_A1                        -0.391490
+#define CS_SIDE_11025_A2                        -0.165881
+#define CS_SIDE_11025_B1                        -0.880608
+#define CS_SIDE_11025_B2                         0.032397
+#define CS_SIDE_11025_SCALE                      15
+
+/* Stereo Enhancer coefficients for 12000Hz sample rate, scaled with 0.162191 */
+#define CS_MIDDLE_12000_A0                        0.229932
+#define CS_MIDDLE_12000_A1                       -0.221436
+#define CS_MIDDLE_12000_A2                        0.000000
+#define CS_MIDDLE_12000_B1                       -0.947616
+#define CS_MIDDLE_12000_B2                        0.000000
+#define CS_MIDDLE_12000_SCALE                        15
+#define CS_SIDE_12000_A0                         0.558398
+#define CS_SIDE_12000_A1                        -0.392211
+#define CS_SIDE_12000_A2                        -0.166187
+#define CS_SIDE_12000_B1                        -0.892550
+#define CS_SIDE_12000_B2                         0.032856
+#define CS_SIDE_12000_SCALE                          15
+
+/* Stereo Enhancer coefficients for 16000Hz sample rate, scaled with 0.162371 */
+#define CS_MIDDLE_16000_A0                       0.230638
+#define CS_MIDDLE_16000_A1                      -0.224232
+#define CS_MIDDLE_16000_A2                       0.000000
+#define CS_MIDDLE_16000_B1                      -0.960550
+#define CS_MIDDLE_16000_B2                       0.000000
+#define CS_MIDDLE_16000_SCALE                        15
+#define CS_SIDE_16000_A0                         0.499695
+#define CS_SIDE_16000_A1                        -0.355543
+#define CS_SIDE_16000_A2                        -0.144152
+#define CS_SIDE_16000_B1                        -1.050788
+#define CS_SIDE_16000_B2                         0.144104
+#define CS_SIDE_16000_SCALE                          14
+
+/* Stereo Enhancer coefficients for 22050Hz sample rate, scaled with 0.160781 */
+#define CS_MIDDLE_22050_A0                       0.228749
+#define CS_MIDDLE_22050_A1                      -0.224128
+#define CS_MIDDLE_22050_A2                       0.000000
+#define CS_MIDDLE_22050_B1                      -0.971262
+#define CS_MIDDLE_22050_B2                       0.000000
+#define CS_MIDDLE_22050_SCALE                        15
+#define CS_SIDE_22050_A0                          0.440112
+#define CS_SIDE_22050_A1                         -0.261096
+#define CS_SIDE_22050_A2                         -0.179016
+#define CS_SIDE_22050_B1                         -1.116786
+#define CS_SIDE_22050_B2                          0.182507
+#define CS_SIDE_22050_SCALE                          14
+
+/* Stereo Enhancer coefficients for 24000Hz sample rate, scaled with 0.161882 */
+#define CS_MIDDLE_24000_A0                         0.230395
+#define CS_MIDDLE_24000_A1                        -0.226117
+#define CS_MIDDLE_24000_A2                         0.000000
+#define CS_MIDDLE_24000_B1                        -0.973573
+#define CS_MIDDLE_24000_B2                         0.000000
+#define CS_MIDDLE_24000_SCALE                        15
+#define CS_SIDE_24000_A0                           0.414770
+#define CS_SIDE_24000_A1                          -0.287182
+#define CS_SIDE_24000_A2                          -0.127588
+#define CS_SIDE_24000_B1                          -1.229648
+#define CS_SIDE_24000_B2                           0.282177
+#define CS_SIDE_24000_SCALE                          14
+
+/* Stereo Enhancer coefficients for 32000Hz sample rate, scaled with 0.160322 */
+#define CS_MIDDLE_32000_A0                          0.228400
+#define CS_MIDDLE_32000_A1                         -0.225214
+#define CS_MIDDLE_32000_A2                          0.000000
+#define CS_MIDDLE_32000_B1                         -0.980126
+#define CS_MIDDLE_32000_B2                          0.000000
+#define CS_MIDDLE_32000_SCALE                        15
+#define CS_SIDE_32000_A0                            0.364579
+#define CS_SIDE_32000_A1                           -0.207355
+#define CS_SIDE_32000_A2                           -0.157224
+#define CS_SIDE_32000_B1                           -1.274231
+#define CS_SIDE_32000_B2                            0.312495
+#define CS_SIDE_32000_SCALE                          14
+
+/* Stereo Enhancer coefficients for 44100Hz sample rate, scaled with 0.163834 */
+#define CS_MIDDLE_44100_A0                     0.233593
+#define CS_MIDDLE_44100_A1                    -0.231225
+#define CS_MIDDLE_44100_A2                     0.000000
+#define CS_MIDDLE_44100_B1                    -0.985545
+#define CS_MIDDLE_44100_B2                     0.000000
+#define CS_MIDDLE_44100_SCALE                        15
+#define CS_SIDE_44100_A0                       0.284573
+#define CS_SIDE_44100_A1                      -0.258910
+#define CS_SIDE_44100_A2                      -0.025662
+#define CS_SIDE_44100_B1                      -1.572248
+#define CS_SIDE_44100_B2                       0.588399
+#define CS_SIDE_44100_SCALE                  14
+
+/* Stereo Enhancer coefficients for 48000Hz sample rate, scaled with 0.164402 */
+#define CS_MIDDLE_48000_A0                     0.234445
+#define CS_MIDDLE_48000_A1                    -0.232261
+#define CS_MIDDLE_48000_A2                     0.000000
+#define CS_MIDDLE_48000_B1                    -0.986713
+#define CS_MIDDLE_48000_B2                     0.000000
+#define CS_MIDDLE_48000_SCALE                        15
+#define CS_SIDE_48000_A0                     0.272606
+#define CS_SIDE_48000_A1                    -0.266952
+#define CS_SIDE_48000_A2                    -0.005654
+#define CS_SIDE_48000_B1                    -1.617141
+#define CS_SIDE_48000_B2                     0.630405
+#define CS_SIDE_48000_SCALE                          14
+
+#ifdef HIGHER_FS
+/* Stereo Enhancer coefficients for 96000Hz sample rate, scaled with  0.165*/
+/* high pass filter with cutoff frequency 102.18 Hz*/
+#define CS_MIDDLE_96000_A0                     0.235532
+#define CS_MIDDLE_96000_A1                    -0.234432
+#define CS_MIDDLE_96000_A2                     0.000000
+#define CS_MIDDLE_96000_B1                    -0.993334
+#define CS_MIDDLE_96000_B2                     0.000000
+#define CS_MIDDLE_96000_SCALE                        15
+/* bandpass filter with fc1 270 and fc2 3703, designed using 2nd order butterworth */
+#define CS_SIDE_96000_A0                     0.016727
+#define CS_SIDE_96000_A1                     0.000000
+#define CS_SIDE_96000_A2                    -0.016727
+#define CS_SIDE_96000_B1                    -1.793372
+#define CS_SIDE_96000_B2                     0.797236
+#define CS_SIDE_96000_SCALE                        14
+
+/* Stereo Enhancer coefficients for 192000Hz sample rate, scaled with  0.1689*/
+#define CS_MIDDLE_192000_A0                     0.241219
+#define CS_MIDDLE_192000_A1                    -0.240656
+#define CS_MIDDLE_192000_A2                     0.000000
+#define CS_MIDDLE_192000_B1                    -0.996661
+#define CS_MIDDLE_192000_B2                     0.000000
+#define CS_MIDDLE_192000_SCALE                        15
+/* bandpass filter with fc1 270 and fc2 3703, designed using 2nd order butterworth */
+#define CS_SIDE_192000_A0                     0.008991
+#define CS_SIDE_192000_A1                    -0.000000
+#define CS_SIDE_192000_A2                    -0.008991
+#define CS_SIDE_192000_B1                    -1.892509
+#define CS_SIDE_192000_B2                     0.893524
+#define CS_SIDE_192000_SCALE                       14
+#endif
+
+/************************************************************************************/
+/*                                                                                  */
+/* The Reverb Unit                                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Reverb delay settings in samples */
+#define LVCS_STEREODELAY_CS_8KHZ                     93         /* Sample rate 8kS/s */
+#define LVCS_STEREODELAY_CS_11KHZ                   128         /* Sample rate 11kS/s */
+#define LVCS_STEREODELAY_CS_12KHZ                   139         /* Sample rate 12kS/s */
+#define LVCS_STEREODELAY_CS_16KHZ                   186         /* Sample rate 16kS/s */
+#define LVCS_STEREODELAY_CS_22KHZ                   256         /* Sample rate 22kS/s */
+#define LVCS_STEREODELAY_CS_24KHZ                   279         /* Sample rate 24kS/s */
+#define LVCS_STEREODELAY_CS_32KHZ                   372         /* Sample rate 32kS/s */
+#define LVCS_STEREODELAY_CS_44KHZ                   512         /* Sample rate 44kS/s */
+#define LVCS_STEREODELAY_CS_48KHZ                   512         /* Sample rate 48kS/s */
+
+/* Reverb coefficients for 8000 Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_8000_A0                          0.667271
+#define CS_REVERB_8000_A1                         -0.667271
+#define CS_REVERB_8000_A2                          0.000000
+#define CS_REVERB_8000_B1                         -0.668179
+#define CS_REVERB_8000_B2                          0.000000
+#define CS_REVERB_8000_SCALE                         15
+
+/* Reverb coefficients for 11025Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_11025_A0                     0.699638
+#define CS_REVERB_11025_A1                    -0.699638
+#define CS_REVERB_11025_A2                     0.000000
+#define CS_REVERB_11025_B1                    -0.749096
+#define CS_REVERB_11025_B2                     0.000000
+#define CS_REVERB_11025_SCALE                  15
+
+/* Reverb coefficients for 12000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_12000_A0                   0.706931
+#define CS_REVERB_12000_A1                  -0.706931
+#define CS_REVERB_12000_A2                   0.000000
+#define CS_REVERB_12000_B1                  -0.767327
+#define CS_REVERB_12000_B2                   0.000000
+#define CS_REVERB_12000_SCALE                15
+
+/* Reverb coefficients for 16000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_16000_A0                      0.728272
+#define CS_REVERB_16000_A1                     -0.728272
+#define CS_REVERB_16000_A2                      0.000000
+#define CS_REVERB_16000_B1                     -0.820679
+#define CS_REVERB_16000_B2                      0.000000
+#define CS_REVERB_16000_SCALE                        15
+
+/* Reverb coefficients for 22050Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_22050_A0                     0.516396
+#define CS_REVERB_22050_A1                     0.000000
+#define CS_REVERB_22050_A2                    -0.516396
+#define CS_REVERB_22050_B1                    -0.518512
+#define CS_REVERB_22050_B2                    -0.290990
+#define CS_REVERB_22050_SCALE                        15
+
+
+/* Reverb coefficients for 24000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_24000_A0                       0.479565
+#define CS_REVERB_24000_A1                       0.000000
+#define CS_REVERB_24000_A2                      -0.479565
+#define CS_REVERB_24000_B1                      -0.637745
+#define CS_REVERB_24000_B2                      -0.198912
+#define CS_REVERB_24000_SCALE                        15
+
+/* Reverb coefficients for 32000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_32000_A0                      0.380349
+#define CS_REVERB_32000_A1                      0.000000
+#define CS_REVERB_32000_A2                     -0.380349
+#define CS_REVERB_32000_B1                     -0.950873
+#define CS_REVERB_32000_B2                      0.049127
+#define CS_REVERB_32000_SCALE                        15
+
+/* Reverb coefficients for 44100Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_44100_A0                         0.297389
+#define CS_REVERB_44100_A1                         0.000000
+#define CS_REVERB_44100_A2                        -0.297389
+#define CS_REVERB_44100_B1                        -1.200423
+#define CS_REVERB_44100_B2                         0.256529
+#define CS_REVERB_44100_SCALE                        14
+
+/* Reverb coefficients for 48000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_48000_A0                       0.278661
+#define CS_REVERB_48000_A1                       0.000000
+#define CS_REVERB_48000_A2                      -0.278661
+#define CS_REVERB_48000_B1                      -1.254993
+#define CS_REVERB_48000_B2                       0.303347
+#define CS_REVERB_48000_SCALE                        14
+
+#ifdef HIGHER_FS
+/* Reverb coefficients for 96000Hz sample rate, scaled with 0.8 */
+/* Band pass filter with fc1=500 and fc2=8000*/
+#define CS_REVERB_96000_A0                       0.1602488
+#define CS_REVERB_96000_A1                       0.000000
+#define CS_REVERB_96000_A2                      -0.1602488
+#define CS_REVERB_96000_B1                      -1.585413
+#define CS_REVERB_96000_B2                       0.599377
+#define CS_REVERB_96000_SCALE                        14
+
+/* Reverb coefficients for 192000Hz sample rate, scaled with 0.8 */
+/* Band pass filter with fc1=500 and fc2=8000*/
+#define CS_REVERB_192000_A0                       0.0878369
+#define CS_REVERB_192000_A1                       0.000000
+#define CS_REVERB_192000_A2                      -0.0878369
+#define CS_REVERB_192000_B1                      -1.7765764
+#define CS_REVERB_192000_B2                       0.7804076
+#define CS_REVERB_192000_SCALE                        14
+
+#endif
+
+
+/* Reverb Gain Settings */
+#define LVCS_HEADPHONE_DELAYGAIN               0.800000         /* Algorithm delay path gain */
+#define LVCS_HEADPHONE_OUTPUTGAIN              1.000000         /* Algorithm output gain */
+#define LVCS_HEADPHONE_PROCGAIN                   18403         /* Processed path gain */
+#define LVCS_HEADPHONE_UNPROCGAIN                 18403         /* Unprocessed path gain */
+#define LVCS_HEADPHONE_GAINCORRECT             1.009343         /* Delay mixer gain correction */
+
+/************************************************************************************/
+/*                                                                                  */
+/* The Equaliser                                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Equaliser coefficients for 8000 Hz sample rate, \
+   CS scaled with 1.038497 and CSEX scaled with 0.775480 */
+#define CS_EQUALISER_8000_A0                     1.263312
+#define CS_EQUALISER_8000_A1                    -0.601748
+#define CS_EQUALISER_8000_A2                    -0.280681
+#define CS_EQUALISER_8000_B1                    -0.475865
+#define CS_EQUALISER_8000_B2                    -0.408154
+#define CS_EQUALISER_8000_SCALE                      14
+#define CSEX_EQUALISER_8000_A0                    0.943357
+#define CSEX_EQUALISER_8000_A1                   -0.449345
+#define CSEX_EQUALISER_8000_A2                   -0.209594
+#define CSEX_EQUALISER_8000_B1                   -0.475865
+#define CSEX_EQUALISER_8000_B2                   -0.408154
+#define CSEX_EQUALISER_8000_SCALE                    15
+
+/* Equaliser coefficients for 11025Hz sample rate, \
+   CS scaled with 1.027761 and CSEX scaled with 0.767463 */
+#define CS_EQUALISER_11025_A0                    1.101145
+#define CS_EQUALISER_11025_A1                    0.139020
+#define CS_EQUALISER_11025_A2                   -0.864423
+#define CS_EQUALISER_11025_B1                    0.024541
+#define CS_EQUALISER_11025_B2                   -0.908930
+#define CS_EQUALISER_11025_SCALE                     14
+#define CSEX_EQUALISER_11025_A0                    0.976058
+#define CSEX_EQUALISER_11025_A1                   -0.695326
+#define CSEX_EQUALISER_11025_A2                   -0.090809
+#define CSEX_EQUALISER_11025_B1                   -0.610594
+#define CSEX_EQUALISER_11025_B2                   -0.311149
+#define CSEX_EQUALISER_11025_SCALE                   15
+
+/* Equaliser coefficients for 12000Hz sample rate, \
+   CS scaled with 1.032521 and CSEX scaled with 0.771017 */
+#define CS_EQUALISER_12000_A0                      1.276661
+#define CS_EQUALISER_12000_A1                     -1.017519
+#define CS_EQUALISER_12000_A2                     -0.044128
+#define CS_EQUALISER_12000_B1                     -0.729616
+#define CS_EQUALISER_12000_B2                     -0.204532
+#define CS_EQUALISER_12000_SCALE                     14
+#define CSEX_EQUALISER_12000_A0                 1.007095
+#define CSEX_EQUALISER_12000_A1                -0.871912
+#define CSEX_EQUALISER_12000_A2                 0.023232
+#define CSEX_EQUALISER_12000_B1                -0.745857
+#define CSEX_EQUALISER_12000_B2                -0.189171
+#define CSEX_EQUALISER_12000_SCALE                   14
+
+/* Equaliser coefficients for 16000Hz sample rate, \
+   CS scaled with 1.031378 and CSEX scaled with 0.770164 */
+#define CS_EQUALISER_16000_A0                     1.281629
+#define CS_EQUALISER_16000_A1                    -1.075872
+#define CS_EQUALISER_16000_A2                    -0.041365
+#define CS_EQUALISER_16000_B1                    -0.725239
+#define CS_EQUALISER_16000_B2                    -0.224358
+#define CS_EQUALISER_16000_SCALE                     14
+#define CSEX_EQUALISER_16000_A0                  1.081091
+#define CSEX_EQUALISER_16000_A1                 -0.867183
+#define CSEX_EQUALISER_16000_A2                 -0.070247
+#define CSEX_EQUALISER_16000_B1                 -0.515121
+#define CSEX_EQUALISER_16000_B2                 -0.425893
+#define CSEX_EQUALISER_16000_SCALE                   14
+
+/* Equaliser coefficients for 22050Hz sample rate, \
+   CS scaled with 1.041576 and CSEX scaled with 0.777779 */
+#define CS_EQUALISER_22050_A0                   1.388605
+#define CS_EQUALISER_22050_A1                  -1.305799
+#define CS_EQUALISER_22050_A2                   0.039922
+#define CS_EQUALISER_22050_B1                  -0.719494
+#define CS_EQUALISER_22050_B2                  -0.243245
+#define CS_EQUALISER_22050_SCALE                     14
+#define CSEX_EQUALISER_22050_A0                   1.272910
+#define CSEX_EQUALISER_22050_A1                  -1.341014
+#define CSEX_EQUALISER_22050_A2                   0.167462
+#define CSEX_EQUALISER_22050_B1                  -0.614219
+#define CSEX_EQUALISER_22050_B2                  -0.345384
+#define CSEX_EQUALISER_22050_SCALE                   14
+
+/* Equaliser coefficients for 24000Hz sample rate, \
+   CS scaled with 1.034495 and CSEX scaled with 0.772491 */
+#define CS_EQUALISER_24000_A0                    1.409832
+#define CS_EQUALISER_24000_A1                   -1.456506
+#define CS_EQUALISER_24000_A2                    0.151410
+#define CS_EQUALISER_24000_B1                   -0.804201
+#define CS_EQUALISER_24000_B2                   -0.163783
+#define CS_EQUALISER_24000_SCALE                     14
+#define CSEX_EQUALISER_24000_A0                  1.299198
+#define CSEX_EQUALISER_24000_A1                 -1.452447
+#define CSEX_EQUALISER_24000_A2                  0.240489
+#define CSEX_EQUALISER_24000_B1                 -0.669303
+#define CSEX_EQUALISER_24000_B2                 -0.294984
+#define CSEX_EQUALISER_24000_SCALE                   14
+
+/* Equaliser coefficients for 32000Hz sample rate, \
+   CS scaled with 1.044559 and CSEX scaled with 0.780006 */
+#define CS_EQUALISER_32000_A0                     1.560988
+#define CS_EQUALISER_32000_A1                    -1.877724
+#define CS_EQUALISER_32000_A2                     0.389741
+#define CS_EQUALISER_32000_B1                    -0.907410
+#define CS_EQUALISER_32000_B2                    -0.070489
+#define CS_EQUALISER_32000_SCALE                     14
+#define CSEX_EQUALISER_32000_A0                  1.785049
+#define CSEX_EQUALISER_32000_A1                 -2.233497
+#define CSEX_EQUALISER_32000_A2                  0.526431
+#define CSEX_EQUALISER_32000_B1                 -0.445939
+#define CSEX_EQUALISER_32000_B2                 -0.522446
+#define CSEX_EQUALISER_32000_SCALE                   13
+
+/* Equaliser coefficients for 44100Hz sample rate, \
+   CS scaled with 1.022170 and CSEX scaled with 0.763288 */
+#define CS_EQUALISER_44100_A0                  1.623993
+#define CS_EQUALISER_44100_A1                 -2.270743
+#define CS_EQUALISER_44100_A2                  0.688829
+#define CS_EQUALISER_44100_B1                 -1.117190
+#define CS_EQUALISER_44100_B2                  0.130208
+#define CS_EQUALISER_44100_SCALE                     13
+#define CSEX_EQUALISER_44100_A0                   2.028315
+#define CSEX_EQUALISER_44100_A1                  -2.882459
+#define CSEX_EQUALISER_44100_A2                   0.904535
+#define CSEX_EQUALISER_44100_B1                  -0.593308
+#define CSEX_EQUALISER_44100_B2                  -0.385816
+#define CSEX_EQUALISER_44100_SCALE                   13
+
+/* Equaliser coefficients for 48000Hz sample rate, \
+   CS scaled with 1.018635 and CSEX scaled with 0.760648 */
+#define CS_EQUALISER_48000_A0                    1.641177
+#define CS_EQUALISER_48000_A1                   -2.364687
+#define CS_EQUALISER_48000_A2                    0.759910
+#define CS_EQUALISER_48000_B1                   -1.166774
+#define CS_EQUALISER_48000_B2                    0.178074
+#define CS_EQUALISER_48000_SCALE                     13
+#define CSEX_EQUALISER_48000_A0                  2.099655
+#define CSEX_EQUALISER_48000_A1                 -3.065220
+#define CSEX_EQUALISER_48000_A2                  1.010417
+#define CSEX_EQUALISER_48000_B1                 -0.634021
+#define CSEX_EQUALISER_48000_B2                 -0.347332
+#define CSEX_EQUALISER_48000_SCALE                   13
+
+
+#ifdef HIGHER_FS
+#define CS_EQUALISER_96000_A0                    1.784497
+#define CS_EQUALISER_96000_A1                   -3.001435
+#define CS_EQUALISER_96000_A2                    1.228422
+#define CS_EQUALISER_96000_B1                   -1.477804
+#define CS_EQUALISER_96000_B2                    0.481369
+#define CS_EQUALISER_96000_SCALE                     13
+#define CSEX_EQUALISER_96000_A0                  2.7573
+#define CSEX_EQUALISER_96000_A1                 -4.6721
+#define CSEX_EQUALISER_96000_A2                  1.9317
+#define CSEX_EQUALISER_96000_B1                 -0.971718
+#define CSEX_EQUALISER_96000_B2                 -0.021216
+#define CSEX_EQUALISER_96000_SCALE                   13
+
+#define CS_EQUALISER_192000_A0                    1.889582
+#define CS_EQUALISER_192000_A1                   -3.456140
+#define CS_EQUALISER_192000_A2                    1.569864
+#define CS_EQUALISER_192000_B1                   -1.700798
+#define CS_EQUALISER_192000_B2                    0.701824
+#define CS_EQUALISER_192000_SCALE                     13
+#define CSEX_EQUALISER_192000_A0                  3.4273
+#define CSEX_EQUALISER_192000_A1                 -6.2936
+#define CSEX_EQUALISER_192000_A2                  2.8720
+#define CSEX_EQUALISER_192000_B1                 -1.31074
+#define CSEX_EQUALISER_192000_B2                 0.31312
+#define CSEX_EQUALISER_192000_SCALE                   13
+#endif
+
+
+#define LVCS_HEADPHONE_SHIFT                          2              /* Output Shift */
+#define LVCS_HEADPHONE_SHIFTLOSS                  0.8477735          /* Output Shift loss */
+#define LVCS_HEADPHONE_GAIN                       0.2087465          /* Unprocessed path gain */
+#define LVCS_EX_HEADPHONE_SHIFT                       3              /* EX Output Shift */
+#define LVCS_EX_HEADPHONE_SHIFTLOSS               0.569225           /* EX Output Shift loss */
+#define LVCS_EX_HEADPHONE_GAIN                    0.07794425         /* EX Unprocessed path gain */
+#else
 /* Stereo Enhancer coefficients for 8000 Hz sample rate, scaled with 0.161258 */
 #define CS_MIDDLE_8000_A0                          7462         /* Floating point value 0.227720 */
 #define CS_MIDDLE_8000_A1                        (-7049)        /* Floating point value -0.215125 */
@@ -394,5 +850,6 @@
 #define LVCS_EX_HEADPHONE_SHIFT                       3              /* EX Output Shift */
 #define LVCS_EX_HEADPHONE_SHIFTLOSS               18600              /* EX Output Shift loss */
 #define LVCS_EX_HEADPHONE_GAIN                     5108              /* EX Unprocessed path gain */
-
 #endif
+#endif
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
index 1904e46..d4c7627 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
@@ -98,7 +98,13 @@
         /*
          * Scratch memory
          */
+#ifdef BUILD_FLOAT
+        /* Inplace processing */
+        ScratchSize = (LVM_UINT32) \
+                        (LVCS_SCRATCHBUFFERS * sizeof(LVM_FLOAT) * pCapabilities->MaxBlockSize);
+#else
         ScratchSize = (LVM_UINT32)(LVCS_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);     /* Inplace processing */
+#endif
         pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Size         = ScratchSize;
         pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Type         = LVCS_SCRATCH;
         pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
@@ -190,6 +196,7 @@
     pLVCS_VolCorrectTable            = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
     pInstance->VolCorrect            = pLVCS_VolCorrectTable[0];
     pInstance->TransitionGain        = 0;
+
     /* These current and target values are intialized again in LVCS_Control.c */
     LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
     /* These current and target values are intialized again in LVCS_Control.c */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
index f3adb8d..a97e4f0 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -95,10 +95,17 @@
 /* Volume correction structure */
 typedef struct
 {
+#ifdef BUILD_FLOAT
+    LVM_FLOAT   CompFull;                       /* Post CS compression 100% effect */
+    LVM_FLOAT   CompMin;                        /* Post CS compression 0% effect */
+    LVM_FLOAT   GainFull;                       /* CS gain correct 100% effect */
+    LVM_FLOAT   GainMin;                        /* CS gain correct 0% effect */
+#else
     LVM_INT16   CompFull;                       /* Post CS compression 100% effect */
     LVM_INT16   CompMin;                        /* Post CS compression 0% effect */
     LVM_INT16   GainFull;                       /* CS gain correct 100% effect */
     LVM_INT16   GainMin;                        /* CS gain correct 0% effect */
+#endif
 } LVCS_VolCorrect_t;
 
 /* Instance structure */
@@ -112,8 +119,13 @@
     /* Private parameters */
     LVCS_OutputDevice_en    OutputDevice;       /* Selected output device type */
     LVCS_VolCorrect_t       VolCorrect;         /* Volume correction settings */
+#ifndef BUILD_FLOAT
     LVM_INT16               TransitionGain;     /* Transition gain */
     LVM_INT16               CompressGain;       /* Last used compressor gain*/
+#else
+    LVM_FLOAT               TransitionGain;     /* Transition gain */
+    LVM_FLOAT               CompressGain;       /* Last used compressor gain*/
+#endif
 
     /* Sub-block configurations */
     LVCS_StereoEnhancer_t   StereoEnhancer;     /* Stereo enhancer configuration */
@@ -134,24 +146,35 @@
 /* Coefficient Structure */
 typedef struct
 {
+#ifdef BUILD_FLOAT
+    Biquad_FLOAT_Instance_t       EqualiserBiquadInstance;
+    Biquad_FLOAT_Instance_t       ReverbBiquadInstance;
+    Biquad_FLOAT_Instance_t       SEBiquadInstanceMid;
+    Biquad_FLOAT_Instance_t       SEBiquadInstanceSide;
+#else
     Biquad_Instance_t       EqualiserBiquadInstance;
     Biquad_Instance_t       ReverbBiquadInstance;
     Biquad_Instance_t       SEBiquadInstanceMid;
     Biquad_Instance_t       SEBiquadInstanceSide;
-
+#endif
 } LVCS_Coefficient_t;
 
 /* Data Structure */
 typedef struct
 {
+#ifdef BUILD_FLOAT
+    Biquad_2I_Order2_FLOAT_Taps_t EqualiserBiquadTaps;
+    Biquad_2I_Order2_FLOAT_Taps_t ReverbBiquadTaps;
+    Biquad_1I_Order1_FLOAT_Taps_t SEBiquadTapsMid;
+    Biquad_1I_Order2_FLOAT_Taps_t SEBiquadTapsSide;
+#else
     Biquad_2I_Order2_Taps_t EqualiserBiquadTaps;
     Biquad_2I_Order2_Taps_t ReverbBiquadTaps;
     Biquad_1I_Order1_Taps_t SEBiquadTapsMid;
     Biquad_1I_Order2_Taps_t SEBiquadTapsSide;
-
+#endif
 } LVCS_Data_t;
 
-
 void LVCS_TimerCallBack (   void* hInstance,
                             void* pCallBackParams,
                             LVM_INT32 CallbackParam);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
index 5d99461..3956d4d 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
@@ -66,7 +66,77 @@
 /* NOTES:                                                                           */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t              hInstance,
+                                     const LVM_FLOAT            *pInData,
+                                     LVM_FLOAT                  *pOutData,
+                                     LVM_UINT16                 NumSamples)
+{
+    const LVM_FLOAT     *pInput;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVM_FLOAT           *pScratch;
+    LVCS_ReturnStatus_en err;
 
+    pScratch  = (LVM_FLOAT *) \
+                  pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+
+    /*
+     * Check if the processing is inplace
+     */
+    if (pInData == pOutData)
+    {
+        /* Processing inplace */
+        pInput = pScratch + (2 * NumSamples);
+        Copy_Float((LVM_FLOAT *)pInData,           /* Source */
+                   (LVM_FLOAT *)pInput,            /* Destination */
+                   (LVM_INT16)(2 * NumSamples));     /* Left and right */
+    }
+    else
+    {
+        /* Processing outplace */
+        pInput = pInData;
+    }
+
+    /*
+     * Call the stereo enhancer
+     */
+    err = LVCS_StereoEnhancer(hInstance,              /* Instance handle */
+                              pInData,                    /* Pointer to the input data */
+                              pOutData,                   /* Pointer to the output data */
+                              NumSamples);                /* Number of samples to process */
+
+    /*
+     * Call the reverb generator
+     */
+    err = LVCS_ReverbGenerator(hInstance,             /* Instance handle */
+                               pOutData,                  /* Pointer to the input data */
+                               pOutData,                  /* Pointer to the output data */
+                               NumSamples);               /* Number of samples to process */
+    
+    /*
+     * Call the equaliser
+     */
+    err = LVCS_Equaliser(hInstance,                   /* Instance handle */
+                         pOutData,                        /* Pointer to the input data */
+                         NumSamples);                     /* Number of samples to process */
+
+    /*
+     * Call the bypass mixer
+     */
+    err = LVCS_BypassMixer(hInstance,                 /* Instance handle */
+                           pOutData,                      /* Pointer to the processed data */
+                           pInput,                        /* Pointer to the input (unprocessed) data */
+                           pOutData,                      /* Pointer to the output data */
+                           NumSamples);                   /* Number of samples to process */
+
+    if(err != LVCS_SUCCESS)
+    {
+        return err;
+    }
+
+    return(LVCS_SUCCESS);
+}
+#else
 LVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t              hInstance,
                                      const LVM_INT16            *pInData,
                                      LVM_INT16                  *pOutData,
@@ -133,7 +203,7 @@
 
     return(LVCS_SUCCESS);
 }
-
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:                LVCS_Process                                            */
@@ -160,7 +230,170 @@
 /* NOTES:                                                                           */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
+                                  const LVM_FLOAT           *pInData,
+                                  LVM_FLOAT                 *pOutData,
+                                  LVM_UINT16                NumSamples)
+{
 
+    LVCS_Instance_t *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_ReturnStatus_en err;
+
+    /*
+     * Check the number of samples is not too large
+     */
+    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+    {
+        return(LVCS_TOOMANYSAMPLES);
+    }
+
+    /*
+     * Check if the algorithm is enabled
+     */
+    if (pInstance->Params.OperatingMode != LVCS_OFF)
+    {
+        /*
+         * Call CS process function
+         */
+            err = LVCS_Process_CS(hInstance,
+                                  pInData,
+                                  pOutData,
+                                  NumSamples);
+            
+            
+        /*
+         * Compress to reduce expansion effect of Concert Sound and correct volume
+         * differences for difference settings. Not applied in test modes
+         */
+        if ((pInstance->Params.OperatingMode == LVCS_ON)&& \
+                                        (pInstance->Params.CompressorMode == LVM_MODE_ON))
+        {
+            LVM_FLOAT Gain = pInstance->VolCorrect.CompMin;
+            LVM_FLOAT Current1;
+
+            Current1 = LVC_Mixer_GetCurrent(&pInstance->BypassMix.Mixer_Instance.MixerStream[0]);
+            Gain = (LVM_FLOAT)(  pInstance->VolCorrect.CompMin
+                               - (((LVM_FLOAT)pInstance->VolCorrect.CompMin  * (Current1)))
+                               + (((LVM_FLOAT)pInstance->VolCorrect.CompFull * (Current1))));
+
+            if(NumSamples < LVCS_COMPGAINFRAME)
+            {
+                NonLinComp_Float(Gain,                    /* Compressor gain setting */
+                                 pOutData,
+                                 pOutData,
+                                 (LVM_INT32)(2 * NumSamples));
+            }
+            else
+            {
+                LVM_FLOAT  GainStep;
+                LVM_FLOAT  FinalGain;
+                LVM_INT16  SampleToProcess = NumSamples;
+                LVM_FLOAT  *pOutPtr;
+
+                /* Large changes in Gain can cause clicks in output
+                   Split data into small blocks and use interpolated gain values */
+
+                GainStep = (LVM_FLOAT)(((Gain-pInstance->CompressGain) * \
+                                                LVCS_COMPGAINFRAME) / NumSamples);
+
+                if((GainStep == 0) && (pInstance->CompressGain < Gain))
+                {
+                    GainStep = 1;
+                }
+                else
+                {
+                    if((GainStep == 0) && (pInstance->CompressGain > Gain))
+                    {
+                        GainStep = -1;
+                    }
+                }
+
+                FinalGain = Gain;
+                Gain = pInstance->CompressGain;
+                pOutPtr = pOutData;
+
+                while(SampleToProcess > 0)
+                {
+                    Gain = (LVM_FLOAT)(Gain + GainStep);
+                    if((GainStep > 0) && (FinalGain <= Gain))
+                    {
+                        Gain = FinalGain;
+                        GainStep = 0;
+                    }
+
+                    if((GainStep < 0) && (FinalGain > Gain))
+                    {
+                        Gain = FinalGain;
+                        GainStep = 0;
+                    }
+
+                    if(SampleToProcess > LVCS_COMPGAINFRAME)
+                    {
+                        NonLinComp_Float(Gain,                    /* Compressor gain setting */
+                                         pOutPtr,
+                                         pOutPtr,
+                                         (LVM_INT32)(2 * LVCS_COMPGAINFRAME));
+                        pOutPtr += (2 * LVCS_COMPGAINFRAME);
+                        SampleToProcess = (LVM_INT16)(SampleToProcess - LVCS_COMPGAINFRAME);
+                    }
+                    else
+                    {
+                        NonLinComp_Float(Gain,                    /* Compressor gain setting */
+                                         pOutPtr,
+                                         pOutPtr,
+                                         (LVM_INT32)(2 * SampleToProcess));
+                        SampleToProcess = 0;
+                    }
+
+                }
+            }
+
+            /* Store gain value*/
+            pInstance->CompressGain = Gain;
+        }
+
+
+        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
+
+            /*
+             * Re-init bypass mix when timer has completed
+             */
+            if ((pInstance->bTimerDone == LVM_TRUE) &&
+                (pInstance->BypassMix.Mixer_Instance.MixerStream[1].CallbackSet == 0))
+            {
+                err = LVCS_BypassMixInit(hInstance,
+                                         &pInstance->Params);
+
+                if(err != LVCS_SUCCESS)
+                {
+                    return err;
+                }
+
+            }
+            else{
+                LVM_Timer ( &pInstance->TimerInstance,
+                            (LVM_INT16)NumSamples);
+            }
+        }
+    }
+    else
+    {
+        if (pInData != pOutData)
+        {
+            /*
+             * The algorithm is disabled so just copy the data
+             */
+            Copy_Float((LVM_FLOAT *)pInData,               /* Source */
+                       (LVM_FLOAT *)pOutData,                  /* Destination */
+                       (LVM_INT16)(2 * NumSamples));             /* Left and right */
+        }
+    }
+
+
+    return(LVCS_SUCCESS);
+}
+#else
 LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
                                   const LVM_INT16           *pInData,
                                   LVM_INT16                 *pOutData,
@@ -321,13 +554,4 @@
 
     return(LVCS_SUCCESS);
 }
-
-
-
-
-
-
-
-
-
-
+#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c
index ee257b8..1085101 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c
@@ -57,7 +57,98 @@
 /*  2.  The numerator coefficients of the filter are negated to cause an inversion. */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t     hInstance,
+                                              LVCS_Params_t     *pParams)
+{
 
+    LVM_UINT16              Delay;
+    LVM_UINT16              Offset;
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
+    LVCS_Data_t             *pData;
+    LVCS_Coefficient_t      *pCoefficients;
+    BQ_FLOAT_Coefs_t         Coeffs;
+    const BiquadA012B12CoefsSP_t  *pReverbCoefTable;
+
+
+    pData = (LVCS_Data_t *) \
+                 pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+
+    pCoefficients = (LVCS_Coefficient_t *) \
+                 pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    /*
+     * Initialise the delay and filters if:
+     *  - the sample rate has changed
+     *  - the speaker type has changed to or from the mobile speaker
+     */
+    if(pInstance->Params.SampleRate != pParams->SampleRate )      /* Sample rate change test */
+
+    {
+        /*
+         * Setup the delay
+         */
+        Delay = (LVM_UINT16)LVCS_StereoDelayCS[(LVM_UINT16)pParams->SampleRate];
+
+
+        pConfig->DelaySize      = (LVM_INT16)(2 * Delay);
+        pConfig->DelayOffset    = 0;
+        LoadConst_Float(0,                                            /* Value */
+                        (LVM_FLOAT *)&pConfig->StereoSamples[0],      /* Destination */
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pConfig->StereoSamples) / sizeof(LVM_FLOAT)));
+        /*
+         * Setup the filters
+         */
+        Offset = (LVM_UINT16)pParams->SampleRate;
+        pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
+
+        /* Convert incoming coefficients to the required format/ordering */
+        Coeffs.A0 = (LVM_FLOAT)pReverbCoefTable[Offset].A0;
+        Coeffs.A1 = (LVM_FLOAT)pReverbCoefTable[Offset].A1;
+        Coeffs.A2 = (LVM_FLOAT)pReverbCoefTable[Offset].A2;
+        Coeffs.B1 = (LVM_FLOAT)-pReverbCoefTable[Offset].B1;
+        Coeffs.B2 = (LVM_FLOAT)-pReverbCoefTable[Offset].B2;
+
+        LoadConst_Float(0,                                 /* Value */
+                        (void *)&pData->ReverbBiquadTaps,  /* Destination Cast to void:
+                                                             no dereferencing in function*/
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pData->ReverbBiquadTaps) / sizeof(LVM_FLOAT)));
+
+        BQ_2I_D16F16Css_TRC_WRA_01_Init(&pCoefficients->ReverbBiquadInstance,
+                                        &pData->ReverbBiquadTaps,
+                                        &Coeffs);
+
+        /* Callbacks */
+        switch(pReverbCoefTable[Offset].Scale)
+        {
+            case 14:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F16C14_TRC_WRA_01;
+                break;
+            case 15:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F16C15_TRC_WRA_01;
+                break;
+        }
+
+
+        /*
+         * Setup the mixer
+         */
+        pConfig->ProcGain = (LVM_UINT16)(HEADPHONEGAINPROC);
+        pConfig->UnprocGain  = (LVM_UINT16)(HEADPHONEGAINUNPROC);
+    }
+
+    if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
+    {
+        LVM_INT32   ReverbPercentage = 83886;      // 1 Percent Reverb i.e 1/100 in Q 23 format
+        ReverbPercentage *= pParams->ReverbLevel;  // Actual Reverb Level in Q 23 format
+        pConfig->ReverbLevel = ((LVM_FLOAT)(ReverbPercentage>>8)) / 32767.0f;
+    }
+    return(LVCS_SUCCESS);
+}
+#else
 LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t     hInstance,
                                               LVCS_Params_t     *pParams)
 {
@@ -140,7 +231,7 @@
 
     return(LVCS_SUCCESS);
 }
-
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:                LVCS_Reverb                                             */
@@ -179,7 +270,91 @@
 /*  2.  The Gain is combined with the LPF and incorporated in to the coefficients   */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
+                                          const LVM_FLOAT       *pInData,
+                                          LVM_FLOAT             *pOutData,
+                                          LVM_UINT16            NumSamples)
+{
 
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
+    LVCS_Coefficient_t      *pCoefficients;
+    LVM_FLOAT               *pScratch;
+
+    pCoefficients = (LVCS_Coefficient_t *)\
+                   pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    pScratch  = (LVM_FLOAT *)\
+                    pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+
+    /*
+     * Copy the data to the output in outplace processing
+     */
+    if (pInData != pOutData)
+    {
+        /*
+         * Reverb not required so just copy the data
+         */
+        Copy_Float((LVM_FLOAT *)pInData,                                       /* Source */
+                   (LVM_FLOAT *)pOutData,                                      /* Destination */
+                   (LVM_INT16)(2 * NumSamples));                                 /* Left and right */
+    }
+
+
+    /*
+     * Check if the reverb is required
+     */
+    /* Disable when CS4MS in stereo mode */
+    if (((pInstance->Params.SpeakerType == LVCS_HEADPHONE) || \
+         (pInstance->Params.SpeakerType == LVCS_EX_HEADPHONES) ||
+         (pInstance->Params.SourceFormat != LVCS_STEREO))  &&
+                                    /* For validation testing */
+        ((pInstance->Params.OperatingMode & LVCS_REVERBSWITCH) !=0))
+    {
+        /********************************************************************************/
+        /*                                                                              */
+        /* Copy the input data to scratch memory and filter it                          */
+        /*                                                                              */
+        /********************************************************************************/
+
+        /*
+         * Copy the input data to the scratch memory
+         */
+        Copy_Float((LVM_FLOAT *)pInData,                                     /* Source */
+                   (LVM_FLOAT *)pScratch,                                    /* Destination */
+                   (LVM_INT16)(2 * NumSamples));                               /* Left and right */
+
+        /*
+         * Filter the data
+         */
+        (pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*)&pCoefficients->ReverbBiquadInstance,
+                                   (LVM_FLOAT *)pScratch,
+                                   (LVM_FLOAT *)pScratch,
+                                   (LVM_INT16)NumSamples);
+
+        Mult3s_Float( (LVM_FLOAT *)pScratch,
+                      pConfig->ReverbLevel,
+                      (LVM_FLOAT *)pScratch,
+                      (LVM_INT16)(2 * NumSamples));
+
+
+        /*
+         * Apply the delay mix
+         */
+        DelayMix_Float((LVM_FLOAT *)pScratch,
+                       &pConfig->StereoSamples[0],
+                       pConfig->DelaySize,
+                       pOutData,
+                       &pConfig->DelayOffset,
+                       (LVM_INT16)NumSamples);
+
+
+    }
+
+    return(LVCS_SUCCESS);
+}
+#else
 LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
                                           const LVM_INT16       *pInData,
                                           LVM_INT16             *pOutData,
@@ -257,8 +432,4 @@
 
     return(LVCS_SUCCESS);
 }
-
-
-
-
-
+#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
index 6e026ff..69892b6 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
@@ -58,14 +58,20 @@
     LVM_INT16                   DelayOffset;
     LVM_INT16                   ProcGain;
     LVM_INT16                   UnprocGain;
+#ifndef BUILD_FLOAT
     LVM_INT16                    StereoSamples[2*LVCS_STEREODELAY_CS_48KHZ];
-
     /* Reverb Level */
     LVM_INT16                   ReverbLevel;
-
     /* Filter */
     void                        (*pBiquadCallBack) (Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
-
+#else
+    LVM_FLOAT                   StereoSamples[2 * LVCS_STEREODELAY_CS_48KHZ];
+    /* Reverb Level */
+    LVM_FLOAT                   ReverbLevel;
+    /* Filter */
+    void                        (*pBiquadCallBack) (Biquad_FLOAT_Instance_t*,
+                                                    LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
+#endif
 } LVCS_ReverbGenerator_t;
 
 
@@ -77,12 +83,17 @@
 
 LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t     hInstance,
                                                  LVCS_Params_t  *pParams);
-
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
+                                          const LVM_FLOAT       *pInput,
+                                          LVM_FLOAT             *pOutput,
+                                          LVM_UINT16            NumSamples);
+#else
 LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
                                           const LVM_INT16       *pInput,
                                           LVM_INT16             *pOutput,
                                           LVM_UINT16            NumSamples);
-
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
index b9b8b05..2992c35 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
@@ -49,7 +49,103 @@
 /* NOTES:                                                                           */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t       hInstance,
+                                        LVCS_Params_t       *pParams)
+{
 
+    LVM_UINT16              Offset;
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
+    LVCS_Data_t             *pData;
+    LVCS_Coefficient_t      *pCoefficient;
+    FO_FLOAT_Coefs_t          CoeffsMid;
+    BQ_FLOAT_Coefs_t          CoeffsSide;
+    const BiquadA012B12CoefsSP_t *pSESideCoefs;
+
+
+    pData     = (LVCS_Data_t *) \
+                  pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+
+    pCoefficient = (LVCS_Coefficient_t *) \
+                  pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    /*
+     * If the sample rate or speaker type has changed update the filters
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.SpeakerType != pParams->SpeakerType))
+    {
+        /*
+         * Set the filter coefficients based on the sample rate
+         */
+        /* Mid filter */
+        Offset = (LVM_UINT16)pParams->SampleRate;
+
+        /* Convert incoming coefficients to the required format/ordering */
+        CoeffsMid.A0 = (LVM_FLOAT) LVCS_SEMidCoefTable[Offset].A0;
+        CoeffsMid.A1 = (LVM_FLOAT) LVCS_SEMidCoefTable[Offset].A1;
+        CoeffsMid.B1 = (LVM_FLOAT)-LVCS_SEMidCoefTable[Offset].B1;
+
+        /* Clear the taps */
+        LoadConst_Float(0,                                  /* Value */
+                        (void *)&pData->SEBiquadTapsMid,    /* Destination Cast to void:\
+                                                              no dereferencing in function*/
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pData->SEBiquadTapsMid) / sizeof(LVM_FLOAT)));
+
+        FO_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceMid,
+                                        &pData->SEBiquadTapsMid,
+                                        &CoeffsMid);
+
+        /* Callbacks */
+        if(LVCS_SEMidCoefTable[Offset].Scale == 15)
+        {
+            pConfig->pBiquadCallBack_Mid  = FO_1I_D16F16C15_TRC_WRA_01;
+        }
+
+        Offset = (LVM_UINT16)(pParams->SampleRate);
+        pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
+
+        /* Side filter */
+        /* Convert incoming coefficients to the required format/ordering */
+        CoeffsSide.A0 = (LVM_FLOAT) pSESideCoefs[Offset].A0;
+        CoeffsSide.A1 = (LVM_FLOAT) pSESideCoefs[Offset].A1;
+        CoeffsSide.A2 = (LVM_FLOAT) pSESideCoefs[Offset].A2;
+        CoeffsSide.B1 = (LVM_FLOAT)-pSESideCoefs[Offset].B1;
+        CoeffsSide.B2 = (LVM_FLOAT)-pSESideCoefs[Offset].B2;
+
+        /* Clear the taps */
+        LoadConst_Float(0,                                /* Value */
+                        (void *)&pData->SEBiquadTapsSide, /* Destination Cast to void:\
+                                                             no dereferencing in function*/
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pData->SEBiquadTapsSide) / sizeof(LVM_FLOAT)));
+        /* Callbacks */
+        switch(pSESideCoefs[Offset].Scale)
+        {
+            case 14:
+                BQ_1I_D16F32Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
+                                                &pData->SEBiquadTapsSide,
+                                                &CoeffsSide);
+
+                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F32C14_TRC_WRA_01;
+                break;
+            case 15:
+                BQ_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
+                                                &pData->SEBiquadTapsSide,
+                                                &CoeffsSide);
+
+                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F16C15_TRC_WRA_01;
+                break;
+        }
+
+    }
+
+
+    return(LVCS_SUCCESS);
+}
+#else
 LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t       hInstance,
                                         LVCS_Params_t       *pParams)
 {
@@ -138,7 +234,7 @@
 
     return(LVCS_SUCCESS);
 }
-
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:                LVCS_StereoEnhance                                      */
@@ -177,7 +273,90 @@
 /*  1.  The side filter is not used in Mobile Speaker mode                          */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BUILD_FLOAT
+LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t          hInstance,
+                                         const LVM_FLOAT        *pInData,
+                                         LVM_FLOAT              *pOutData,
+                                         LVM_UINT16             NumSamples)
+{
 
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
+    LVCS_Coefficient_t      *pCoefficient;
+    LVM_FLOAT               *pScratch;
+
+    pCoefficient = (LVCS_Coefficient_t *) \
+                   pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    pScratch  = (LVM_FLOAT *) \
+                    pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+    /*
+     * Check if the Stereo Enhancer is enabled
+     */
+    if ((pInstance->Params.OperatingMode & LVCS_STEREOENHANCESWITCH) != 0)
+        {
+        /*
+         * Convert from stereo to middle and side
+         */
+        From2iToMS_Float(pInData,
+                         pScratch,
+                         pScratch + NumSamples,
+                         (LVM_INT16)NumSamples);
+
+        /*
+         * Apply filter to the middle signal
+         */
+        if (pInstance->OutputDevice == LVCS_HEADPHONE)
+        {
+            (pConfig->pBiquadCallBack_Mid)((Biquad_FLOAT_Instance_t*)\
+                                            &pCoefficient->SEBiquadInstanceMid,
+                                            (LVM_FLOAT *)pScratch,
+                                            (LVM_FLOAT *)pScratch,
+                                            (LVM_INT16)NumSamples);
+        }
+        else
+        {
+            Mult3s_Float(pScratch,              /* Source */
+                         (LVM_FLOAT)pConfig->MidGain,      /* Gain */
+                         pScratch,              /* Destination */
+                         (LVM_INT16)NumSamples);           /* Number of samples */
+        }
+
+        /*
+         * Apply the filter the side signal only in stereo mode for headphones
+         * and in all modes for mobile speakers
+         */
+        if (pInstance->Params.SourceFormat == LVCS_STEREO)
+        {
+            (pConfig->pBiquadCallBack_Side)((Biquad_FLOAT_Instance_t*) \
+                                            &pCoefficient->SEBiquadInstanceSide,
+                                            (LVM_FLOAT *)(pScratch + NumSamples),
+                                            (LVM_FLOAT *)(pScratch + NumSamples),
+                                            (LVM_INT16)NumSamples);
+        }
+
+        /*
+         * Convert from middle and side to stereo
+         */
+        MSTo2i_Sat_Float(pScratch,
+                         pScratch + NumSamples,
+                         pOutData,
+                         (LVM_INT16)NumSamples);
+
+    }
+    else
+    {
+        /*
+         * The stereo enhancer is disabled so just copy the data
+         */
+        Copy_Float((LVM_FLOAT *)pInData,           /* Source */
+                   (LVM_FLOAT *)pOutData,          /* Destination */
+                   (LVM_INT16)(2 * NumSamples));     /* Left and right */
+    }
+
+    return(LVCS_SUCCESS);
+}
+#else
 LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t          hInstance,
                                          const LVM_INT16        *pInData,
                                          LVM_INT16              *pOutData,
@@ -254,7 +433,4 @@
 
     return(LVCS_SUCCESS);
 }
-
-
-
-
+#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
index 15bc407..4125f24 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
@@ -43,18 +43,31 @@
 /* Stereo enhancer structure */
 typedef struct
 {
+
+#ifndef BUILD_FLOAT
     /*
      * Middle filter
      */
     void                    (*pBiquadCallBack_Mid)(Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
-
     /*
      * Side filter
      */
     void                    (*pBiquadCallBack_Side)(Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
+    LVM_UINT16              MidGain;            /* Middle gain in mobile speaker mode */
+#else
+    /*
+     * Middle filter
+     */
+    void                    (*pBiquadCallBack_Mid)(Biquad_FLOAT_Instance_t*,
+                                    LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
 
-      LVM_UINT16              MidGain;            /* Middle gain in mobile speaker mode */
-
+    /*
+     * Side filter
+     */
+    void                    (*pBiquadCallBack_Side)(Biquad_FLOAT_Instance_t*,
+                                    LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
+    LVM_FLOAT              MidGain;            /* Middle gain in mobile speaker mode */
+#endif
 } LVCS_StereoEnhancer_t;
 
 
@@ -67,12 +80,17 @@
 LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t        hInstance,
                                         LVCS_Params_t        *pParams);
 
+#ifndef BUILD_FLOAT
 LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t        hInstance,
                                          const LVM_INT16    *pInData,
                                          LVM_INT16            *pOutData,
                                          LVM_UINT16            NumSamples);
-
-
+#else
+LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t        hInstance,
+                                         const LVM_FLOAT    *pInData,
+                                         LVM_FLOAT            *pOutData,
+                                         LVM_UINT16            NumSamples);
+#endif
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
index 974de21..e154e29 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
@@ -71,7 +71,19 @@
     {CS_MIDDLE_48000_A0,        /* 48kS/s coefficients */
      CS_MIDDLE_48000_A1,
      CS_MIDDLE_48000_B1,
-     (LVM_UINT16 )CS_MIDDLE_48000_SCALE}};
+     (LVM_UINT16 )CS_MIDDLE_48000_SCALE}
+#ifdef HIGHER_FS
+    ,
+    {CS_MIDDLE_96000_A0,        /* 96kS/s coefficients */
+     CS_MIDDLE_96000_A1,
+     CS_MIDDLE_96000_B1,
+     (LVM_UINT16 )CS_MIDDLE_96000_SCALE},
+    {CS_MIDDLE_192000_A0,        /* 192kS/s coefficients */
+     CS_MIDDLE_192000_A1,
+     CS_MIDDLE_192000_B1,
+     (LVM_UINT16 )CS_MIDDLE_192000_SCALE}
+#endif
+    };
 
 /* Coefficient table for the side filter */
 const BiquadA012B12CoefsSP_t LVCS_SESideCoefTable[] = {
@@ -130,6 +142,21 @@
      CS_SIDE_48000_B1,
      CS_SIDE_48000_B2,
      (LVM_UINT16 )CS_SIDE_48000_SCALE}
+#ifdef HIGHER_FS
+     ,
+     {CS_SIDE_96000_A0,          /* 96kS/s coefficients */
+     CS_SIDE_96000_A1,
+     CS_SIDE_96000_A2,
+     CS_SIDE_96000_B1,
+     CS_SIDE_96000_B2,
+     (LVM_UINT16 )CS_SIDE_96000_SCALE},
+     {CS_SIDE_192000_A0,          /* 192kS/s coefficients */
+     CS_SIDE_192000_A1,
+     CS_SIDE_192000_A2,
+     CS_SIDE_192000_B1,
+     CS_SIDE_192000_B2,
+     (LVM_UINT16 )CS_SIDE_192000_SCALE}
+#endif
 };
 
 
@@ -195,6 +222,20 @@
      CS_EQUALISER_48000_B1,
      CS_EQUALISER_48000_B2,
      (LVM_UINT16 )CS_EQUALISER_48000_SCALE},
+#ifdef HIGHER_FS
+    {CS_EQUALISER_96000_A0,     /* 96kS/s coefficients */
+     CS_EQUALISER_96000_A1,
+     CS_EQUALISER_96000_A2,
+     CS_EQUALISER_96000_B1,
+     CS_EQUALISER_96000_B2,
+     (LVM_UINT16 )CS_EQUALISER_96000_SCALE},
+    {CS_EQUALISER_192000_A0,     /* 192kS/s coefficients */
+     CS_EQUALISER_192000_A1,
+     CS_EQUALISER_192000_A2,
+     CS_EQUALISER_192000_B1,
+     CS_EQUALISER_192000_B2,
+     (LVM_UINT16 )CS_EQUALISER_192000_SCALE},
+#endif
 
     /* Concert Sound EX Headphone coefficients */
     {CSEX_EQUALISER_8000_A0,    /* 8kS/s coefficients */
@@ -251,6 +292,21 @@
      CSEX_EQUALISER_48000_B1,
      CSEX_EQUALISER_48000_B2,
      (LVM_UINT16 )CSEX_EQUALISER_48000_SCALE}
+#ifdef HIGHER_FS
+    ,
+    {CSEX_EQUALISER_96000_A0,   /* 96kS/s coefficients */
+     CSEX_EQUALISER_96000_A1,
+     CSEX_EQUALISER_96000_A2,
+     CSEX_EQUALISER_96000_B1,
+     CSEX_EQUALISER_96000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_96000_SCALE},
+     {CSEX_EQUALISER_192000_A0,   /* 192kS/s coefficients */
+     CSEX_EQUALISER_192000_A1,
+     CSEX_EQUALISER_192000_A2,
+     CSEX_EQUALISER_192000_B1,
+     CSEX_EQUALISER_192000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_192000_SCALE}
+#endif
 };
 
 
@@ -334,6 +390,21 @@
      CS_REVERB_48000_B1,
      CS_REVERB_48000_B2,
      (LVM_UINT16 )CS_REVERB_48000_SCALE}
+#ifdef HIGHER_FS
+    ,
+    {CS_REVERB_96000_A0,            /* 96kS/s coefficients */
+     CS_REVERB_96000_A1,
+     CS_REVERB_96000_A2,
+     CS_REVERB_96000_B1,
+     CS_REVERB_96000_B2,
+     (LVM_UINT16 )CS_REVERB_96000_SCALE},
+     {CS_REVERB_192000_A0,            /* 192kS/s coefficients */
+     CS_REVERB_192000_A1,
+     CS_REVERB_192000_A2,
+     CS_REVERB_192000_B1,
+     CS_REVERB_192000_B2,
+     (LVM_UINT16 )CS_REVERB_192000_SCALE}
+#endif
 };
 
 
@@ -385,6 +456,24 @@
 /*                                                                                  */
 /************************************************************************************/
 const LVCS_VolCorrect_t LVCS_VolCorrectTable[] = {
+#ifdef BUILD_FLOAT
+    {0.433362f,          /* Headphone, stereo mode */
+     0.000000f,
+     1.000024f,
+     1.412640f},
+    {0.433362f,          /* EX Headphone, stereo mode */
+     0.000000f,
+     1.000024f,
+     1.412640f},
+    {1.000000f,         /* Headphone, mono mode */
+     0.000000f,
+     1.000024f,
+     1.412640f},
+    {1.000000f,         /* EX Headphone, mono mode */
+     0.000000f,
+     1.000024f,
+     1.412640f}
+#else
     {14200,          /* Headphone, stereo mode */
      0,
      4096,
@@ -401,6 +490,7 @@
      0,
      4096,
      5786}
+#endif
 };
 
 /************************************************************************************/
@@ -418,8 +508,25 @@
 #define LVCS_VOL_TC_Fs32000     32721       /* Floating point value 0.998565674 */
 #define LVCS_VOL_TC_Fs44100     32734       /* Floating point value 0.998962402 */
 #define LVCS_VOL_TC_Fs48000     32737       /* Floating point value 0.999053955 */
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+#define LVCS_VOL_TC_Fs96000     32751       /* Floating point value 0.999511703 */   /* Todo @ need to re check this value*/
+#define LVCS_VOL_TC_Fs192000    32763       /* Floating point value 0.999877925 */  /* Todo @ need to re check this value*/
+#endif
 
-
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+const LVM_INT16 LVCS_VolumeTCTable[11] = {LVCS_VOL_TC_Fs8000,
+		                                  LVCS_VOL_TC_Fs11025,
+										  LVCS_VOL_TC_Fs12000,
+										  LVCS_VOL_TC_Fs16000,
+										  LVCS_VOL_TC_Fs22050,
+										  LVCS_VOL_TC_Fs24000,
+										  LVCS_VOL_TC_Fs32000,
+										  LVCS_VOL_TC_Fs44100,
+										  LVCS_VOL_TC_Fs48000,
+										  LVCS_VOL_TC_Fs96000,
+										  LVCS_VOL_TC_Fs192000
+};
+#else
 const LVM_INT16 LVCS_VolumeTCTable[9] = {LVCS_VOL_TC_Fs8000,
                                         LVCS_VOL_TC_Fs11025,
                                         LVCS_VOL_TC_Fs12000,
@@ -428,15 +535,30 @@
                                         LVCS_VOL_TC_Fs24000,
                                         LVCS_VOL_TC_Fs32000,
                                         LVCS_VOL_TC_Fs44100,
-                                        LVCS_VOL_TC_Fs48000};
+                                        LVCS_VOL_TC_Fs48000
+};
+#endif
 
 /************************************************************************************/
 /*                                                                                  */
 /*  Sample rate table                                                               */
 /*                                                                                  */
 /************************************************************************************/
-
-const LVM_INT32   LVCS_SampleRateTable[9] = {8000,
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+const LVM_INT32   LVCS_SampleRateTable[11] = {8000,
+		                                      11025,
+											  12000,
+											  16000,
+											  22050,
+											  24000,
+											  32000,
+											  44100,
+											  48000,
+											  96000,
+											  192000
+};
+#else
+const LVM_INT16   LVCS_SampleRateTable[9] = {8000,
                                             11025,
                                             12000,
                                             16000,
@@ -444,5 +566,6 @@
                                             24000,
                                             32000,
                                             44100,
-                                            48000};
-
+                                            48000
+};
+#endif
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index efd30fb..f106aae 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -10,7 +10,7 @@
 LOCAL_SRC_FILES:= \
 	Bundle/EffectBundle.cpp
 
-LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -fvisibility=hidden -DBUILD_FLOAT -DHIGHER_FS
 LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_MODULE:= libbundlewrapper
@@ -43,7 +43,7 @@
 LOCAL_SRC_FILES:= \
     Reverb/EffectReverb.cpp
 
-LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -fvisibility=hidden -DBUILD_FLOAT -DHIGHER_FS
 LOCAL_CFLAGS += -Wall -Werror
 
 LOCAL_MODULE:= libreverbwrapper
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index df6501b..aae80b6 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -14,7 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#ifndef LVM_FLOAT
+typedef float LVM_FLOAT;
+#endif
 #define LOG_TAG "Bundle"
 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array)[0])
 //#define LOG_NDEBUG 0
@@ -33,6 +35,15 @@
 // effect_handle_t interface implementation for bass boost
 extern "C" const struct effect_interface_s gLvmEffectInterface;
 
+// Turn on VERY_VERY_VERBOSE_LOGGING to log parameter get and set for effects.
+
+//#define VERY_VERY_VERBOSE_LOGGING
+#ifdef VERY_VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while (false)
+#endif
+
 #define LVM_ERROR_CHECK(LvmStatus, callingFunc, calledFunc){\
         if ((LvmStatus) == LVM_NULLADDRESS){\
             ALOGV("\tLVM_ERROR : Parameter error - "\
@@ -138,26 +149,43 @@
 void LvmEffect_free            (EffectContext *pContext);
 int  Effect_setConfig          (EffectContext *pContext, effect_config_t *pConfig);
 void Effect_getConfig          (EffectContext *pContext, effect_config_t *pConfig);
-int  BassBoost_setParameter    (EffectContext *pContext, void *pParam, void *pValue);
+int  BassBoost_setParameter    (EffectContext *pContext,
+                                uint32_t       paramSize,
+                                void          *pParam,
+                                uint32_t       valueSize,
+                                void          *pValue);
 int  BassBoost_getParameter    (EffectContext *pContext,
-                               void           *pParam,
-                               uint32_t       *pValueSize,
-                               void           *pValue);
-int  Virtualizer_setParameter  (EffectContext *pContext, void *pParam, void *pValue);
-int  Virtualizer_getParameter  (EffectContext *pContext,
-                               void           *pParam,
-                               uint32_t       *pValueSize,
-                               void           *pValue);
-int  Equalizer_setParameter    (EffectContext *pContext,
-                               void *pParam,
-                               uint32_t valueSize,
-                               void *pValue);
-int  Equalizer_getParameter    (EffectContext *pContext,
+                                uint32_t       paramSize,
                                 void          *pParam,
                                 uint32_t      *pValueSize,
                                 void          *pValue);
-int  Volume_setParameter       (EffectContext *pContext, void *pParam, void *pValue);
+int  Virtualizer_setParameter  (EffectContext *pContext,
+                                uint32_t       paramSize,
+                                void          *pParam,
+                                uint32_t       valueSize,
+                                void          *pValue);
+int  Virtualizer_getParameter  (EffectContext *pContext,
+                                uint32_t       paramSize,
+                                void          *pParam,
+                                uint32_t      *pValueSize,
+                                void          *pValue);
+int  Equalizer_setParameter    (EffectContext *pContext,
+                                uint32_t       paramSize,
+                                void          *pParam,
+                                uint32_t       valueSize,
+                                void          *pValue);
+int  Equalizer_getParameter    (EffectContext *pContext,
+                                uint32_t       paramSize,
+                                void          *pParam,
+                                uint32_t      *pValueSize,
+                                void          *pValue);
+int  Volume_setParameter       (EffectContext *pContext,
+                                uint32_t       paramSize,
+                                void          *pParam,
+                                uint32_t       valueSize,
+                                void          *pValue);
 int  Volume_getParameter       (EffectContext *pContext,
+                                uint32_t       paramSize,
                                 void          *pParam,
                                 uint32_t      *pValueSize,
                                 void          *pValue);
@@ -271,7 +299,10 @@
         pContext->pBundledContext->SamplesToExitCountVirt   = 0;
         pContext->pBundledContext->SamplesToExitCountBb     = 0;
         pContext->pBundledContext->SamplesToExitCountEq     = 0;
-
+#ifdef BUILD_FLOAT
+        pContext->pBundledContext->pInputBuffer             = NULL;
+        pContext->pBundledContext->pOutputBuffer            = NULL;
+#endif
         for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
             pContext->pBundledContext->bandGaindB[i] = EQNB_5BandSoftPresets[i];
         }
@@ -439,6 +470,14 @@
         if (pContext->pBundledContext->workBuffer != NULL) {
             free(pContext->pBundledContext->workBuffer);
         }
+#ifdef BUILD_FLOAT
+        if (pContext->pBundledContext->pInputBuffer != NULL) {
+            free(pContext->pBundledContext->pInputBuffer);
+        }
+        if (pContext->pBundledContext->pOutputBuffer != NULL) {
+            free(pContext->pBundledContext->pOutputBuffer);
+        }
+#endif
         delete pContext->pBundledContext;
         pContext->pBundledContext = LVM_NULL;
     }
@@ -695,7 +734,47 @@
     return 0;
 }   /* end LvmBundle_init */
 
+#ifdef BUILD_FLOAT
+/**********************************************************************************
+   FUNCTION INT16LTOFLOAT
+***********************************************************************************/
+// Todo: need to write function descriptor
+static void Int16ToFloat(const LVM_INT16 *src, LVM_FLOAT *dst, size_t n) {
+    size_t ii;
+    src += n-1;
+    dst += n-1;
+    for (ii = n; ii != 0; ii--) {
+        *dst = ((LVM_FLOAT)((LVM_INT16)*src)) / 32768.0f;
+        src--;
+        dst--;
+    }
+    return;
+}
+/**********************************************************************************
+   FUNCTION FLOATTOINT16_SAT
+***********************************************************************************/
+// Todo : Need to write function descriptor
+static void FloatToInt16_SAT(const LVM_FLOAT *src, LVM_INT16 *dst, size_t n) {
+    size_t ii;
+    LVM_INT32 temp;
 
+    src += n-1;
+    dst += n-1;
+    for (ii = n; ii != 0; ii--) {
+        temp = (LVM_INT32)((*src) * 32768.0f);
+        if (temp >= 32767) {
+            *dst = 32767;
+        } else if (temp <= -32768) {
+            *dst = -32768;
+        } else {
+            *dst = (LVM_INT16)temp;
+        }
+        src--;
+        dst--;
+    }
+    return;
+}
+#endif
 //----------------------------------------------------------------------------
 // LvmBundle_process()
 //----------------------------------------------------------------------------
@@ -713,7 +792,99 @@
 //  pOut:       pointer to updated stereo 16 bit output data
 //
 //----------------------------------------------------------------------------
+#ifdef BUILD_FLOAT
+int LvmBundle_process(LVM_INT16        *pIn,
+                      LVM_INT16        *pOut,
+                      int              frameCount,
+                      EffectContext    *pContext){
 
+
+    //LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+    LVM_INT16               *pOutTmp;
+    LVM_FLOAT               *pInputBuff;
+    LVM_FLOAT               *pOutputBuff;
+
+    if (pContext->pBundledContext->pInputBuffer == NULL ||
+            pContext->pBundledContext->frameCount < frameCount) {
+        if (pContext->pBundledContext->pInputBuffer != NULL) {
+            free(pContext->pBundledContext->pInputBuffer);
+        }
+        pContext->pBundledContext->pInputBuffer = (LVM_FLOAT *)malloc(frameCount * \
+                                                                      sizeof(LVM_FLOAT) * FCC_2);
+    }
+
+    if (pContext->pBundledContext->pOutputBuffer == NULL ||
+            pContext->pBundledContext->frameCount < frameCount) {
+        if (pContext->pBundledContext->pOutputBuffer != NULL) {
+            free(pContext->pBundledContext->pOutputBuffer);
+        }
+        pContext->pBundledContext->pOutputBuffer = (LVM_FLOAT *)malloc(frameCount * \
+                                                                       sizeof(LVM_FLOAT) * FCC_2);
+    }
+
+    if ((pContext->pBundledContext->pInputBuffer == NULL) ||
+                                    (pContext->pBundledContext->pOutputBuffer == NULL)) {
+        ALOGV("LVM_ERROR : LvmBundle_process memory allocation for float buffer's failed");
+        return -EINVAL;
+    }
+
+    pInputBuff = pContext->pBundledContext->pInputBuffer;
+    pOutputBuff = pContext->pBundledContext->pOutputBuffer;
+
+    if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
+        pOutTmp = pOut;
+    } else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+        if (pContext->pBundledContext->frameCount != frameCount) {
+            if (pContext->pBundledContext->workBuffer != NULL) {
+                free(pContext->pBundledContext->workBuffer);
+            }
+            pContext->pBundledContext->workBuffer =
+                    (LVM_INT16 *)calloc(frameCount, sizeof(LVM_INT16) * FCC_2);
+            if (pContext->pBundledContext->workBuffer == NULL) {
+                return -ENOMEM;
+            }
+            pContext->pBundledContext->frameCount = frameCount;
+        }
+        pOutTmp = pContext->pBundledContext->workBuffer;
+    } else {
+        ALOGV("LVM_ERROR : LvmBundle_process invalid access mode");
+        return -EINVAL;
+    }
+
+    #ifdef LVM_PCM
+    fwrite(pIn, frameCount*sizeof(LVM_INT16) * FCC_2, 1, pContext->pBundledContext->PcmInPtr);
+    fflush(pContext->pBundledContext->PcmInPtr);
+    #endif
+
+    /* Converting input data from fixed point to float point */
+    Int16ToFloat(pIn, pInputBuff, frameCount * 2);
+
+    /* Process the samples */
+    LvmStatus = LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
+                            pInputBuff,                           /* Input buffer */
+                            pOutputBuff,                          /* Output buffer */
+                            (LVM_UINT16)frameCount,               /* Number of samples to read */
+                            0);                                   /* Audo Time */
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_Process", "LvmBundle_process")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    /* Converting output data from float point to fixed point */
+    FloatToInt16_SAT(pOutputBuff, pOutTmp, (LVM_UINT16)frameCount * 2);
+    #ifdef LVM_PCM
+    fwrite(pOutTmp, frameCount*sizeof(LVM_INT16) * FCC_2, 1, pContext->pBundledContext->PcmOutPtr);
+    fflush(pContext->pBundledContext->PcmOutPtr);
+    #endif
+
+    if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+        for (int i = 0; i < frameCount * 2; i++){
+            pOut[i] = clamp16((LVM_INT32)pOut[i] + (LVM_INT32)pOutTmp[i]);
+        }
+    }
+    return 0;
+}    /* end LvmBundle_process */
+#else
 int LvmBundle_process(LVM_INT16        *pIn,
                       LVM_INT16        *pOut,
                       int              frameCount,
@@ -771,7 +942,7 @@
     }
     return 0;
 }    /* end LvmBundle_process */
-
+#endif
 
 //----------------------------------------------------------------------------
 // EqualizerUpdateActiveParams()
@@ -840,8 +1011,12 @@
     float energyBassBoost = 0;
     float crossCorrection = 0;
 
+    bool eqEnabled = pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE;
+    bool bbEnabled = pContext->pBundledContext->bBassEnabled == LVM_TRUE;
+    bool viEnabled = pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE;
+
     //EQ contribution
-    if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
+    if (eqEnabled) {
         for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
             float bandFactor = pContext->pBundledContext->bandGaindB[i]/15.0;
             float bandCoefficient = LimitLevel_bandEnergyCoefficient[i];
@@ -867,35 +1042,37 @@
         }
         bandFactorSum -= 1.0;
         if (bandFactorSum > 0)
-            crossCorrection = bandFactorSum * 0.7;
+          crossCorrection = bandFactorSum * 0.7;
     }
 
     //BassBoost contribution
-    if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
+    if (bbEnabled) {
         float boostFactor = (pContext->pBundledContext->BassStrengthSaved)/1000.0;
         float boostCoefficient = LimitLevel_bassBoostEnergyCoefficient;
 
         energyContribution += boostFactor * boostCoefficient * boostCoefficient;
 
-        for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
-            float bandFactor = pContext->pBundledContext->bandGaindB[i]/15.0;
-            float bandCrossCoefficient = LimitLevel_bassBoostEnergyCrossCoefficient[i];
-            float bandEnergy = boostFactor * bandFactor *
+        if (eqEnabled) {
+            for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+                float bandFactor = pContext->pBundledContext->bandGaindB[i]/15.0;
+                float bandCrossCoefficient = LimitLevel_bassBoostEnergyCrossCoefficient[i];
+                float bandEnergy = boostFactor * bandFactor *
                     bandCrossCoefficient;
-            if (bandEnergy > 0)
-                energyBassBoost += bandEnergy;
+                if (bandEnergy > 0)
+                  energyBassBoost += bandEnergy;
+            }
         }
     }
 
     //Virtualizer contribution
-    if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
+    if (viEnabled) {
         energyContribution += LimitLevel_virtualizerContribution *
                 LimitLevel_virtualizerContribution;
     }
 
     double totalEnergyEstimation = sqrt(energyContribution + energyCross + energyBassBoost) -
             crossCorrection;
-    ALOGV(" TOTAL energy estimation: %0.2f", totalEnergyEstimation);
+    ALOGV(" TOTAL energy estimation: %0.2f dB", totalEnergyEstimation);
 
     //roundoff
     int maxLevelRound = (int)(totalEnergyEstimation + 0.99);
@@ -913,6 +1090,8 @@
     /* Activate the initial settings */
     LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
     LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_limitLevel")
+
+    ALOGV("LVM_SetControlParameters return:%d", (int)LvmStatus);
     //ALOGV("\tLvmEffect_limitLevel just Set -> %d\n",
     //          ActiveParams.pEQNB_BandDefinition[band].Gain);
 
@@ -1126,6 +1305,16 @@
         SampleRate = LVM_FS_48000;
         pContext->pBundledContext->SamplesPerSecond = 48000*2; // 2 secs Stereo
         break;
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+    case 96000:
+        SampleRate = LVM_FS_96000;
+        pContext->pBundledContext->SamplesPerSecond = 96000*2; // 2 secs Stereo
+        break;
+    case 192000:
+        SampleRate = LVM_FS_192000;
+        pContext->pBundledContext->SamplesPerSecond = 192000*2; // 2 secs Stereo
+        break;
+#endif
     default:
         ALOGV("\tEffect_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
         return -EINVAL;
@@ -1153,6 +1342,8 @@
         ALOGV("\tEffect_setConfig Succesfully called LVM_SetControlParameters\n");
         pContext->pBundledContext->SampleRate = SampleRate;
 
+        LvmEffect_limitLevel(pContext);
+
     }else{
         //ALOGV("\tEffect_setConfig keep sampling rate at %d", SampleRate);
     }
@@ -2010,59 +2201,54 @@
 //
 //----------------------------------------------------------------------------
 
-int BassBoost_getParameter(EffectContext     *pContext,
-                           void              *pParam,
-                           uint32_t          *pValueSize,
-                           void              *pValue){
+int BassBoost_getParameter(EffectContext *pContext,
+                           uint32_t       paramSize,
+                           void          *pParam,
+                           uint32_t      *pValueSize,
+                           void          *pValue) {
     int status = 0;
-    int32_t *pParamTemp = (int32_t *)pParam;
-    int32_t param = *pParamTemp++;
+    int32_t *params = (int32_t *)pParam;
 
-    //ALOGV("\tBassBoost_getParameter start");
+    ALOGVV("%s start", __func__);
 
-    switch (param){
-        case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
-            if (*pValueSize != sizeof(uint32_t)){
-                ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize1 %d", *pValueSize);
-                return -EINVAL;
-            }
-            *pValueSize = sizeof(uint32_t);
-            break;
-        case BASSBOOST_PARAM_STRENGTH:
-            if (*pValueSize != sizeof(int16_t)){
-                ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize2 %d", *pValueSize);
-                return -EINVAL;
-            }
-            *pValueSize = sizeof(int16_t);
-            break;
-
-        default:
-            ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
-            return -EINVAL;
+    if (paramSize < sizeof(int32_t)) {
+        ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+        return -EINVAL;
     }
-
-    switch (param){
+    switch (params[0]) {
         case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
-            *(uint32_t *)pValue = 1;
+            if (*pValueSize != sizeof(uint32_t)) {  // legacy: check equality here.
+                ALOGV("%s BASSBOOST_PARAM_STRENGTH_SUPPORTED invalid *pValueSize %u",
+                        __func__, *pValueSize);
+                status = -EINVAL;
+                break;
+            }
+            // no need to set *pValueSize
 
-            //ALOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH_SUPPORTED Value is %d",
-            //        *(uint32_t *)pValue);
+            *(uint32_t *)pValue = 1;
+            ALOGVV("%s BASSBOOST_PARAM_STRENGTH_SUPPORTED %u", __func__, *(uint32_t *)pValue);
             break;
 
         case BASSBOOST_PARAM_STRENGTH:
-            *(int16_t *)pValue = BassGetStrength(pContext);
+            if (*pValueSize != sizeof(int16_t)) {  // legacy: check equality here.
+                ALOGV("%s BASSBOOST_PARAM_STRENGTH invalid *pValueSize %u",
+                        __func__, *pValueSize);
+                status = -EINVAL;
+                break;
+            }
+            // no need to set *pValueSize
 
-            //ALOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH Value is %d",
-            //        *(int16_t *)pValue);
+            *(int16_t *)pValue = BassGetStrength(pContext);
+            ALOGVV("%s BASSBOOST_PARAM_STRENGTH %d", __func__, *(int16_t *)pValue);
             break;
 
         default:
-            ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
+            ALOGV("%s invalid param %d", __func__, params[0]);
             status = -EINVAL;
             break;
     }
 
-    //ALOGV("\tBassBoost_getParameter end");
+    ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
     return status;
 } /* end BassBoost_getParameter */
 
@@ -2081,27 +2267,42 @@
 //
 //----------------------------------------------------------------------------
 
-int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue){
+int BassBoost_setParameter(EffectContext *pContext,
+                           uint32_t       paramSize,
+                           void          *pParam,
+                           uint32_t       valueSize,
+                           void          *pValue) {
     int status = 0;
-    int16_t strength;
-    int32_t *pParamTemp = (int32_t *)pParam;
+    int32_t *params = (int32_t *)pParam;
 
-    //ALOGV("\tBassBoost_setParameter start");
+    ALOGVV("%s start", __func__);
 
-    switch (*pParamTemp){
-        case BASSBOOST_PARAM_STRENGTH:
-            strength = *(int16_t *)pValue;
-            //ALOGV("\tBassBoost_setParameter() BASSBOOST_PARAM_STRENGTH value is %d", strength);
-            //ALOGV("\tBassBoost_setParameter() Calling pBassBoost->BassSetStrength");
+    if (paramSize != sizeof(int32_t)) {  // legacy: check equality here.
+        ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+        return -EINVAL;
+    }
+    switch (params[0]) {
+        case BASSBOOST_PARAM_STRENGTH: {
+            if (valueSize < sizeof(int16_t)) {
+                ALOGV("%s BASSBOOST_PARAM_STRENGTH invalid valueSize: %u", __func__, valueSize);
+                status = -EINVAL;
+                break;
+            }
+
+            const int16_t strength = *(int16_t *)pValue;
+            ALOGVV("%s BASSBOOST_PARAM_STRENGTH %d", __func__, strength);
+            ALOGVV("%s BASSBOOST_PARAM_STRENGTH Calling BassSetStrength", __func__);
             BassSetStrength(pContext, (int32_t)strength);
-            //ALOGV("\tBassBoost_setParameter() Called pBassBoost->BassSetStrength");
-           break;
+            ALOGVV("%s BASSBOOST_PARAM_STRENGTH Called BassSetStrength", __func__);
+        } break;
+
         default:
-            ALOGV("\tLVM_ERROR : BassBoost_setParameter() invalid param %d", *pParamTemp);
+            ALOGV("%s invalid param %d", __func__, params[0]);
+            status = -EINVAL;
             break;
     }
 
-    //ALOGV("\tBassBoost_setParameter end");
+    ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
     return status;
 } /* end BassBoost_setParameter */
 
@@ -2126,92 +2327,97 @@
 //
 //----------------------------------------------------------------------------
 
-int Virtualizer_getParameter(EffectContext        *pContext,
-                             void                 *pParam,
-                             uint32_t             *pValueSize,
-                             void                 *pValue){
+int Virtualizer_getParameter(EffectContext *pContext,
+                             uint32_t       paramSize,
+                             void          *pParam,
+                             uint32_t      *pValueSize,
+                             void          *pValue) {
     int status = 0;
-    int32_t *pParamTemp = (int32_t *)pParam;
-    int32_t param = *pParamTemp++;
+    int32_t *params = (int32_t *)pParam;
 
-    //ALOGV("\tVirtualizer_getParameter start");
+    ALOGVV("%s start", __func__);
 
-    switch (param){
-        case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
-            if (*pValueSize != sizeof(uint32_t)){
-                ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize %d",*pValueSize);
-                return -EINVAL;
-            }
-            *pValueSize = sizeof(uint32_t);
-            break;
-        case VIRTUALIZER_PARAM_STRENGTH:
-            if (*pValueSize != sizeof(int16_t)){
-                ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize2 %d",*pValueSize);
-                return -EINVAL;
-            }
-            *pValueSize = sizeof(int16_t);
-            break;
-        case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES:
-            // return value size can only be interpreted as relative to input value,
-            // deferring validity check to below
-            break;
-        case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE:
-            if (*pValueSize != sizeof(uint32_t)){
-                ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize %d",*pValueSize);
-                return -EINVAL;
-            }
-            *pValueSize = sizeof(uint32_t);
-            break;
-        default:
-            ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
-            return -EINVAL;
+    if (paramSize < sizeof(int32_t)) {
+        ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+        return -EINVAL;
     }
-
-    switch (param){
+    switch (params[0]) {
         case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
-            *(uint32_t *)pValue = 1;
+            if (*pValueSize != sizeof(uint32_t)) { // legacy: check equality here.
+                ALOGV("%s VIRTUALIZER_PARAM_STRENGTH_SUPPORTED invalid *pValueSize %u",
+                        __func__, *pValueSize);
+                status = -EINVAL;
+                break;
+            }
+            // no need to set *pValueSize
 
-            //ALOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH_SUPPORTED Value is %d",
-            //        *(uint32_t *)pValue);
+            *(uint32_t *)pValue = 1;
+            ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH_SUPPORTED %d", __func__, *(uint32_t *)pValue);
             break;
 
         case VIRTUALIZER_PARAM_STRENGTH:
+            if (*pValueSize != sizeof(int16_t)) { // legacy: check equality here.
+                ALOGV("%s VIRTUALIZER_PARAM_STRENGTH invalid *pValueSize %u",
+                        __func__, *pValueSize);
+                status = -EINVAL;
+                break;
+            }
+            // no need to set *pValueSize
+
             *(int16_t *)pValue = VirtualizerGetStrength(pContext);
 
-            //ALOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH Value is %d",
-            //        *(int16_t *)pValue);
+            ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH %d", __func__, *(int16_t *)pValue);
             break;
 
         case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES: {
-            const audio_channel_mask_t channelMask = (audio_channel_mask_t) *pParamTemp++;
-            const audio_devices_t deviceType = (audio_devices_t) *pParamTemp;
-            uint32_t nbChannels = audio_channel_count_from_out_mask(channelMask);
-            if (*pValueSize < 3 * nbChannels * sizeof(int32_t)){
-                ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize %d",*pValueSize);
-                return -EINVAL;
+            if (paramSize < 3 * sizeof(int32_t)) {
+                ALOGV("%s VIRTUALIZER_PARAM_SPEAKER_ANGLES invalid paramSize: %u",
+                        __func__, paramSize);
+                status = -EINVAL;
+                break;
             }
+
+            const audio_channel_mask_t channelMask = (audio_channel_mask_t) params[1];
+            const audio_devices_t deviceType = (audio_devices_t) params[2];
+            const uint32_t nbChannels = audio_channel_count_from_out_mask(channelMask);
+            const uint32_t valueSizeRequired = 3 * nbChannels * sizeof(int32_t);
+            if (*pValueSize < valueSizeRequired) {
+                ALOGV("%s VIRTUALIZER_PARAM_SPEAKER_ANGLES invalid *pValueSize %u",
+                        __func__, *pValueSize);
+                status = -EINVAL;
+                break;
+            }
+            *pValueSize = valueSizeRequired;
+
             // verify the configuration is supported
             status = VirtualizerIsConfigurationSupported(channelMask, deviceType);
             if (status == 0) {
-                ALOGV("VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES supports mask=0x%x device=0x%x",
-                        channelMask, deviceType);
+                ALOGV("%s VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES mask=0x%x device=0x%x",
+                        __func__, channelMask, deviceType);
                 // configuration is supported, get the angles
                 VirtualizerGetSpeakerAngles(channelMask, deviceType, (int32_t *)pValue);
             }
-            }
-            break;
+        } break;
 
         case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE:
-            *(uint32_t *)pValue  = (uint32_t) VirtualizerGetVirtualizationMode(pContext);
+            if (*pValueSize != sizeof(uint32_t)) { // legacy: check equality here.
+                ALOGV("%s VIRTUALIZER_PARAM_VIRTUALIZATION_MODE invalid *pValueSize %u",
+                        __func__, *pValueSize);
+                status = -EINVAL;
+                break;
+            }
+            // no need to set *pValueSize
+
+            *(uint32_t *)pValue = (uint32_t) VirtualizerGetVirtualizationMode(pContext);
             break;
 
         default:
-            ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
+            ALOGV("%s invalid param %d", __func__, params[0]);
             status = -EINVAL;
             break;
     }
 
-    ALOGV("\tVirtualizer_getParameter end returning status=%d", status);
+    ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
     return status;
 } /* end Virtualizer_getParameter */
 
@@ -2230,37 +2436,57 @@
 //
 //----------------------------------------------------------------------------
 
-int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValue){
+int Virtualizer_setParameter(EffectContext *pContext,
+                             uint32_t       paramSize,
+                             void          *pParam,
+                             uint32_t       valueSize,
+                             void          *pValue) {
     int status = 0;
-    int16_t strength;
-    int32_t *pParamTemp = (int32_t *)pParam;
-    int32_t param = *pParamTemp++;
+    int32_t *params = (int32_t *)pParam;
 
-    //ALOGV("\tVirtualizer_setParameter start");
+    ALOGVV("%s start", __func__);
 
-    switch (param){
-        case VIRTUALIZER_PARAM_STRENGTH:
-            strength = *(int16_t *)pValue;
-            //ALOGV("\tVirtualizer_setParameter() VIRTUALIZER_PARAM_STRENGTH value is %d", strength);
-            //ALOGV("\tVirtualizer_setParameter() Calling pVirtualizer->setStrength");
+    if (paramSize != sizeof(int32_t)) { // legacy: check equality here.
+        ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+        return -EINVAL;
+    }
+    switch (params[0]) {
+        case VIRTUALIZER_PARAM_STRENGTH: {
+            if (valueSize < sizeof(int16_t)) {
+                ALOGV("%s VIRTUALIZER_PARAM_STRENGTH invalid valueSize: %u", __func__, valueSize);
+                status = -EINVAL;
+                break;
+            }
+
+            const int16_t strength = *(int16_t *)pValue;
+            ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH %d", __func__, strength);
+            ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH Calling VirtualizerSetStrength", __func__);
             VirtualizerSetStrength(pContext, (int32_t)strength);
-            //ALOGV("\tVirtualizer_setParameter() Called pVirtualizer->setStrength");
-           break;
+            ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH Called VirtualizerSetStrength", __func__);
+        } break;
 
         case VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE: {
-            const audio_devices_t deviceType = *(audio_devices_t *) pValue;
-            status = VirtualizerForceVirtualizationMode(pContext, deviceType);
-            //ALOGV("VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE device=0x%x result=%d",
-            //        deviceType, status);
+            if (valueSize < sizeof(int32_t)) {
+                ALOGV("%s VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE invalid valueSize: %u",
+                        __func__, valueSize);
+                android_errorWriteLog(0x534e4554, "64478003");
+                status = -EINVAL;
+                break;
             }
-            break;
+
+            const audio_devices_t deviceType = (audio_devices_t)*(int32_t *)pValue;
+            status = VirtualizerForceVirtualizationMode(pContext, deviceType);
+            ALOGVV("%s VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE device=%#x result=%d",
+                    __func__, deviceType, status);
+        } break;
 
         default:
-            ALOGV("\tLVM_ERROR : Virtualizer_setParameter() invalid param %d", param);
+            ALOGV("%s invalid param %d", __func__, params[0]);
+            status = -EINVAL;
             break;
     }
 
-    //ALOGV("\tVirtualizer_setParameter end");
+    ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
     return status;
 } /* end Virtualizer_setParameter */
 
@@ -2284,174 +2510,215 @@
 // Side Effects:
 //
 //----------------------------------------------------------------------------
-int Equalizer_getParameter(EffectContext     *pContext,
-                           void              *pParam,
-                           uint32_t          *pValueSize,
-                           void              *pValue){
+int Equalizer_getParameter(EffectContext *pContext,
+                           uint32_t       paramSize,
+                           void          *pParam,
+                           uint32_t      *pValueSize,
+                           void          *pValue) {
     int status = 0;
-    int32_t *pParamTemp = (int32_t *)pParam;
-    int32_t param = *pParamTemp++;
-    int32_t param2;
-    char *name;
+    int32_t *params = (int32_t *)pParam;
 
-    //ALOGV("\tEqualizer_getParameter start");
+    ALOGVV("%s start", __func__);
 
-    switch (param) {
+    if (paramSize < sizeof(int32_t)) {
+        ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+        return -EINVAL;
+    }
+    switch (params[0]) {
     case EQ_PARAM_NUM_BANDS:
+        if (*pValueSize < sizeof(uint16_t)) {
+            ALOGV("%s EQ_PARAM_NUM_BANDS invalid *pValueSize %u", __func__, *pValueSize);
+            status = -EINVAL;
+            break;
+        }
+        *pValueSize = sizeof(uint16_t);
+
+        *(uint16_t *)pValue = (uint16_t)FIVEBAND_NUMBANDS;
+        ALOGVV("%s EQ_PARAM_NUM_BANDS %u", __func__, *(uint16_t *)pValue);
+        break;
+
     case EQ_PARAM_CUR_PRESET:
+        if (*pValueSize < sizeof(uint16_t)) {
+            ALOGV("%s EQ_PARAM_CUR_PRESET invalid *pValueSize %u", __func__, *pValueSize);
+            status = -EINVAL;
+            break;
+        }
+        *pValueSize = sizeof(uint16_t);
+
+        *(uint16_t *)pValue = (uint16_t)EqualizerGetPreset(pContext);
+        ALOGVV("%s EQ_PARAM_CUR_PRESET %u", __func__, *(uint16_t *)pValue);
+        break;
+
     case EQ_PARAM_GET_NUM_OF_PRESETS:
-    case EQ_PARAM_BAND_LEVEL:
-    case EQ_PARAM_GET_BAND:
+        if (*pValueSize < sizeof(uint16_t)) {
+            ALOGV("%s EQ_PARAM_GET_NUM_OF_PRESETS invalid *pValueSize %u", __func__, *pValueSize);
+            status = -EINVAL;
+            break;
+        }
+        *pValueSize = sizeof(uint16_t);
+
+        *(uint16_t *)pValue = (uint16_t)EqualizerGetNumPresets();
+        ALOGVV("%s EQ_PARAM_GET_NUM_OF_PRESETS %u", __func__, *(uint16_t *)pValue);
+        break;
+
+    case EQ_PARAM_GET_BAND: {
+        if (paramSize < 2 * sizeof(int32_t)) {
+            ALOGV("%s EQ_PARAM_GET_BAND invalid paramSize: %u", __func__, paramSize);
+            status = -EINVAL;
+            break;
+        }
+        if (*pValueSize < sizeof(uint16_t)) {
+            ALOGV("%s EQ_PARAM_GET_BAND invalid *pValueSize %u", __func__, *pValueSize);
+            status = -EINVAL;
+            break;
+        }
+        *pValueSize = sizeof(uint16_t);
+
+        const int32_t frequency = params[1];
+        *(uint16_t *)pValue = (uint16_t)EqualizerGetBand(pContext, frequency);
+        ALOGVV("%s EQ_PARAM_GET_BAND frequency %d, band %u",
+                __func__, frequency, *(uint16_t *)pValue);
+    } break;
+
+    case EQ_PARAM_BAND_LEVEL: {
+        if (paramSize < 2 * sizeof(int32_t)) {
+            ALOGV("%s EQ_PARAM_BAND_LEVEL invalid paramSize %u", __func__, paramSize);
+            status = -EINVAL;
+            break;
+        }
         if (*pValueSize < sizeof(int16_t)) {
-            ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1  %d", *pValueSize);
-            return -EINVAL;
+            ALOGV("%s EQ_PARAM_BAND_LEVEL invalid *pValueSize %u", __func__, *pValueSize);
+            status = -EINVAL;
+            break;
         }
         *pValueSize = sizeof(int16_t);
-        break;
+
+        const int32_t band = params[1];
+        if (band < 0 || band >= FIVEBAND_NUMBANDS) {
+            if (band < 0) {
+                android_errorWriteLog(0x534e4554, "32438598");
+                ALOGW("%s EQ_PARAM_BAND_LEVEL invalid band %d", __func__, band);
+            }
+            status = -EINVAL;
+            break;
+        }
+        *(int16_t *)pValue = (int16_t)EqualizerGetBandLevel(pContext, band);
+        ALOGVV("%s EQ_PARAM_BAND_LEVEL band %d, level %d",
+                __func__, band, *(int16_t *)pValue);
+    } break;
 
     case EQ_PARAM_LEVEL_RANGE:
         if (*pValueSize < 2 * sizeof(int16_t)) {
-            ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 2  %d", *pValueSize);
-            return -EINVAL;
+            ALOGV("%s EQ_PARAM_LEVEL_RANGE invalid *pValueSize %u", __func__, *pValueSize);
+            status = -EINVAL;
+            break;
         }
         *pValueSize = 2 * sizeof(int16_t);
-        break;
-    case EQ_PARAM_BAND_FREQ_RANGE:
-        if (*pValueSize < 2 * sizeof(int32_t)) {
-            ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 3  %d", *pValueSize);
-            return -EINVAL;
-        }
-        *pValueSize = 2 * sizeof(int32_t);
-        break;
 
-    case EQ_PARAM_CENTER_FREQ:
-        if (*pValueSize < sizeof(int32_t)) {
-            ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 5  %d", *pValueSize);
-            return -EINVAL;
-        }
-        *pValueSize = sizeof(int32_t);
-        break;
-
-    case EQ_PARAM_GET_PRESET_NAME:
-        break;
-
-    case EQ_PARAM_PROPERTIES:
-        if (*pValueSize < (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t)) {
-            ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1  %d", *pValueSize);
-            return -EINVAL;
-        }
-        *pValueSize = (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t);
-        break;
-
-    default:
-        ALOGV("\tLVM_ERROR : Equalizer_getParameter unknown param %d", param);
-        return -EINVAL;
-    }
-
-    switch (param) {
-    case EQ_PARAM_NUM_BANDS:
-        *(uint16_t *)pValue = (uint16_t)FIVEBAND_NUMBANDS;
-        //ALOGV("\tEqualizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
-        break;
-
-    case EQ_PARAM_LEVEL_RANGE:
         *(int16_t *)pValue = -1500;
         *((int16_t *)pValue + 1) = 1500;
-        //ALOGV("\tEqualizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d",
-        //      *(int16_t *)pValue, *((int16_t *)pValue + 1));
+        ALOGVV("%s EQ_PARAM_LEVEL_RANGE min %d, max %d",
+                __func__, *(int16_t *)pValue, *((int16_t *)pValue + 1));
         break;
 
-    case EQ_PARAM_BAND_LEVEL:
-        param2 = *pParamTemp;
-        if (param2 < 0 || param2 >= FIVEBAND_NUMBANDS) {
+    case EQ_PARAM_BAND_FREQ_RANGE: {
+        if (paramSize < 2 * sizeof(int32_t)) {
+            ALOGV("%s EQ_PARAM_BAND_FREQ_RANGE invalid paramSize: %u", __func__, paramSize);
             status = -EINVAL;
-            if (param2 < 0) {
-                android_errorWriteLog(0x534e4554, "32438598");
-                ALOGW("\tERROR Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d", param2);
-            }
             break;
         }
-        *(int16_t *)pValue = (int16_t)EqualizerGetBandLevel(pContext, param2);
-        //ALOGV("\tEqualizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d",
-        //      param2, *(int32_t *)pValue);
-        break;
-
-    case EQ_PARAM_CENTER_FREQ:
-        param2 = *pParamTemp;
-        if (param2 < 0 || param2 >= FIVEBAND_NUMBANDS) {
+        if (*pValueSize < 2 * sizeof(int32_t)) {
+            ALOGV("%s EQ_PARAM_BAND_FREQ_RANGE invalid *pValueSize %u", __func__, *pValueSize);
             status = -EINVAL;
-            if (param2 < 0) {
-                android_errorWriteLog(0x534e4554, "32436341");
-                ALOGW("\tERROR Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d", param2);
-            }
             break;
         }
-        *(int32_t *)pValue = EqualizerGetCentreFrequency(pContext, param2);
-        //ALOGV("\tEqualizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d",
-        //      param2, *(int32_t *)pValue);
-        break;
+        *pValueSize = 2 * sizeof(int32_t);
 
-    case EQ_PARAM_BAND_FREQ_RANGE:
-        param2 = *pParamTemp;
-        if (param2 < 0 || param2 >= FIVEBAND_NUMBANDS) {
-            status = -EINVAL;
-            if (param2 < 0) {
+        const int32_t band = params[1];
+        if (band < 0 || band >= FIVEBAND_NUMBANDS) {
+            if (band < 0) {
                 android_errorWriteLog(0x534e4554, "32247948");
-                ALOGW("\tERROR Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d", param2);
+                ALOGW("%s EQ_PARAM_BAND_FREQ_RANGE invalid band %d",
+                        __func__, band);
             }
-            break;
-        }
-        EqualizerGetBandFreqRange(pContext, param2, (uint32_t *)pValue, ((uint32_t *)pValue + 1));
-        //ALOGV("\tEqualizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
-        //      param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
-        break;
-
-    case EQ_PARAM_GET_BAND:
-        param2 = *pParamTemp;
-        *(uint16_t *)pValue = (uint16_t)EqualizerGetBand(pContext, param2);
-        //ALOGV("\tEqualizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
-        //      param2, *(uint16_t *)pValue);
-        break;
-
-    case EQ_PARAM_CUR_PRESET:
-        *(uint16_t *)pValue = (uint16_t)EqualizerGetPreset(pContext);
-        //ALOGV("\tEqualizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
-        break;
-
-    case EQ_PARAM_GET_NUM_OF_PRESETS:
-        *(uint16_t *)pValue = (uint16_t)EqualizerGetNumPresets();
-        //ALOGV("\tEqualizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
-        break;
-
-    case EQ_PARAM_GET_PRESET_NAME:
-        param2 = *pParamTemp;
-        if ((param2 < 0 && param2 != PRESET_CUSTOM) ||  param2 >= EqualizerGetNumPresets()) {
             status = -EINVAL;
-            if (param2 < 0) {
-                android_errorWriteLog(0x534e4554, "32448258");
-                ALOGE("\tERROR Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d",
-                        param2);
+            break;
+        }
+        EqualizerGetBandFreqRange(pContext, band, (uint32_t *)pValue, ((uint32_t *)pValue + 1));
+        ALOGVV("%s EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
+                __func__, band, *(int32_t *)pValue, *((int32_t *)pValue + 1));
+
+    } break;
+
+    case EQ_PARAM_CENTER_FREQ: {
+        if (paramSize < 2 * sizeof(int32_t)) {
+            ALOGV("%s EQ_PARAM_CENTER_FREQ invalid paramSize: %u", __func__, paramSize);
+            status = -EINVAL;
+            break;
+        }
+        if (*pValueSize < sizeof(int32_t)) {
+            ALOGV("%s EQ_PARAM_CENTER_FREQ invalid *pValueSize %u", __func__, *pValueSize);
+            status = -EINVAL;
+            break;
+        }
+        *pValueSize = sizeof(int32_t);
+
+        const int32_t band = params[1];
+        if (band < 0 || band >= FIVEBAND_NUMBANDS) {
+            status = -EINVAL;
+            if (band < 0) {
+                android_errorWriteLog(0x534e4554, "32436341");
+                ALOGW("%s EQ_PARAM_CENTER_FREQ invalid band %d", __func__, band);
             }
             break;
         }
+        *(int32_t *)pValue = EqualizerGetCentreFrequency(pContext, band);
+        ALOGVV("%s EQ_PARAM_CENTER_FREQ band %d, frequency %d",
+                __func__, band, *(int32_t *)pValue);
+    } break;
 
+    case EQ_PARAM_GET_PRESET_NAME: {
+        if (paramSize < 2 * sizeof(int32_t)) {
+            ALOGV("%s EQ_PARAM_PRESET_NAME invalid paramSize: %u", __func__, paramSize);
+            status = -EINVAL;
+            break;
+        }
         if (*pValueSize < 1) {
-            status = -EINVAL;
             android_errorWriteLog(0x534e4554, "37536407");
+            status = -EINVAL;
             break;
         }
 
-        name = (char *)pValue;
-        strncpy(name, EqualizerGetPresetName(param2), *pValueSize - 1);
+        const int32_t preset = params[1];
+        if ((preset < 0 && preset != PRESET_CUSTOM) ||  preset >= EqualizerGetNumPresets()) {
+            if (preset < 0) {
+                android_errorWriteLog(0x534e4554, "32448258");
+                ALOGE("%s EQ_PARAM_GET_PRESET_NAME preset %d", __func__, preset);
+            }
+            status = -EINVAL;
+            break;
+        }
+
+        char * const name = (char *)pValue;
+        strncpy(name, EqualizerGetPresetName(preset), *pValueSize - 1);
         name[*pValueSize - 1] = 0;
         *pValueSize = strlen(name) + 1;
-        //ALOGV("\tEqualizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
-        //      param2, gEqualizerPresets[param2].name, *pValueSize);
-        break;
+        ALOGVV("%s EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
+                __func__, preset, gEqualizerPresets[preset].name, *pValueSize);
+
+    } break;
 
     case EQ_PARAM_PROPERTIES: {
+        constexpr uint32_t requiredValueSize = (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t);
+        if (*pValueSize < requiredValueSize) {
+            ALOGV("%s EQ_PARAM_PROPERTIES invalid *pValueSize %u", __func__, *pValueSize);
+            status = -EINVAL;
+            break;
+        }
+        *pValueSize = requiredValueSize;
+
         int16_t *p = (int16_t *)pValue;
-        ALOGV("\tEqualizer_getParameter() EQ_PARAM_PROPERTIES");
+        ALOGV("%s EQ_PARAM_PROPERTIES", __func__);
         p[0] = (int16_t)EqualizerGetPreset(pContext);
         p[1] = (int16_t)FIVEBAND_NUMBANDS;
         for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
@@ -2460,12 +2727,12 @@
     } break;
 
     default:
-        ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid param %d", param);
+        ALOGV("%s invalid param %d", __func__, params[0]);
         status = -EINVAL;
         break;
     }
 
-    //GV("\tEqualizer_getParameter end\n");
+    ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
     return status;
 } /* end Equalizer_getParameter */
 
@@ -2485,74 +2752,89 @@
 // Outputs:
 //
 //----------------------------------------------------------------------------
-int Equalizer_setParameter (EffectContext *pContext,
-                            void *pParam,
-                            uint32_t valueSize,
-                            void *pValue) {
+int Equalizer_setParameter(EffectContext *pContext,
+                           uint32_t       paramSize,
+                           void          *pParam,
+                           uint32_t       valueSize,
+                           void          *pValue) {
     int status = 0;
-    int32_t preset;
-    int32_t band;
-    int32_t level;
-    int32_t *pParamTemp = (int32_t *)pParam;
-    int32_t param = *pParamTemp++;
+    int32_t *params = (int32_t *)pParam;
 
+    ALOGVV("%s start", __func__);
 
-    //ALOGV("\tEqualizer_setParameter start");
-    switch (param) {
-    case EQ_PARAM_CUR_PRESET:
+    if (paramSize < sizeof(int32_t)) {
+        ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+        return -EINVAL;
+    }
+    switch (params[0]) {
+    case EQ_PARAM_CUR_PRESET: {
         if (valueSize < sizeof(int16_t)) {
-          status = -EINVAL;
-          break;
+            ALOGV("%s EQ_PARAM_CUR_PRESET invalid valueSize %u", __func__, valueSize);
+            status = -EINVAL;
+            break;
         }
-        preset = (int32_t)(*(uint16_t *)pValue);
+        const int32_t preset = (int32_t)*(uint16_t *)pValue;
 
-        //ALOGV("\tEqualizer_setParameter() EQ_PARAM_CUR_PRESET %d", preset);
-        if ((preset >= EqualizerGetNumPresets())||(preset < 0)) {
+        ALOGVV("%s EQ_PARAM_CUR_PRESET %d", __func__, preset);
+        if (preset >= EqualizerGetNumPresets() || preset < 0) {
+            ALOGV("%s EQ_PARAM_CUR_PRESET invalid preset %d", __func__, preset);
             status = -EINVAL;
             break;
         }
         EqualizerSetPreset(pContext, preset);
-        break;
-    case EQ_PARAM_BAND_LEVEL:
-        if (valueSize < sizeof(int16_t)) {
-          status = -EINVAL;
-          break;
-        }
-        band =  *pParamTemp;
-        level = (int32_t)(*(int16_t *)pValue);
-        //ALOGV("\tEqualizer_setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
-        if (band < 0 || band >= FIVEBAND_NUMBANDS) {
+    } break;
+
+    case EQ_PARAM_BAND_LEVEL: {
+        if (paramSize < 2 * sizeof(int32_t)) {
+            ALOGV("%s EQ_PARAM_BAND_LEVEL invalid paramSize: %u", __func__, paramSize);
             status = -EINVAL;
+            break;
+        }
+        if (valueSize < sizeof(int16_t)) {
+            ALOGV("%s EQ_PARAM_BAND_LEVEL invalid valueSize %u", __func__, valueSize);
+            status = -EINVAL;
+            break;
+        }
+        const int32_t band =  params[1];
+        const int32_t level = (int32_t)*(int16_t *)pValue;
+        ALOGVV("%s EQ_PARAM_BAND_LEVEL band %d, level %d", __func__, band, level);
+        if (band < 0 || band >= FIVEBAND_NUMBANDS) {
             if (band < 0) {
                 android_errorWriteLog(0x534e4554, "32095626");
-                ALOGE("\tERROR Equalizer_setParameter() EQ_PARAM_BAND_LEVEL band %d", band);
+                ALOGE("%s EQ_PARAM_BAND_LEVEL invalid band %d", __func__, band);
             }
+            status = -EINVAL;
             break;
         }
         EqualizerSetBandLevel(pContext, band, level);
-        break;
+    } break;
+
     case EQ_PARAM_PROPERTIES: {
-        //ALOGV("\tEqualizer_setParameter() EQ_PARAM_PROPERTIES");
+        ALOGVV("%s EQ_PARAM_PROPERTIES", __func__);
         if (valueSize < sizeof(int16_t)) {
-          status = -EINVAL;
-          break;
+            ALOGV("%s EQ_PARAM_PROPERTIES invalid valueSize %u", __func__, valueSize);
+            status = -EINVAL;
+            break;
         }
         int16_t *p = (int16_t *)pValue;
         if ((int)p[0] >= EqualizerGetNumPresets()) {
+            ALOGV("%s EQ_PARAM_PROPERTIES invalid preset %d", __func__, (int)p[0]);
             status = -EINVAL;
             break;
         }
         if (p[0] >= 0) {
             EqualizerSetPreset(pContext, (int)p[0]);
         } else {
-            if (valueSize < (2 + FIVEBAND_NUMBANDS) * sizeof(int16_t)) {
+            constexpr uint32_t valueSizeRequired = (2 + FIVEBAND_NUMBANDS) * sizeof(int16_t);
+            if (valueSize < valueSizeRequired) {
               android_errorWriteLog(0x534e4554, "37563371");
-              ALOGE("\tERROR Equalizer_setParameter() EQ_PARAM_PROPERTIES valueSize %d < %d",
-                    (int)valueSize, (int)((2 + FIVEBAND_NUMBANDS) * sizeof(int16_t)));
+              ALOGE("%s EQ_PARAM_PROPERTIES invalid valueSize %u < %u",
+                      __func__, valueSize, valueSizeRequired);
               status = -EINVAL;
               break;
             }
             if ((int)p[1] != FIVEBAND_NUMBANDS) {
+                ALOGV("%s EQ_PARAM_PROPERTIES invalid bands %d", __func__, (int)p[1]);
                 status = -EINVAL;
                 break;
             }
@@ -2561,13 +2843,14 @@
             }
         }
     } break;
+
     default:
-        ALOGV("\tLVM_ERROR : Equalizer_setParameter() invalid param %d", param);
+        ALOGV("%s invalid param %d", __func__, params[0]);
         status = -EINVAL;
         break;
     }
 
-    //ALOGV("\tEqualizer_setParameter end");
+    ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
     return status;
 } /* end Equalizer_setParameter */
 
@@ -2592,79 +2875,92 @@
 //
 //----------------------------------------------------------------------------
 
-int Volume_getParameter(EffectContext     *pContext,
-                        void              *pParam,
-                        uint32_t          *pValueSize,
-                        void              *pValue){
+int Volume_getParameter(EffectContext *pContext,
+                        uint32_t       paramSize,
+                        void          *pParam,
+                        uint32_t      *pValueSize,
+                        void          *pValue) {
     int status = 0;
-    int32_t *pParamTemp = (int32_t *)pParam;
-    int32_t param = *pParamTemp++;;
+    int32_t *params = (int32_t *)pParam;
 
-    //ALOGV("\tVolume_getParameter start");
+    ALOGVV("%s start", __func__);
 
-    switch (param){
+    if (paramSize < sizeof(int32_t)) {
+        ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+        return -EINVAL;
+    }
+    switch (params[0]) {
         case VOLUME_PARAM_LEVEL:
-        case VOLUME_PARAM_MAXLEVEL:
-        case VOLUME_PARAM_STEREOPOSITION:
-            if (*pValueSize != sizeof(int16_t)){
-                ALOGV("\tLVM_ERROR : Volume_getParameter() invalid pValueSize 1  %d", *pValueSize);
-                return -EINVAL;
+            if (*pValueSize != sizeof(int16_t)) { // legacy: check equality here.
+                ALOGV("%s VOLUME_PARAM_LEVEL invalid *pValueSize %u", __func__, *pValueSize);
+                status = -EINVAL;
+                break;
             }
-            *pValueSize = sizeof(int16_t);
+            // no need to set *pValueSize
+
+            status = VolumeGetVolumeLevel(pContext, (int16_t *)(pValue));
+            ALOGVV("%s VOLUME_PARAM_LEVEL %d", __func__, *(int16_t *)pValue);
+            break;
+
+        case VOLUME_PARAM_MAXLEVEL:
+            if (*pValueSize != sizeof(int16_t)) { // legacy: check equality here.
+                ALOGV("%s VOLUME_PARAM_MAXLEVEL invalid *pValueSize %u", __func__, *pValueSize);
+                status = -EINVAL;
+                break;
+            }
+            // no need to set *pValueSize
+
+            // in millibel
+            *(int16_t *)pValue = 0;
+            ALOGVV("%s VOLUME_PARAM_MAXLEVEL %d", __func__, *(int16_t *)pValue);
+            break;
+
+        case VOLUME_PARAM_STEREOPOSITION:
+            if (*pValueSize != sizeof(int16_t)) { // legacy: check equality here.
+                ALOGV("%s VOLUME_PARAM_STEREOPOSITION invalid *pValueSize %u",
+                        __func__, *pValueSize);
+                status = -EINVAL;
+                break;
+            }
+            // no need to set *pValueSize
+
+            VolumeGetStereoPosition(pContext, (int16_t *)pValue);
+            ALOGVV("%s VOLUME_PARAM_STEREOPOSITION %d", __func__, *(int16_t *)pValue);
             break;
 
         case VOLUME_PARAM_MUTE:
+            if (*pValueSize < sizeof(uint32_t)) {
+                ALOGV("%s VOLUME_PARAM_MUTE invalid *pValueSize %u", __func__, *pValueSize);
+                status = -EINVAL;
+                break;
+            }
+            *pValueSize = sizeof(uint32_t);
+
+            status = VolumeGetMute(pContext, (uint32_t *)pValue);
+            ALOGV("%s VOLUME_PARAM_MUTE %u", __func__, *(uint32_t *)pValue);
+            break;
+
         case VOLUME_PARAM_ENABLESTEREOPOSITION:
-            if (*pValueSize < sizeof(int32_t)){
-                ALOGV("\tLVM_ERROR : Volume_getParameter() invalid pValueSize 2  %d", *pValueSize);
-                return -EINVAL;
+            if (*pValueSize < sizeof(int32_t)) {
+                ALOGV("%s VOLUME_PARAM_ENABLESTEREOPOSITION invalid *pValueSize %u",
+                        __func__, *pValueSize);
+                status = -EINVAL;
+                break;
             }
             *pValueSize = sizeof(int32_t);
-            break;
 
-        default:
-            ALOGV("\tLVM_ERROR : Volume_getParameter unknown param %d", param);
-            return -EINVAL;
-    }
-
-    switch (param){
-        case VOLUME_PARAM_LEVEL:
-            status = VolumeGetVolumeLevel(pContext, (int16_t *)(pValue));
-            //ALOGV("\tVolume_getParameter() VOLUME_PARAM_LEVEL Value is %d",
-            //        *(int16_t *)pValue);
-            break;
-
-        case VOLUME_PARAM_MAXLEVEL:
-            *(int16_t *)pValue = 0;
-            //ALOGV("\tVolume_getParameter() VOLUME_PARAM_MAXLEVEL Value is %d",
-            //        *(int16_t *)pValue);
-            break;
-
-        case VOLUME_PARAM_STEREOPOSITION:
-            VolumeGetStereoPosition(pContext, (int16_t *)pValue);
-            //ALOGV("\tVolume_getParameter() VOLUME_PARAM_STEREOPOSITION Value is %d",
-            //        *(int16_t *)pValue);
-            break;
-
-        case VOLUME_PARAM_MUTE:
-            status = VolumeGetMute(pContext, (uint32_t *)pValue);
-            ALOGV("\tVolume_getParameter() VOLUME_PARAM_MUTE Value is %d",
-                    *(uint32_t *)pValue);
-            break;
-
-        case VOLUME_PARAM_ENABLESTEREOPOSITION:
             *(int32_t *)pValue = pContext->pBundledContext->bStereoPositionEnabled;
-            //ALOGV("\tVolume_getParameter() VOLUME_PARAM_ENABLESTEREOPOSITION Value is %d",
-            //        *(uint32_t *)pValue);
+            ALOGVV("%s VOLUME_PARAM_ENABLESTEREOPOSITION %d", __func__, *(int32_t *)pValue);
+
             break;
 
         default:
-            ALOGV("\tLVM_ERROR : Volume_getParameter() invalid param %d", param);
+            ALOGV("%s invalid param %d", __func__, params[0]);
             status = -EINVAL;
             break;
     }
 
-    //ALOGV("\tVolume_getParameter end");
+    ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
     return status;
 } /* end Volume_getParameter */
 
@@ -2684,55 +2980,87 @@
 //
 //----------------------------------------------------------------------------
 
-int Volume_setParameter (EffectContext *pContext, void *pParam, void *pValue){
-    int      status = 0;
-    int16_t  level;
-    int16_t  position;
-    uint32_t mute;
-    uint32_t positionEnabled;
-    int32_t *pParamTemp = (int32_t *)pParam;
-    int32_t param = *pParamTemp++;
+int Volume_setParameter(EffectContext *pContext,
+                        uint32_t       paramSize,
+                        void          *pParam,
+                        uint32_t       valueSize,
+                        void          *pValue) {
+    int status = 0;
+    int32_t *params = (int32_t *)pParam;
 
-    //ALOGV("\tVolume_setParameter start");
+    ALOGVV("%s start", __func__);
 
-    switch (param){
-        case VOLUME_PARAM_LEVEL:
-            level = *(int16_t *)pValue;
-            //ALOGV("\tVolume_setParameter() VOLUME_PARAM_LEVEL value is %d", level);
-            //ALOGV("\tVolume_setParameter() Calling pVolume->setVolumeLevel");
-            status = VolumeSetVolumeLevel(pContext, (int16_t)level);
-            //ALOGV("\tVolume_setParameter() Called pVolume->setVolumeLevel");
-            break;
+    if (paramSize < sizeof(int32_t)) {
+        ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+        return -EINVAL;
+    }
+    switch (params[0]) {
+        case VOLUME_PARAM_LEVEL: {
+            if (valueSize < sizeof(int16_t)) {
+                ALOGV("%s VOLUME_PARAM_LEVEL invalid valueSize %u", __func__, valueSize);
+                status = -EINVAL;
+                break;
+            }
 
-        case VOLUME_PARAM_MUTE:
-            mute = *(uint32_t *)pValue;
-            //ALOGV("\tVolume_setParameter() Calling pVolume->setMute, mute is %d", mute);
-            //ALOGV("\tVolume_setParameter() Calling pVolume->setMute");
+            const int16_t level = *(int16_t *)pValue;
+            ALOGVV("%s VOLUME_PARAM_LEVEL %d", __func__, level);
+            ALOGVV("%s VOLUME_PARAM_LEVEL Calling VolumeSetVolumeLevel", __func__);
+            status = VolumeSetVolumeLevel(pContext, level);
+            ALOGVV("%s VOLUME_PARAM_LEVEL Called VolumeSetVolumeLevel", __func__);
+        } break;
+
+        case VOLUME_PARAM_MUTE: {
+            if (valueSize < sizeof(uint32_t)) {
+                ALOGV("%s VOLUME_PARAM_MUTE invalid valueSize %u", __func__, valueSize);
+                android_errorWriteLog(0x534e4554, "64477217");
+                status = -EINVAL;
+                break;
+            }
+
+            const uint32_t mute = *(uint32_t *)pValue;
+            ALOGVV("%s VOLUME_PARAM_MUTE %d", __func__, mute);
+            ALOGVV("%s VOLUME_PARAM_MUTE Calling VolumeSetMute", __func__);
             status = VolumeSetMute(pContext, mute);
-            //ALOGV("\tVolume_setParameter() Called pVolume->setMute");
-            break;
+            ALOGVV("%s VOLUME_PARAM_MUTE Called VolumeSetMute", __func__);
+        } break;
 
-        case VOLUME_PARAM_ENABLESTEREOPOSITION:
-            positionEnabled = *(uint32_t *)pValue;
-            (void) VolumeEnableStereoPosition(pContext, positionEnabled);
-            (void) VolumeSetStereoPosition(pContext, pContext->pBundledContext->positionSaved);
-            //ALOGV("\tVolume_setParameter() VOLUME_PARAM_ENABLESTEREOPOSITION called");
-            break;
+        case VOLUME_PARAM_ENABLESTEREOPOSITION: {
+            if (valueSize < sizeof(uint32_t)) {
+                ALOGV("%s VOLUME_PARAM_ENABLESTEREOPOSITION invalid valueSize %u",
+                        __func__, valueSize);
+                status = -EINVAL;
+                break;
+            }
 
-        case VOLUME_PARAM_STEREOPOSITION:
-            position = *(int16_t *)pValue;
-            //ALOGV("\tVolume_setParameter() VOLUME_PARAM_STEREOPOSITION value is %d", position);
-            //ALOGV("\tVolume_setParameter() Calling pVolume->VolumeSetStereoPosition");
-            status = VolumeSetStereoPosition(pContext, (int16_t)position);
-            //ALOGV("\tVolume_setParameter() Called pVolume->VolumeSetStereoPosition");
-            break;
+            const uint32_t positionEnabled = *(uint32_t *)pValue;
+            status = VolumeEnableStereoPosition(pContext, positionEnabled)
+                    ?: VolumeSetStereoPosition(pContext, pContext->pBundledContext->positionSaved);
+            ALOGVV("%s VOLUME_PARAM_ENABLESTEREOPOSITION called", __func__);
+        } break;
+
+        case VOLUME_PARAM_STEREOPOSITION: {
+            if (valueSize < sizeof(int16_t)) {
+                ALOGV("%s VOLUME_PARAM_STEREOPOSITION invalid valueSize %u", __func__, valueSize);
+                status = -EINVAL;
+                break;
+            }
+
+            const int16_t position = *(int16_t *)pValue;
+            ALOGVV("%s VOLUME_PARAM_STEREOPOSITION %d", __func__, position);
+            ALOGVV("%s VOLUME_PARAM_STEREOPOSITION Calling VolumeSetStereoPosition",
+                    __func__);
+            status = VolumeSetStereoPosition(pContext, position);
+            ALOGVV("%s VOLUME_PARAM_STEREOPOSITION Called VolumeSetStereoPosition",
+                    __func__);
+        } break;
 
         default:
-            ALOGV("\tLVM_ERROR : Volume_setParameter() invalid param %d", param);
+            ALOGV("%s invalid param %d", __func__, params[0]);
+            status = -EINVAL;
             break;
     }
 
-    //ALOGV("\tVolume_setParameter end");
+    ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
     return status;
 } /* end Volume_setParameter */
 
@@ -3050,6 +3378,13 @@
     return status;
 }   /* end Effect_process */
 
+// The value offset of an effect parameter is computed by rounding up
+// the parameter size to the next 32 bit alignment.
+static inline uint32_t computeParamVOffset(const effect_param_t *p) {
+    return ((p->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) *
+            sizeof(int32_t);
+}
+
 /* Effect Control Interface Implementation: Command */
 int Effect_command(effect_handle_t  self,
                               uint32_t            cmdCode,
@@ -3160,8 +3495,7 @@
                 ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: psize too big");
                 return -EINVAL;
             }
-            uint32_t paddedParamSize = ((p->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) *
-                    sizeof(int32_t);
+            const uint32_t paddedParamSize = computeParamVOffset(p);
             if ((EFFECT_PARAM_SIZE_MAX - sizeof(effect_param_t) < paddedParamSize) ||
                 (EFFECT_PARAM_SIZE_MAX - sizeof(effect_param_t) - paddedParamSize <
                     p->vsize)) {
@@ -3183,6 +3517,7 @@
             uint32_t voffset = paddedParamSize;
             if(pContext->EffectType == LVM_BASS_BOOST){
                 p->status = android::BassBoost_getParameter(pContext,
+                                                            p->psize,
                                                             p->data,
                                                             &p->vsize,
                                                             p->data + voffset);
@@ -3195,6 +3530,7 @@
 
             if(pContext->EffectType == LVM_VIRTUALIZER){
                 p->status = android::Virtualizer_getParameter(pContext,
+                                                              p->psize,
                                                               (void *)p->data,
                                                               &p->vsize,
                                                               p->data + voffset);
@@ -3209,6 +3545,7 @@
                 //ALOGV("\tEqualizer_command cmdCode Case: "
                 //        "EFFECT_CMD_GET_PARAM start");
                 p->status = android::Equalizer_getParameter(pContext,
+                                                            p->psize,
                                                             p->data,
                                                             &p->vsize,
                                                             p->data + voffset);
@@ -3223,6 +3560,7 @@
             if(pContext->EffectType == LVM_VOLUME){
                 //ALOGV("\tVolume_command cmdCode Case: EFFECT_CMD_GET_PARAM start");
                 p->status = android::Volume_getParameter(pContext,
+                                                         p->psize,
                                                          (void *)p->data,
                                                          &p->vsize,
                                                          p->data + voffset);
@@ -3252,13 +3590,9 @@
                             "EFFECT_CMD_SET_PARAM: ERROR");
                     return -EINVAL;
                 }
-                effect_param_t *p = (effect_param_t *) pCmdData;
 
-                if (p->psize != sizeof(int32_t)){
-                    ALOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
-                            "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
-                    return -EINVAL;
-                }
+                effect_param_t * const p = (effect_param_t *) pCmdData;
+                const uint32_t voffset = computeParamVOffset(p);
 
                 //ALOGV("\tnBassBoost_command cmdSize is %d\n"
                 //        "\tsizeof(effect_param_t) is  %d\n"
@@ -3268,8 +3602,10 @@
                 //        cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
 
                 *(int *)pReplyData = android::BassBoost_setParameter(pContext,
-                                                                    (void *)p->data,
-                                                                    p->data + p->psize);
+                                                                     p->psize,
+                                                                     (void *)p->data,
+                                                                     p->vsize,
+                                                                     p->data + voffset);
             }
             if(pContext->EffectType == LVM_VIRTUALIZER){
               // Warning this log will fail to properly read an int32_t value, assumes int16_t
@@ -3287,13 +3623,9 @@
                             "EFFECT_CMD_SET_PARAM: ERROR");
                     return -EINVAL;
                 }
-                effect_param_t *p = (effect_param_t *) pCmdData;
 
-                if (p->psize != sizeof(int32_t)){
-                    ALOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
-                            "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
-                    return -EINVAL;
-                }
+                effect_param_t * const p = (effect_param_t *) pCmdData;
+                const uint32_t voffset = computeParamVOffset(p);
 
                 //ALOGV("\tnVirtualizer_command cmdSize is %d\n"
                 //        "\tsizeof(effect_param_t) is  %d\n"
@@ -3303,8 +3635,10 @@
                 //        cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
 
                 *(int *)pReplyData = android::Virtualizer_setParameter(pContext,
-                                                                      (void *)p->data,
-                                                                       p->data + p->psize);
+                                                                       p->psize,
+                                                                       (void *)p->data,
+                                                                       p->vsize,
+                                                                       p->data + voffset);
             }
             if(pContext->EffectType == LVM_EQUALIZER){
                //ALOGV("\tEqualizer_command cmdCode Case: "
@@ -3320,12 +3654,15 @@
                             "EFFECT_CMD_SET_PARAM: ERROR");
                     return -EINVAL;
                 }
-                effect_param_t *p = (effect_param_t *) pCmdData;
+
+                effect_param_t * const p = (effect_param_t *) pCmdData;
+                const uint32_t voffset = computeParamVOffset(p);
 
                 *(int *)pReplyData = android::Equalizer_setParameter(pContext,
-                                                                    (void *)p->data,
-                                                                    p->vsize,
-                                                                    p->data + p->psize);
+                                                                     p->psize,
+                                                                     (void *)p->data,
+                                                                     p->vsize,
+                                                                     p->data + voffset);
             }
             if(pContext->EffectType == LVM_VOLUME){
                 //ALOGV("\tVolume_command cmdCode Case: EFFECT_CMD_SET_PARAM start");
@@ -3342,11 +3679,15 @@
                             "EFFECT_CMD_SET_PARAM: ERROR");
                     return -EINVAL;
                 }
-                effect_param_t *p = (effect_param_t *) pCmdData;
+
+                effect_param_t * const p = (effect_param_t *) pCmdData;
+                const uint32_t voffset = computeParamVOffset(p);
 
                 *(int *)pReplyData = android::Volume_setParameter(pContext,
-                                                                 (void *)p->data,
-                                                                 p->data + p->psize);
+                                                                  p->psize,
+                                                                  (void *)p->data,
+                                                                  p->vsize,
+                                                                  p->data + voffset);
             }
             //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM end");
         } break;
@@ -3493,10 +3834,10 @@
             if(rightdB > maxdB){
                 maxdB = rightdB;
             }
-            //ALOGV("\tEFFECT_CMD_SET_VOLUME Session: %d, SessionID: %d VOLUME is %d dB (%d), "
+            //ALOGV("\tEFFECT_CMD_SET_VOLUME Session: %d, SessionID: %d VOLUME is %d dB, "
             //      "effect is %d",
             //pContext->pBundledContext->SessionNo, pContext->pBundledContext->SessionId,
-            //(int32_t)maxdB, maxVol<<7, pContext->EffectType);
+            //(int32_t)maxdB, pContext->EffectType);
             //ALOGV("\tEFFECT_CMD_SET_VOLUME: Left is %d, Right is %d", leftVolume, rightVolume);
             //ALOGV("\tEFFECT_CMD_SET_VOLUME: Left %ddB, Right %ddB, Position %ddB",
             //        leftdB, rightdB, pandB);
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index ee604eb..291383a 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -103,6 +103,10 @@
     FILE                            *PcmInPtr;
     FILE                            *PcmOutPtr;
     #endif
+    #ifdef BUILD_FLOAT
+    LVM_FLOAT                       *pInputBuffer;
+    LVM_FLOAT                       *pOutputBuffer;
+    #endif
 };
 
 /* SessionContext : One session */
@@ -209,7 +213,7 @@
 static const float LimitLevel_bassBoostEnergyCrossCoefficient[FIVEBAND_NUMBANDS] = {
         221.21, 208.10, 28.16, 0.0, 0.0 };
 
-static const float LimitLevel_bassBoostEnergyCoefficient = 7.12;
+static const float LimitLevel_bassBoostEnergyCoefficient = 9.00;
 
 static const float LimitLevel_virtualizerContribution = 1.9;
 
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 6d7d4cd..ee9406d 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -14,7 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#ifndef LVM_FLOAT
+typedef float LVM_FLOAT;
+#endif
 #define LOG_TAG "Reverb"
 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array)[0])
 //#define LOG_NDEBUG 0
@@ -152,6 +154,8 @@
     LVM_Fs_en                       SampleRate;
     LVM_INT32                       *InFrames32;
     LVM_INT32                       *OutFrames32;
+    size_t                          bufferSizeIn;
+    size_t                          bufferSizeOut;
     bool                            auxiliary;
     bool                            preset;
     uint16_t                        curPreset;
@@ -172,8 +176,11 @@
 
 #define REVERB_DEFAULT_PRESET REVERB_PRESET_NONE
 
-
+#ifdef BUILD_FLOAT
+#define REVERB_SEND_LEVEL   0.75f // 0.75 in 4.12 format
+#else
 #define REVERB_SEND_LEVEL   (0x0C00) // 0.75 in 4.12 format
+#endif
 #define REVERB_UNIT_VOLUME  (0x1000) // 1.0 in 4.12 format
 
 //--- local function prototypes
@@ -270,8 +277,15 @@
 
 
     // Allocate memory for reverb process (*2 is for STEREO)
-    pContext->InFrames32  = (LVM_INT32 *)malloc(LVREV_MAX_FRAME_SIZE * sizeof(LVM_INT32) * 2);
-    pContext->OutFrames32 = (LVM_INT32 *)malloc(LVREV_MAX_FRAME_SIZE * sizeof(LVM_INT32) * 2);
+#ifdef BUILD_FLOAT
+    pContext->bufferSizeIn = LVREV_MAX_FRAME_SIZE * sizeof(float) * 2;
+    pContext->bufferSizeOut = pContext->bufferSizeIn;
+#else
+    pContext->bufferSizeIn = LVREV_MAX_FRAME_SIZE * sizeof(LVM_INT32) * 2;
+    pContext->bufferSizeOut = pContext->bufferSizeIn;
+#endif
+    pContext->InFrames32  = (LVM_INT32 *)malloc(pContext->bufferSizeIn);
+    pContext->OutFrames32 = (LVM_INT32 *)malloc(pContext->bufferSizeOut);
 
     ALOGV("\tEffectCreate %p, size %zu", pContext, sizeof(ReverbContext));
     ALOGV("\tEffectCreate end\n");
@@ -293,6 +307,8 @@
     #endif
     free(pContext->InFrames32);
     free(pContext->OutFrames32);
+    pContext->bufferSizeIn = 0;
+    pContext->bufferSizeOut = 0;
     Reverb_free(pContext);
     delete pContext;
     return 0;
@@ -389,6 +405,46 @@
 }
 #endif
 
+#ifdef BUILD_FLOAT
+/**********************************************************************************
+   FUNCTION INT16LTOFLOAT
+***********************************************************************************/
+// Todo: need to write function descriptor
+static void Int16ToFloat(const LVM_INT16 *src, LVM_FLOAT *dst, size_t n) {
+    size_t ii;
+    src += n-1;
+    dst += n-1;
+    for (ii = n; ii != 0; ii--) {
+        *dst = ((LVM_FLOAT)((LVM_INT16)*src)) / 32768.0f;
+        src--;
+        dst--;
+    }
+    return;
+}
+/**********************************************************************************
+   FUNCTION FLOATTOINT16_SAT
+***********************************************************************************/
+// Todo : Need to write function descriptor
+static void FloatToInt16_SAT(const LVM_FLOAT *src, LVM_INT16 *dst, size_t n) {
+    size_t ii;
+    LVM_INT32 temp;
+
+    for (ii = 0; ii < n; ii++) {
+        temp = (LVM_INT32)((*src) * 32768.0f);
+        if (temp >= 32767) {
+            *dst = 32767;
+        } else if (temp <= -32768) {
+            *dst = -32768;
+        } else {
+            *dst = (LVM_INT16)temp;
+        }
+        src++;
+        dst++;
+    }
+    return;
+}
+#endif
+
 static inline int16_t clamp16(int32_t sample)
 {
     if ((sample>>15) ^ (sample>>31))
@@ -422,8 +478,31 @@
     LVM_INT16               samplesPerFrame = 1;
     LVREV_ReturnStatus_en   LvmStatus = LVREV_SUCCESS;              /* Function call status */
     LVM_INT16 *OutFrames16;
+#ifdef BUILD_FLOAT
+    LVM_FLOAT               *pInputBuff;
+    LVM_FLOAT               *pOutputBuff;
+#endif
 
-
+#ifdef BUILD_FLOAT
+    if (pContext->InFrames32 == NULL ||
+            pContext->bufferSizeIn < frameCount * sizeof(float) * 2) {
+        if (pContext->InFrames32 != NULL) {
+            free(pContext->InFrames32);
+        }
+        pContext->bufferSizeIn = frameCount * sizeof(float) * 2;
+        pContext->InFrames32 = (LVM_INT32 *)malloc(pContext->bufferSizeIn);
+    }
+    if (pContext->OutFrames32 == NULL ||
+            pContext->bufferSizeOut < frameCount * sizeof(float) * 2) {
+        if (pContext->OutFrames32 != NULL) {
+            free(pContext->OutFrames32);
+        }
+        pContext->bufferSizeOut = frameCount * sizeof(float) * 2;
+        pContext->OutFrames32 = (LVM_INT32 *)malloc(pContext->bufferSizeOut);
+    }
+    pInputBuff = (float *)pContext->InFrames32;
+    pOutputBuff = (float *)pContext->OutFrames32;
+#endif
     // Check that the input is either mono or stereo
     if (pContext->config.inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO) {
         samplesPerFrame = 2;
@@ -449,49 +528,84 @@
         Reverb_LoadPreset(pContext);
     }
 
-
-
     // Convert to Input 32 bits
     if (pContext->auxiliary) {
+#ifdef BUILD_FLOAT
+        Int16ToFloat(pIn, pInputBuff, frameCount * samplesPerFrame);
+#else
         for(int i=0; i<frameCount*samplesPerFrame; i++){
             pContext->InFrames32[i] = (LVM_INT32)pIn[i]<<8;
         }
-    } else {
+#endif
+        } else {
         // insert reverb input is always stereo
         for (int i = 0; i < frameCount; i++) {
+#ifndef BUILD_FLOAT
             pContext->InFrames32[2*i] = (pIn[2*i] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
             pContext->InFrames32[2*i+1] = (pIn[2*i+1] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
+#else
+            pInputBuff[2 * i] = (LVM_FLOAT)pIn[2 * i] * REVERB_SEND_LEVEL / 32768.0f;
+            pInputBuff[2 * i + 1] = (LVM_FLOAT)pIn[2 * i + 1] * REVERB_SEND_LEVEL / 32768.0f;
+#endif
         }
     }
 
     if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
+#ifdef BUILD_FLOAT
+        memset(pOutputBuff, 0, frameCount * sizeof(LVM_FLOAT) * 2); //always stereo here
+#else
         memset(pContext->OutFrames32, 0, frameCount * sizeof(LVM_INT32) * 2); //always stereo here
+#endif
     } else {
         if(pContext->bEnabled == LVM_FALSE && pContext->SamplesToExitCount > 0) {
+#ifdef BUILD_FLOAT
+            memset(pInputBuff, 0, frameCount * sizeof(LVM_FLOAT) * samplesPerFrame);
+#else
             memset(pContext->InFrames32,0,frameCount * sizeof(LVM_INT32) * samplesPerFrame);
+#endif
             ALOGV("\tZeroing %d samples per frame at the end of call", samplesPerFrame);
         }
 
         /* Process the samples, producing a stereo output */
+#ifdef BUILD_FLOAT
+        LvmStatus = LVREV_Process(pContext->hInstance,      /* Instance handle */
+                                  pInputBuff,     /* Input buffer */
+                                  pOutputBuff,    /* Output buffer */
+                                  frameCount);              /* Number of samples to read */
+#else
         LvmStatus = LVREV_Process(pContext->hInstance,      /* Instance handle */
                                   pContext->InFrames32,     /* Input buffer */
                                   pContext->OutFrames32,    /* Output buffer */
                                   frameCount);              /* Number of samples to read */
-    }
+#endif
+        }
 
     LVM_ERROR_CHECK(LvmStatus, "LVREV_Process", "process")
     if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
 
     // Convert to 16 bits
     if (pContext->auxiliary) {
+#ifdef BUILD_FLOAT
+        FloatToInt16_SAT(pOutputBuff, OutFrames16, (size_t)frameCount * 2);
+#else
         for (int i=0; i < frameCount*2; i++) { //always stereo here
             OutFrames16[i] = clamp16(pContext->OutFrames32[i]>>8);
         }
-    } else {
-        for (int i=0; i < frameCount*2; i++) { //always stereo here
-            OutFrames16[i] = clamp16((pContext->OutFrames32[i]>>8) + (LVM_INT32)pIn[i]);
-        }
+#endif
+        } else {
+#ifdef BUILD_FLOAT
+            for (int i = 0; i < frameCount * 2; i++) {//always stereo here
+                //pOutputBuff and OutFrames16 point to the same buffer, so better to
+                //accumulate in pInputBuff, which is available
+                pInputBuff[i] = pOutputBuff[i] + (LVM_FLOAT)pIn[i] / 32768.0f;
+            }
 
+            FloatToInt16_SAT(pInputBuff, OutFrames16, (size_t)frameCount * 2);
+#else
+            for (int i=0; i < frameCount*2; i++) { //always stereo here
+                OutFrames16[i] = clamp16((pContext->OutFrames32[i]>>8) + (LVM_INT32)pIn[i]);
+            }
+#endif
         // apply volume with ramp if needed
         if ((pContext->leftVolume != pContext->prevLeftVolume ||
                 pContext->rightVolume != pContext->prevRightVolume) &&
@@ -644,6 +758,14 @@
     case 48000:
         SampleRate = LVM_FS_48000;
         break;
+#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+    case 96000:
+        SampleRate = LVM_FS_96000;
+        break;
+    case 192000:
+        SampleRate = LVM_FS_192000;
+        break;
+#endif
     default:
         ALOGV("\rReverb_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
         return -EINVAL;
@@ -1011,7 +1133,7 @@
     //ALOGV("\tReverbGetRoomHfLevel() ActiveParams.LPFL %d, pContext->SavedHfLevel: %d, "
     //     "converted level: %d\n", ActiveParams.LPF, pContext->SavedHfLevel, level);
 
-    if(ActiveParams.LPF != level){
+    if((int16_t)ActiveParams.LPF != level){
         ALOGV("\tLVM_ERROR : (ignore at start up) ReverbGetRoomHfLevel() has wrong level -> %d %d\n",
                ActiveParams.Level, level);
     }
diff --git a/media/libheif/Android.bp b/media/libheif/Android.bp
new file mode 100644
index 0000000..7d5a4eb
--- /dev/null
+++ b/media/libheif/Android.bp
@@ -0,0 +1,23 @@
+cc_library_shared {
+    name: "libheif",
+
+    srcs: [
+        "HeifDecoderImpl.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+        "libmedia",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    include_dirs: [],
+
+    export_include_dirs: ["include"],
+}
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
new file mode 100644
index 0000000..4b131a7
--- /dev/null
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "HeifDecoderImpl"
+
+#include "HeifDecoderImpl.h"
+
+#include <stdio.h>
+
+#include <binder/IMemory.h>
+#include <drm/drm_framework_common.h>
+#include <media/IDataSource.h>
+#include <media/mediametadataretriever.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaSource.h>
+#include <private/media/VideoFrame.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+HeifDecoder* createHeifDecoder() {
+    return new android::HeifDecoderImpl();
+}
+
+namespace android {
+
+/*
+ * HeifDataSource
+ *
+ * Proxies data requests over IDataSource interface from MediaMetadataRetriever
+ * to the HeifStream interface we received from the heif decoder client.
+ */
+class HeifDataSource : public BnDataSource {
+public:
+    /*
+     * Constructs HeifDataSource; will take ownership of |stream|.
+     */
+    HeifDataSource(HeifStream* stream)
+        : mStream(stream), mEOS(false),
+          mCachedOffset(0), mCachedSize(0), mCacheBufferSize(0) {}
+
+    ~HeifDataSource() override {}
+
+    /*
+     * Initializes internal resources.
+     */
+    bool init();
+
+    sp<IMemory> getIMemory() override { return mMemory; }
+    ssize_t readAt(off64_t offset, size_t size) override;
+    status_t getSize(off64_t* size) override ;
+    void close() {}
+    uint32_t getFlags() override { return 0; }
+    String8 toString() override { return String8("HeifDataSource"); }
+    sp<DecryptHandle> DrmInitialization(const char*) override {
+        return nullptr;
+    }
+
+private:
+    enum {
+        /*
+         * Buffer size for passing the read data to mediaserver. Set to 64K
+         * (which is what MediaDataSource Java API's jni implementation uses).
+         */
+        kBufferSize = 64 * 1024,
+        /*
+         * Initial and max cache buffer size.
+         */
+        kInitialCacheBufferSize = 4 * 1024 * 1024,
+        kMaxCacheBufferSize = 64 * 1024 * 1024,
+    };
+    sp<IMemory> mMemory;
+    std::unique_ptr<HeifStream> mStream;
+    bool mEOS;
+    std::unique_ptr<uint8_t> mCache;
+    off64_t mCachedOffset;
+    size_t mCachedSize;
+    size_t mCacheBufferSize;
+};
+
+bool HeifDataSource::init() {
+    sp<MemoryDealer> memoryDealer =
+            new MemoryDealer(kBufferSize, "HeifDataSource");
+    mMemory = memoryDealer->allocate(kBufferSize);
+    if (mMemory == nullptr) {
+        ALOGE("Failed to allocate shared memory!");
+        return false;
+    }
+    mCache.reset(new uint8_t[kInitialCacheBufferSize]);
+    if (mCache.get() == nullptr) {
+        ALOGE("mFailed to allocate cache!");
+        return false;
+    }
+    mCacheBufferSize = kInitialCacheBufferSize;
+    return true;
+}
+
+ssize_t HeifDataSource::readAt(off64_t offset, size_t size) {
+    ALOGV("readAt: offset=%lld, size=%zu", (long long)offset, size);
+
+    if (offset < mCachedOffset) {
+        // try seek, then rewind/skip, fail if none worked
+        if (mStream->seek(offset)) {
+            ALOGV("readAt: seek to offset=%lld", (long long)offset);
+            mCachedOffset = offset;
+            mCachedSize = 0;
+            mEOS = false;
+        } else if (mStream->rewind()) {
+            ALOGV("readAt: rewind to offset=0");
+            mCachedOffset = 0;
+            mCachedSize = 0;
+            mEOS = false;
+        } else {
+            ALOGE("readAt: couldn't seek or rewind!");
+            mEOS = true;
+        }
+    }
+
+    if (mEOS && (offset < mCachedOffset ||
+                 offset >= (off64_t)(mCachedOffset + mCachedSize))) {
+        ALOGV("readAt: EOS");
+        return ERROR_END_OF_STREAM;
+    }
+
+    // at this point, offset must be >= mCachedOffset, other cases should
+    // have been caught above.
+    CHECK(offset >= mCachedOffset);
+
+    if (size == 0) {
+        return 0;
+    }
+
+    // Can only read max of kBufferSize
+    if (size > kBufferSize) {
+        size = kBufferSize;
+    }
+
+    // copy from cache if the request falls entirely in cache
+    if (offset + size <= mCachedOffset + mCachedSize) {
+        memcpy(mMemory->pointer(), mCache.get() + offset - mCachedOffset, size);
+        return size;
+    }
+
+    // need to fetch more, check if we need to expand the cache buffer.
+    if ((off64_t)(offset + size) > mCachedOffset + kMaxCacheBufferSize) {
+        // it's reaching max cache buffer size, need to roll window, and possibly
+        // expand the cache buffer.
+        size_t newCacheBufferSize = mCacheBufferSize;
+        std::unique_ptr<uint8_t> newCache;
+        uint8_t* dst = mCache.get();
+        if (newCacheBufferSize < kMaxCacheBufferSize) {
+            newCacheBufferSize = kMaxCacheBufferSize;
+            newCache.reset(new uint8_t[newCacheBufferSize]);
+            dst = newCache.get();
+        }
+
+        // when rolling the cache window, try to keep about half the old bytes
+        // in case that the client goes back.
+        off64_t newCachedOffset = offset - (off64_t)(newCacheBufferSize / 2);
+        if (newCachedOffset < mCachedOffset) {
+            newCachedOffset = mCachedOffset;
+        }
+
+        int64_t newCachedSize = (int64_t)(mCachedOffset + mCachedSize) - newCachedOffset;
+        if (newCachedSize > 0) {
+            // in this case, the new cache region partially overlop the old cache,
+            // move the portion of the cache we want to save to the beginning of
+            // the cache buffer.
+            memcpy(dst, mCache.get() + newCachedOffset - mCachedOffset, newCachedSize);
+        } else if (newCachedSize < 0){
+            // in this case, the new cache region is entirely out of the old cache,
+            // in order to guarantee sequential read, we need to skip a number of
+            // bytes before reading.
+            size_t bytesToSkip = -newCachedSize;
+            size_t bytesSkipped = mStream->read(nullptr, bytesToSkip);
+            if (bytesSkipped != bytesToSkip) {
+                // bytesSkipped is invalid, there is not enough bytes to reach
+                // the requested offset.
+                ALOGE("readAt: skip failed, EOS");
+
+                mEOS = true;
+                mCachedOffset = newCachedOffset;
+                mCachedSize = 0;
+                return ERROR_END_OF_STREAM;
+            }
+            // set cache size to 0, since we're not keeping any old cache
+            newCachedSize = 0;
+        }
+
+        if (newCache.get() != nullptr) {
+            mCache.reset(newCache.release());
+            mCacheBufferSize = newCacheBufferSize;
+        }
+        mCachedOffset = newCachedOffset;
+        mCachedSize = newCachedSize;
+
+        ALOGV("readAt: rolling cache window to (%lld, %zu), cache buffer size %zu",
+                (long long)mCachedOffset, mCachedSize, mCacheBufferSize);
+    } else {
+        // expand cache buffer, but no need to roll the window
+        size_t newCacheBufferSize = mCacheBufferSize;
+        while (offset + size > mCachedOffset + newCacheBufferSize) {
+            newCacheBufferSize *= 2;
+        }
+        CHECK(newCacheBufferSize <= kMaxCacheBufferSize);
+        if (mCacheBufferSize < newCacheBufferSize) {
+            uint8_t* newCache = new uint8_t[newCacheBufferSize];
+            memcpy(newCache, mCache.get(), mCachedSize);
+            mCache.reset(newCache);
+            mCacheBufferSize = newCacheBufferSize;
+
+            ALOGV("readAt: current cache window (%lld, %zu), new cache buffer size %zu",
+                    (long long) mCachedOffset, mCachedSize, mCacheBufferSize);
+        }
+    }
+    size_t bytesToRead = offset + size - mCachedOffset - mCachedSize;
+    size_t bytesRead = mStream->read(mCache.get() + mCachedSize, bytesToRead);
+    if (bytesRead > bytesToRead || bytesRead == 0) {
+        // bytesRead is invalid
+        mEOS = true;
+        bytesRead = 0;
+    } else if (bytesRead < bytesToRead) {
+        // read some bytes but not all, set EOS
+        mEOS = true;
+    }
+    mCachedSize += bytesRead;
+    ALOGV("readAt: current cache window (%lld, %zu)",
+            (long long) mCachedOffset, mCachedSize);
+
+    // here bytesAvailable could be negative if offset jumped past EOS.
+    int64_t bytesAvailable = mCachedOffset + mCachedSize - offset;
+    if (bytesAvailable <= 0) {
+        return ERROR_END_OF_STREAM;
+    }
+    if (bytesAvailable < (int64_t)size) {
+        size = bytesAvailable;
+    }
+    memcpy(mMemory->pointer(), mCache.get() + offset - mCachedOffset, size);
+    return size;
+}
+
+status_t HeifDataSource::getSize(off64_t* size) {
+    if (!mStream->hasLength()) {
+        *size = -1;
+        ALOGE("getSize: not supported!");
+        return ERROR_UNSUPPORTED;
+    }
+    *size = mStream->getLength();
+    ALOGV("getSize: size=%lld", (long long)*size);
+    return OK;
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+HeifDecoderImpl::HeifDecoderImpl() :
+    // output color format should always be set via setOutputColor(), in case
+    // it's not, default to HAL_PIXEL_FORMAT_RGB_565.
+    mOutputColor(HAL_PIXEL_FORMAT_RGB_565),
+    mCurScanline(0),
+    mFrameDecoded(false) {
+}
+
+HeifDecoderImpl::~HeifDecoderImpl() {
+}
+
+bool HeifDecoderImpl::init(HeifStream* stream, HeifFrameInfo* frameInfo) {
+    mFrameDecoded = false;
+    sp<HeifDataSource> dataSource = new HeifDataSource(stream);
+    if (!dataSource->init()) {
+        return false;
+    }
+    mDataSource = dataSource;
+
+    mRetriever = new MediaMetadataRetriever();
+    status_t err = mRetriever->setDataSource(mDataSource, "video/mp4");
+    if (err != OK) {
+        ALOGE("failed to set data source!");
+
+        mRetriever.clear();
+        mDataSource.clear();
+        return false;
+    }
+    ALOGV("successfully set data source.");
+
+    const char* hasVideo = mRetriever->extractMetadata(METADATA_KEY_HAS_VIDEO);
+    if (!hasVideo || strcasecmp(hasVideo, "yes")) {
+        ALOGE("no video: %s", hasVideo ? hasVideo : "null");
+        return false;
+    }
+
+    mFrameMemory = mRetriever->getFrameAtTime(0,
+            IMediaSource::ReadOptions::SEEK_PREVIOUS_SYNC,
+            mOutputColor, true /*metaOnly*/);
+    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+        ALOGE("getFrameAtTime: videoFrame is a nullptr");
+        return false;
+    }
+
+    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+
+    ALOGV("Meta dimension %dx%d, display %dx%d, angle %d, iccSize %d",
+            videoFrame->mWidth,
+            videoFrame->mHeight,
+            videoFrame->mDisplayWidth,
+            videoFrame->mDisplayHeight,
+            videoFrame->mRotationAngle,
+            videoFrame->mIccSize);
+
+    if (frameInfo != nullptr) {
+        frameInfo->set(
+                videoFrame->mDisplayWidth,
+                videoFrame->mDisplayHeight,
+                videoFrame->mRotationAngle,
+                videoFrame->mBytesPerPixel,
+                videoFrame->mIccSize,
+                videoFrame->getFlattenedIccData());
+    }
+    return true;
+}
+
+bool HeifDecoderImpl::getEncodedColor(HeifEncodedColor* /*outColor*/) const {
+    ALOGW("getEncodedColor: not implemented!");
+    return false;
+}
+
+bool HeifDecoderImpl::setOutputColor(HeifColorFormat heifColor) {
+    switch(heifColor) {
+        case kHeifColorFormat_RGB565:
+        {
+            mOutputColor = HAL_PIXEL_FORMAT_RGB_565;
+            return true;
+        }
+        case kHeifColorFormat_RGBA_8888:
+        {
+            mOutputColor = HAL_PIXEL_FORMAT_RGBA_8888;
+            return true;
+        }
+        case kHeifColorFormat_BGRA_8888:
+        {
+            mOutputColor = HAL_PIXEL_FORMAT_BGRA_8888;
+            return true;
+        }
+        default:
+            break;
+    }
+    ALOGE("Unsupported output color format %d", heifColor);
+    return false;
+}
+
+bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {
+    // reset scanline pointer
+    mCurScanline = 0;
+
+    if (mFrameDecoded) {
+        return true;
+    }
+
+    mFrameMemory = mRetriever->getFrameAtTime(0,
+            IMediaSource::ReadOptions::SEEK_PREVIOUS_SYNC, mOutputColor);
+    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+        ALOGE("getFrameAtTime: videoFrame is a nullptr");
+        return false;
+    }
+
+    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+    if (videoFrame->mSize == 0 ||
+            mFrameMemory->size() < videoFrame->getFlattenedSize()) {
+        ALOGE("getFrameAtTime: videoFrame size is invalid");
+        return false;
+    }
+
+    ALOGV("Decoded dimension %dx%d, display %dx%d, angle %d, rowbytes %d, size %d",
+            videoFrame->mWidth,
+            videoFrame->mHeight,
+            videoFrame->mDisplayWidth,
+            videoFrame->mDisplayHeight,
+            videoFrame->mRotationAngle,
+            videoFrame->mRowBytes,
+            videoFrame->mSize);
+
+    if (frameInfo != nullptr) {
+        frameInfo->set(
+                videoFrame->mDisplayWidth,
+                videoFrame->mDisplayHeight,
+                videoFrame->mRotationAngle,
+                videoFrame->mBytesPerPixel,
+                videoFrame->mIccSize,
+                videoFrame->getFlattenedIccData());
+    }
+    mFrameDecoded = true;
+
+    // Aggressive clear to avoid holding on to resources
+    mRetriever.clear();
+    mDataSource.clear();
+    return true;
+}
+
+bool HeifDecoderImpl::getScanline(uint8_t* dst) {
+    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+        return false;
+    }
+    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+    if (mCurScanline >= videoFrame->mDisplayHeight) {
+        ALOGE("no more scanline available");
+        return false;
+    }
+    uint8_t* src = videoFrame->getFlattenedData() + videoFrame->mRowBytes * mCurScanline++;
+    memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mDisplayWidth);
+    return true;
+}
+
+size_t HeifDecoderImpl::skipScanlines(size_t count) {
+    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+        return 0;
+    }
+    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+
+    uint32_t oldScanline = mCurScanline;
+    mCurScanline += count;
+    if (mCurScanline > videoFrame->mDisplayHeight) {
+        mCurScanline = videoFrame->mDisplayHeight;
+    }
+    return (mCurScanline > oldScanline) ? (mCurScanline - oldScanline) : 0;
+}
+
+} // namespace android
diff --git a/media/libheif/HeifDecoderImpl.h b/media/libheif/HeifDecoderImpl.h
new file mode 100644
index 0000000..c2e4ff3
--- /dev/null
+++ b/media/libheif/HeifDecoderImpl.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HEIF_DECODER_IMPL_
+#define _HEIF_DECODER_IMPL_
+
+#include "include/HeifDecoderAPI.h"
+#include <system/graphics.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class IDataSource;
+class IMemory;
+class MediaMetadataRetriever;
+
+/*
+ * An implementation of HeifDecoder based on Android's MediaMetadataRetriever.
+ */
+class HeifDecoderImpl : public HeifDecoder {
+public:
+
+    HeifDecoderImpl();
+    ~HeifDecoderImpl() override;
+
+    bool init(HeifStream* stream, HeifFrameInfo* frameInfo) override;
+
+    bool getEncodedColor(HeifEncodedColor* outColor) const override;
+
+    bool setOutputColor(HeifColorFormat heifColor) override;
+
+    bool decode(HeifFrameInfo* frameInfo) override;
+
+    bool getScanline(uint8_t* dst) override;
+
+    size_t skipScanlines(size_t count) override;
+
+private:
+    sp<IDataSource> mDataSource;
+    sp<MediaMetadataRetriever> mRetriever;
+    sp<IMemory> mFrameMemory;
+    android_pixel_format_t mOutputColor;
+    size_t mCurScanline;
+    bool mFrameDecoded;
+};
+
+} // namespace android
+
+#endif // _HEIF_DECODER_IMPL_
diff --git a/media/libheif/include/HeifDecoderAPI.h b/media/libheif/include/HeifDecoderAPI.h
new file mode 100644
index 0000000..5183c39
--- /dev/null
+++ b/media/libheif/include/HeifDecoderAPI.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HEIF_DECODER_API_
+#define _HEIF_DECODER_API_
+
+#include <memory>
+
+/*
+ * The output color pixel format of heif decoder.
+ */
+typedef enum {
+    kHeifColorFormat_RGB565     = 0,
+    kHeifColorFormat_RGBA_8888  = 1,
+    kHeifColorFormat_BGRA_8888  = 2,
+} HeifColorFormat;
+
+/*
+ * The color spaces encoded in the heif image.
+ */
+typedef enum {
+    kHeifEncodedColor_RGB = 0,
+    kHeifEncodedColor_YUV = 1,
+    kHeifEncodedColor_CMYK = 2,
+} HeifEncodedColor;
+
+/*
+ * Represents a color converted (RGB-based) video frame
+ */
+struct HeifFrameInfo
+{
+    HeifFrameInfo() :
+        mWidth(0), mHeight(0), mRotationAngle(0), mBytesPerPixel(0),
+        mIccSize(0), mIccData(nullptr) {}
+
+    // update the frame info, will make a copy of |iccData| internally
+    void set(uint32_t width, uint32_t height, int32_t rotation, uint32_t bpp,
+            uint32_t iccSize, uint8_t* iccData) {
+        mWidth = width;
+        mHeight = height;
+        mRotationAngle = rotation;
+        mBytesPerPixel = bpp;
+
+        if (mIccData != nullptr) {
+            mIccData.reset(nullptr);
+        }
+        mIccSize = iccSize;
+        if (iccSize > 0) {
+            mIccData.reset(new uint8_t[iccSize]);
+            if (mIccData.get() != nullptr) {
+                memcpy(mIccData.get(), iccData, iccSize);
+            } else {
+                mIccSize = 0;
+            }
+        }
+    }
+
+    // Intentional public access modifiers:
+    uint32_t mWidth;
+    uint32_t mHeight;
+    int32_t  mRotationAngle;           // Rotation angle, clockwise, should be multiple of 90
+    uint32_t mBytesPerPixel;           // Number of bytes for one pixel
+    uint32_t mIccSize;                 // Number of bytes in mIccData
+    std::unique_ptr<uint8_t> mIccData; // Actual ICC data, memory is owned by this structure
+};
+
+/*
+ * Abstract interface to provide data to HeifDecoder.
+ */
+struct HeifStream {
+    HeifStream() {}
+
+    virtual ~HeifStream() {}
+
+    /*
+     * Reads or skips size number of bytes. return the number of bytes actually
+     * read or skipped.
+     * If |buffer| == NULL, skip size bytes, return how many were skipped.
+     * If |buffer| != NULL, copy size bytes into buffer, return how many were copied.
+     */
+    virtual size_t read(void* buffer, size_t size) = 0;
+
+    /*
+     * Rewinds to the beginning of the stream. Returns true if the stream is known
+     * to be at the beginning after this call returns.
+     */
+    virtual bool rewind() = 0;
+
+    /*
+     * Seeks to an absolute position in the stream. If this cannot be done, returns false.
+     * If an attempt is made to seek past the end of the stream, the position will be set
+     * to the end of the stream.
+     */
+    virtual bool seek(size_t /*position*/) = 0;
+
+    /** Returns true if this stream can report its total length. */
+    virtual bool hasLength() const = 0;
+
+    /** Returns the total length of the stream. If this cannot be done, returns 0. */
+    virtual size_t getLength() const = 0;
+
+private:
+    HeifStream(const HeifFrameInfo&) = delete;
+    HeifStream& operator=(const HeifFrameInfo&) = delete;
+};
+
+/*
+ * Abstract interface to decode heif images from a HeifStream data source.
+ */
+struct HeifDecoder {
+    HeifDecoder() {}
+
+    virtual ~HeifDecoder() {}
+
+    /*
+     * Returns true if it successfully sets outColor to the encoded color,
+     * and false otherwise.
+     */
+    virtual bool getEncodedColor(HeifEncodedColor* outColor) const = 0;
+
+    /*
+     * Returns true if it successfully sets the output color format to color,
+     * and false otherwise.
+     */
+    virtual bool setOutputColor(HeifColorFormat color) = 0;
+
+    /*
+     * Returns true if it successfully initialize heif decoder with source,
+     * and false otherwise. |frameInfo| will be filled with information of
+     * the primary picture upon success and unmodified upon failure.
+     * Takes ownership of |stream| regardless of result.
+     */
+    virtual bool init(HeifStream* stream, HeifFrameInfo* frameInfo) = 0;
+
+    /*
+     * Decode the picture internally, returning whether it succeeded. |frameInfo|
+     * will be filled with information of the primary picture upon success and
+     * unmodified upon failure.
+     *
+     * After this succeeded, getScanline can be called to read the scanlines
+     * that were decoded.
+     */
+    virtual bool decode(HeifFrameInfo* frameInfo) = 0;
+
+    /*
+     * Read the next scanline (in top-down order), returns true upon success
+     * and false otherwise.
+     */
+    virtual bool getScanline(uint8_t* dst) = 0;
+
+    /*
+     * Skip the next |count| scanlines, returns true upon success and
+     * false otherwise.
+     */
+    virtual size_t skipScanlines(size_t count) = 0;
+
+private:
+    HeifDecoder(const HeifFrameInfo&) = delete;
+    HeifDecoder& operator=(const HeifFrameInfo&) = delete;
+};
+
+/*
+ * Creates a HeifDecoder. Returns a HeifDecoder instance upon success, or NULL
+ * if the creation has failed.
+ */
+HeifDecoder* createHeifDecoder();
+
+#endif // _HEIF_DECODER_API_
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index bbe97ee..a462f3a 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -2,11 +2,22 @@
     name: "libmedia_headers",
     vendor_available: true,
     export_include_dirs: ["include"],
+    header_libs:[
+        "libstagefright_headers",
+        "media_plugin_headers",
+    ],
+    export_header_lib_headers: [
+        "libstagefright_headers",
+        "media_plugin_headers",
+    ],
 }
 
 cc_library {
     name: "libmedia_helper",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
     cflags: [
         "-Werror",
@@ -34,6 +45,7 @@
         "IMediaCodecList.cpp",
         "IMediaCodecService.cpp",
         "IOMX.cpp",
+        "IOMXStore.cpp",
         "MediaCodecBuffer.cpp",
         "MediaCodecInfo.cpp",
         "MediaDefs.cpp",
@@ -69,14 +81,6 @@
         "libutils",
     ],
 
-    include_dirs: [
-        "frameworks/av/include", // for media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h
-        "frameworks/av/include/media",
-        "frameworks/native/include", // for media/hardware/MetadataBufferType.h
-        "frameworks/native/include/media/openmax",
-        "frameworks/av/media/libstagefright",
-    ],
-
     export_shared_lib_headers: [
         "android.hidl.memory@1.0",
         "android.hidl.token@1.0-utils",
@@ -120,6 +124,9 @@
 cc_library_shared {
     name: "libmedia_omx",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     defaults: ["libmedia_omx_defaults"],
 }
@@ -202,6 +209,7 @@
         "libicui18n",
         "libsonivox",
         "libmediadrm",
+        "libmedia_helper",
         "android.hidl.memory@1.0",
     ],
 
@@ -210,15 +218,10 @@
         "libc_malloc_debug_backtrace",
     ],
 
-    include_dirs: [
-        "frameworks/native/include/media/openmax",
-        "frameworks/av/include/media/",
-        "frameworks/av/media/libstagefright",
-    ],
-
     export_include_dirs: [
         "include",
     ],
+
     cflags: [
         "-Werror",
         "-Wno-error=deprecated-declarations",
diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp
index 808c2b5..990d260 100644
--- a/media/libmedia/CharacterEncodingDetector.cpp
+++ b/media/libmedia/CharacterEncodingDetector.cpp
@@ -18,15 +18,15 @@
 #define LOG_TAG "CharacterEncodingDector"
 #include <utils/Log.h>
 
-#include <CharacterEncodingDetector.h>
+#include <media/CharacterEncodingDetector.h>
 #include "CharacterEncodingDetectorTables.h"
 
-#include "utils/Vector.h"
-#include "StringArray.h"
+#include <utils/Vector.h>
+#include <media/StringArray.h>
 
-#include "unicode/ucnv.h"
-#include "unicode/ucsdet.h"
-#include "unicode/ustring.h"
+#include <unicode/ucnv.h>
+#include <unicode/ucsdet.h>
+#include <unicode/ustring.h>
 
 namespace android {
 
diff --git a/media/libmedia/IMediaCodecService.cpp b/media/libmedia/IMediaCodecService.cpp
index 2d62419..adfa93d 100644
--- a/media/libmedia/IMediaCodecService.cpp
+++ b/media/libmedia/IMediaCodecService.cpp
@@ -27,7 +27,8 @@
 namespace android {
 
 enum {
-    GET_OMX = IBinder::FIRST_CALL_TRANSACTION
+    GET_OMX = IBinder::FIRST_CALL_TRANSACTION,
+    GET_OMX_STORE
 };
 
 class BpMediaCodecService : public BpInterface<IMediaCodecService>
@@ -45,6 +46,13 @@
         return interface_cast<IOMX>(reply.readStrongBinder());
     }
 
+    virtual sp<IOMXStore> getOMXStore() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
+        remote()->transact(GET_OMX_STORE, data, &reply);
+        return interface_cast<IOMXStore>(reply.readStrongBinder());
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(MediaCodecService, "android.media.IMediaCodecService");
@@ -62,6 +70,12 @@
             reply->writeStrongBinder(IInterface::asBinder(omx));
             return NO_ERROR;
         }
+        case GET_OMX_STORE: {
+            CHECK_INTERFACE(IMediaCodecService, data, reply);
+            sp<IOMXStore> omxStore = getOMXStore();
+            reply->writeStrongBinder(IInterface::asBinder(omxStore));
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index 4caa79e..a8a7b82 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -21,7 +21,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <android/media/ICas.h>
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <binder/PermissionCache.h>
@@ -40,7 +39,8 @@
     SETMEDIACAS,
     SETUID,
     NAME,
-    GETMETRICS
+    GETMETRICS,
+    RELEASE,
 };
 
 class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -118,12 +118,12 @@
         return NULL;
     }
 
-    virtual status_t setMediaCas(const sp<ICas> & cas) {
+    virtual status_t setMediaCas(const HInterfaceToken &casToken) {
         ALOGV("setMediaCas");
 
         Parcel data, reply;
         data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(cas));
+        data.writeByteVector(casToken);
 
         status_t err = remote()->transact(SETMEDIACAS, data, &reply);
         if (err != NO_ERROR) {
@@ -140,6 +140,13 @@
         ALOGV("name NOT IMPLEMENTED");
         return NULL;
     }
+
+    virtual void release() {
+        ALOGV("release");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        remote()->transact(RELEASE, data, &reply);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
@@ -207,15 +214,20 @@
             ALOGV("setMediaCas");
             CHECK_INTERFACE(IMediaExtractor, data, reply);
 
-            sp<IBinder> casBinder;
-            status_t err = data.readNullableStrongBinder(&casBinder);
+            HInterfaceToken casToken;
+            status_t err = data.readByteVector(&casToken);
             if (err != NO_ERROR) {
-                ALOGE("Error reading cas from parcel");
+                ALOGE("Error reading casToken from parcel");
                 return err;
             }
-            sp<ICas> cas = interface_cast<ICas>(casBinder);
 
-            reply->writeInt32(setMediaCas(cas));
+            reply->writeInt32(setMediaCas(casToken));
+            return OK;
+        }
+        case RELEASE: {
+            ALOGV("release");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            release();
             return OK;
         }
         default:
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 7058ee8..5ea2e8b 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -127,22 +127,32 @@
         return reply.readInt32();
     }
 
-    status_t setDataSource(const sp<IDataSource>& source)
+    status_t setDataSource(const sp<IDataSource>& source, const char *mime)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
         data.writeStrongBinder(IInterface::asBinder(source));
+
+        if (mime != NULL) {
+            data.writeInt32(1);
+            data.writeCString(mime);
+        } else {
+            data.writeInt32(0);
+        }
         remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply);
         return reply.readInt32();
     }
 
-    sp<IMemory> getFrameAtTime(int64_t timeUs, int option)
+    sp<IMemory> getFrameAtTime(int64_t timeUs, int option, int colorFormat, bool metaOnly)
     {
-        ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option);
+        ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d) metaOnly(%d)",
+                timeUs, option, colorFormat, metaOnly);
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
         data.writeInt64(timeUs);
         data.writeInt32(option);
+        data.writeInt32(colorFormat);
+        data.writeInt32(metaOnly);
 #ifndef DISABLE_GROUP_SCHEDULE_HACK
         sendSchedPolicy(data);
 #endif
@@ -258,7 +268,12 @@
             if (source == NULL) {
                 reply->writeInt32(BAD_VALUE);
             } else {
-                reply->writeInt32(setDataSource(source));
+                int32_t hasMime = data.readInt32();
+                const char *mime = NULL;
+                if (hasMime) {
+                    mime = data.readCString();
+                }
+                reply->writeInt32(setDataSource(source, mime));
             }
             return NO_ERROR;
         } break;
@@ -266,11 +281,14 @@
             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
             int64_t timeUs = data.readInt64();
             int option = data.readInt32();
-            ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option);
+            int colorFormat = data.readInt32();
+            bool metaOnly = (data.readInt32() != 0);
+            ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d), metaOnly(%d)",
+                    timeUs, option, colorFormat, metaOnly);
 #ifndef DISABLE_GROUP_SCHEDULE_HACK
             setSchedPolicy(data);
 #endif
-            sp<IMemory> bitmap = getFrameAtTime(timeUs, option);
+            sp<IMemory> bitmap = getFrameAtTime(timeUs, option, colorFormat, metaOnly);
             if (bitmap != 0) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
                 reply->writeStrongBinder(IInterface::asBinder(bitmap));
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 43130eb..a073081 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -29,7 +29,7 @@
 #include <utils/NativeHandle.h>
 #include <gui/IGraphicBufferProducer.h>
 
-#include <omx/1.0/WOmxNode.h>
+#include <media/omx/1.0/WOmxNode.h>
 #include <android/IGraphicBufferSource.h>
 #include <android/IOMXBufferSource.h>
 
diff --git a/media/libmedia/IOMXStore.cpp b/media/libmedia/IOMXStore.cpp
new file mode 100644
index 0000000..4948f1a
--- /dev/null
+++ b/media/libmedia/IOMXStore.cpp
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IOMXStore"
+
+#include <utils/Log.h>
+
+#include <media/IOMX.h>
+#include <media/IOMXStore.h>
+#include <android/hardware/media/omx/1.0/IOmxStore.h>
+
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+
+#include <vector>
+#include <string>
+
+namespace android {
+
+namespace {
+
+enum {
+    CONNECT = IBinder::FIRST_CALL_TRANSACTION,
+    LIST_SERVICE_ATTRIBUTES,
+    GET_NODE_PREFIX,
+    LIST_ROLES,
+    GET_OMX,
+};
+
+// Forward declarations of std::vector<T> <-> Parcel conversion funcitons that
+// depend on writeToParcel() and readToParcel() for T <-> Parcel.
+
+template <typename T>
+status_t writeToParcel(const std::vector<T>& v, Parcel* p);
+
+template <typename T>
+status_t readFromParcel(std::vector<T>* v, const Parcel& p);
+
+// std::string <-> Parcel
+
+status_t writeToParcel(const std::string& s, Parcel* p) {
+    if (s.size() > INT32_MAX) {
+        return BAD_VALUE;
+    }
+    return p->writeByteArray(
+            s.size(), reinterpret_cast<const uint8_t*>(s.c_str()));
+}
+
+status_t readFromParcel(std::string* s, const Parcel& p) {
+    int32_t len;
+    status_t status = p.readInt32(&len);
+    if (status != NO_ERROR) {
+        return status;
+    } else if ((len < 0) || (static_cast<uint64_t>(len) > SIZE_MAX)) {
+        return BAD_VALUE;
+    }
+    s->resize(len);
+    if (len == 0) {
+        return NO_ERROR;
+    }
+    return p.read(static_cast<void*>(&s->front()), static_cast<size_t>(len));
+}
+
+// IOMXStore::Attribute <-> Parcel
+
+status_t writeToParcel(const IOMXStore::Attribute& a, Parcel* p) {
+    status_t status = writeToParcel(a.key, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return writeToParcel(a.value, p);
+}
+
+status_t readFromParcel(IOMXStore::Attribute* a, const Parcel& p) {
+    status_t status = readFromParcel(&(a->key), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return readFromParcel(&(a->value), p);
+}
+
+// IOMXStore::NodeInfo <-> Parcel
+
+status_t writeToParcel(const IOMXStore::NodeInfo& n, Parcel* p) {
+    status_t status = writeToParcel(n.name, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = writeToParcel(n.owner, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return writeToParcel(n.attributes, p);
+}
+
+status_t readFromParcel(IOMXStore::NodeInfo* n, const Parcel& p) {
+    status_t status = readFromParcel(&(n->name), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = readFromParcel(&(n->owner), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return readFromParcel(&(n->attributes), p);
+}
+
+// IOMXStore::RoleInfo <-> Parcel
+
+status_t writeToParcel(const IOMXStore::RoleInfo& r, Parcel* p) {
+    status_t status = writeToParcel(r.role, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = writeToParcel(r.type, p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = p->writeBool(r.isEncoder);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = p->writeBool(r.preferPlatformNodes);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return writeToParcel(r.nodes, p);
+}
+
+status_t readFromParcel(IOMXStore::RoleInfo* r, const Parcel& p) {
+    status_t status = readFromParcel(&(r->role), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = readFromParcel(&(r->type), p);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = p.readBool(&(r->isEncoder));
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = p.readBool(&(r->preferPlatformNodes));
+    if (status != NO_ERROR) {
+        return status;
+    }
+    return readFromParcel(&(r->nodes), p);
+}
+
+// std::vector<NodeInfo> <-> Parcel
+// std::vector<RoleInfo> <-> Parcel
+
+template <typename T>
+status_t writeToParcel(const std::vector<T>& v, Parcel* p) {
+    status_t status = p->writeVectorSize(v);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    for (const T& x : v) {
+        status = writeToParcel(x, p);
+        if (status != NO_ERROR) {
+            return status;
+        }
+    }
+    return NO_ERROR;
+}
+
+template <typename T>
+status_t readFromParcel(std::vector<T>* v, const Parcel& p) {
+    status_t status = p.resizeOutVector(v);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    for (T& x : *v) {
+        status = readFromParcel(&x, p);
+        if (status != NO_ERROR) {
+            return status;
+        }
+    }
+    return NO_ERROR;
+}
+
+} // unnamed namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BpOMXStore : public BpInterface<IOMXStore> {
+public:
+    explicit BpOMXStore(const sp<IBinder> &impl)
+        : BpInterface<IOMXStore>(impl) {
+    }
+
+    status_t listServiceAttributes(
+            std::vector<Attribute>* attributes) override {
+        Parcel data, reply;
+        status_t status;
+        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = remote()->transact(LIST_SERVICE_ATTRIBUTES, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return readFromParcel(attributes, reply);
+    }
+
+    status_t getNodePrefix(std::string* prefix) override {
+        Parcel data, reply;
+        status_t status;
+        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = remote()->transact(GET_NODE_PREFIX, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return readFromParcel(prefix, reply);
+    }
+
+    status_t listRoles(std::vector<RoleInfo>* roleList) override {
+        Parcel data, reply;
+        status_t status;
+        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = remote()->transact(LIST_ROLES, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return readFromParcel(roleList, reply);
+    }
+
+    status_t getOmx(const std::string& name, sp<IOMX>* omx) override {
+        Parcel data, reply;
+        status_t status;
+        status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = writeToParcel(name, &data);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = remote()->transact(GET_OMX, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return reply.readStrongBinder(omx);
+    }
+
+};
+
+IMPLEMENT_META_INTERFACE(OMXStore, "android.hardware.IOMXStore");
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define CHECK_OMX_INTERFACE(interface, data, reply) \
+        do { if (!(data).enforceInterface(interface::getInterfaceDescriptor())) { \
+            ALOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnOMXStore::onTransact(
+    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+    switch (code) {
+        case LIST_SERVICE_ATTRIBUTES: {
+            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+            status_t status;
+            std::vector<Attribute> attributes;
+
+            status = listServiceAttributes(&attributes);
+            if (status != NO_ERROR) {
+                ALOGE("listServiceAttributes() fails with status %d",
+                        static_cast<int>(status));
+                return NO_ERROR;
+            }
+            status = writeToParcel(attributes, reply);
+            if (status != NO_ERROR) {
+                ALOGE("listServiceAttributes() fails to send reply");
+                return NO_ERROR;
+            }
+            return NO_ERROR;
+        }
+        case GET_NODE_PREFIX: {
+            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+            status_t status;
+            std::string prefix;
+
+            status = getNodePrefix(&prefix);
+            if (status != NO_ERROR) {
+                ALOGE("getNodePrefix() fails with status %d",
+                        static_cast<int>(status));
+                return NO_ERROR;
+            }
+            status = writeToParcel(prefix, reply);
+            if (status != NO_ERROR) {
+                ALOGE("getNodePrefix() fails to send reply");
+                return NO_ERROR;
+            }
+            return NO_ERROR;
+        }
+        case LIST_ROLES: {
+            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+            status_t status;
+            std::vector<RoleInfo> roleList;
+
+            status = listRoles(&roleList);
+            if (status != NO_ERROR) {
+                ALOGE("listRoles() fails with status %d",
+                        static_cast<int>(status));
+                return NO_ERROR;
+            }
+            status = writeToParcel(roleList, reply);
+            if (status != NO_ERROR) {
+                ALOGE("listRoles() fails to send reply");
+                return NO_ERROR;
+            }
+            return NO_ERROR;
+        }
+        case GET_OMX: {
+            CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+            status_t status;
+            std::string name;
+            sp<IOMX> omx;
+
+            status = readFromParcel(&name, data);
+            if (status != NO_ERROR) {
+                ALOGE("getOmx() fails to retrieve name");
+                return NO_ERROR;
+            }
+            status = getOmx(name, &omx);
+            if (status != NO_ERROR) {
+                ALOGE("getOmx() fails with status %d",
+                        static_cast<int>(status));
+                return NO_ERROR;
+            }
+            status = reply->writeStrongBinder(IInterface::asBinder(omx));
+            if (status != NO_ERROR) {
+                ALOGE("getOmx() fails to send reply");
+                return NO_ERROR;
+            }
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}  // namespace android
diff --git a/media/libmedia/IResourceManagerService.cpp b/media/libmedia/IResourceManagerService.cpp
index 95f7d2e..9724fc1 100644
--- a/media/libmedia/IResourceManagerService.cpp
+++ b/media/libmedia/IResourceManagerService.cpp
@@ -19,7 +19,7 @@
 #define LOG_TAG "IResourceManagerService"
 #include <utils/Log.h>
 
-#include "media/IResourceManagerService.h"
+#include <media/IResourceManagerService.h>
 
 #include <binder/Parcel.h>
 
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index 1f188f3..a570ffe 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -101,36 +101,46 @@
     return OK;
 }
 
-void MediaCodecInfo::CapabilitiesBuilder::addProfileLevel(uint32_t profile, uint32_t level) {
+void MediaCodecInfo::CapabilitiesWriter::addDetail(
+        const char* key, const char* value) {
+    mCap->mDetails->setString(key, value);
+}
+
+void MediaCodecInfo::CapabilitiesWriter::addDetail(
+        const char* key, int32_t value) {
+    mCap->mDetails->setInt32(key, value);
+}
+
+void MediaCodecInfo::CapabilitiesWriter::addProfileLevel(
+        uint32_t profile, uint32_t level) {
     ProfileLevel profileLevel;
     profileLevel.mProfile = profile;
     profileLevel.mLevel = level;
-    mProfileLevels.push_back(profileLevel);
+    if (mCap->mProfileLevelsSorted.indexOf(profileLevel) < 0) {
+        mCap->mProfileLevels.push_back(profileLevel);
+        mCap->mProfileLevelsSorted.add(profileLevel);
+    }
 }
 
-void MediaCodecInfo::CapabilitiesBuilder::addColorFormat(uint32_t format) {
-    mColorFormats.push(format);
+void MediaCodecInfo::CapabilitiesWriter::addColorFormat(uint32_t format) {
+    if (mCap->mColorFormatsSorted.indexOf(format) < 0) {
+        mCap->mColorFormats.push(format);
+        mCap->mColorFormatsSorted.add(format);
+    }
 }
 
-void MediaCodecInfo::CapabilitiesBuilder::addFlags(uint32_t flags) {
-    mFlags |= flags;
+void MediaCodecInfo::CapabilitiesWriter::addFlags(uint32_t flags) {
+    mCap->mFlags |= flags;
+}
+
+MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter(
+        MediaCodecInfo::Capabilities* cap) : mCap(cap) {
 }
 
 bool MediaCodecInfo::isEncoder() const {
     return mIsEncoder;
 }
 
-bool MediaCodecInfo::hasQuirk(const char *name) const {
-    if (name) {
-        for (size_t ix = 0; ix < mQuirks.size(); ix++) {
-            if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
 void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
     mimes->clear();
     for (size_t ix = 0; ix < mCaps.size(); ix++) {
@@ -151,20 +161,21 @@
     return mName.c_str();
 }
 
+const char *MediaCodecInfo::getOwnerName() const {
+    return mOwner.c_str();
+}
+
 // static
 sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
     AString name = AString::FromParcel(parcel);
+    AString owner = AString::FromParcel(parcel);
     bool isEncoder = static_cast<bool>(parcel.readInt32());
-    sp<MediaCodecInfo> info = new MediaCodecInfo(name, isEncoder, NULL);
+    sp<MediaCodecInfo> info = new MediaCodecInfo;
+    info->mName = name;
+    info->mOwner = owner;
+    info->mIsEncoder = isEncoder;
     size_t size = static_cast<size_t>(parcel.readInt32());
     for (size_t i = 0; i < size; i++) {
-        AString quirk = AString::FromParcel(parcel);
-        if (info != NULL) {
-            info->mQuirks.push_back(quirk);
-        }
-    }
-    size = static_cast<size_t>(parcel.readInt32());
-    for (size_t i = 0; i < size; i++) {
         AString mime = AString::FromParcel(parcel);
         sp<Capabilities> caps = Capabilities::FromParcel(parcel);
         if (caps == NULL)
@@ -178,11 +189,8 @@
 
 status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
     mName.writeToParcel(parcel);
+    mOwner.writeToParcel(parcel);
     parcel->writeInt32(mIsEncoder);
-    parcel->writeInt32(mQuirks.size());
-    for (size_t i = 0; i < mQuirks.size(); i++) {
-        mQuirks.itemAt(i).writeToParcel(parcel);
-    }
     parcel->writeInt32(mCaps.size());
     for (size_t i = 0; i < mCaps.size(); i++) {
         mCaps.keyAt(i).writeToParcel(parcel);
@@ -202,86 +210,46 @@
     return -1;
 }
 
-MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime)
-    : mName(name),
-      mIsEncoder(encoder),
-      mHasSoleMime(false) {
-    if (mime != NULL) {
-        addMime(mime);
-        mHasSoleMime = true;
-    }
+MediaCodecInfo::MediaCodecInfo() {
 }
 
-status_t MediaCodecInfo::addMime(const char *mime) {
-    if (mHasSoleMime) {
-        ALOGE("Codec '%s' already had its type specified", mName.c_str());
-        return -EINVAL;
-    }
-    ssize_t ix = getCapabilityIndex(mime);
+void MediaCodecInfoWriter::setName(const char* name) {
+    mInfo->mName = name;
+}
+
+void MediaCodecInfoWriter::setOwner(const char* owner) {
+    mInfo->mOwner = owner;
+}
+
+void MediaCodecInfoWriter::setEncoder(bool isEncoder) {
+    mInfo->mIsEncoder = isEncoder;
+}
+
+std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
+        MediaCodecInfoWriter::addMime(const char *mime) {
+    ssize_t ix = mInfo->getCapabilityIndex(mime);
     if (ix >= 0) {
-        mCurrentCaps = mCaps.valueAt(ix);
-    } else {
-        mCurrentCaps = new Capabilities();
-        mCaps.add(AString(mime), mCurrentCaps);
+        return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
+                new MediaCodecInfo::CapabilitiesWriter(
+                mInfo->mCaps.valueAt(ix).get()));
     }
-    return OK;
+    sp<MediaCodecInfo::Capabilities> caps = new MediaCodecInfo::Capabilities();
+    mInfo->mCaps.add(AString(mime), caps);
+    return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
+            new MediaCodecInfo::CapabilitiesWriter(caps.get()));
 }
 
-status_t MediaCodecInfo::updateMime(const char *mime) {
-    ssize_t ix = getCapabilityIndex(mime);
-    if (ix < 0) {
-        ALOGE("updateMime mime not found %s", mime);
-        return -EINVAL;
-    }
-
-    mCurrentCaps = mCaps.valueAt(ix);
-    return OK;
-}
-
-void MediaCodecInfo::removeMime(const char *mime) {
-    ssize_t ix = getCapabilityIndex(mime);
+bool MediaCodecInfoWriter::removeMime(const char *mime) {
+    ssize_t ix = mInfo->getCapabilityIndex(mime);
     if (ix >= 0) {
-        mCaps.removeItemsAt(ix);
-        // mCurrentCaps will be removed when completed
+        mInfo->mCaps.removeItemsAt(ix);
+        return true;
     }
+    return false;
 }
 
-status_t MediaCodecInfo::initializeCapabilities(const sp<Capabilities> &caps) {
-    // TRICKY: copy data to mCurrentCaps as it is a reference to
-    // an element of the capabilites map.
-    mCurrentCaps->mColorFormats.clear();
-    mCurrentCaps->mColorFormats.appendVector(caps->mColorFormats);
-    mCurrentCaps->mProfileLevels.clear();
-    mCurrentCaps->mProfileLevels.appendVector(caps->mProfileLevels);
-    mCurrentCaps->mFlags = caps->mFlags;
-    mCurrentCaps->mDetails = caps->mDetails;
-    return OK;
-}
-
-void MediaCodecInfo::addQuirk(const char *name) {
-    if (!hasQuirk(name)) {
-        mQuirks.push(name);
-    }
-}
-
-void MediaCodecInfo::complete() {
-    mCurrentCaps = NULL;
-}
-
-void MediaCodecInfo::addDetail(const AString &key, const AString &value) {
-    mCurrentCaps->mDetails->setString(key.c_str(), value.c_str());
-}
-
-void MediaCodecInfo::addFeature(const AString &key, int32_t value) {
-    AString tag = "feature-";
-    tag.append(key);
-    mCurrentCaps->mDetails->setInt32(tag.c_str(), value);
-}
-
-void MediaCodecInfo::addFeature(const AString &key, const char *value) {
-    AString tag = "feature-";
-    tag.append(key);
-    mCurrentCaps->mDetails->setString(tag.c_str(), value);
+MediaCodecInfoWriter::MediaCodecInfoWriter(MediaCodecInfo* info) :
+    mInfo(info) {
 }
 
 }  // namespace android
diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp
index 9f803cb..028616b 100644
--- a/media/libmedia/MediaScannerClient.cpp
+++ b/media/libmedia/MediaScannerClient.cpp
@@ -20,8 +20,8 @@
 
 #include <media/mediascanner.h>
 
-#include "CharacterEncodingDetector.h"
-#include "StringArray.h"
+#include <media/CharacterEncodingDetector.h>
+#include <media/StringArray.h>
 
 namespace android {
 
diff --git a/media/libmedia/MidiDeviceInfo.cpp b/media/libmedia/MidiDeviceInfo.cpp
index 02efc5f..7588e00 100644
--- a/media/libmedia/MidiDeviceInfo.cpp
+++ b/media/libmedia/MidiDeviceInfo.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "MidiDeviceInfo"
 
-#include "MidiDeviceInfo.h"
+#include <media/MidiDeviceInfo.h>
 
 #include <binder/Parcel.h>
 #include <log/log.h>
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index faae954..4e5d67f 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -22,7 +22,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 
-#include "media/MidiIoWrapper.h"
+#include <media/MidiIoWrapper.h>
 
 static int readAt(void *handle, void *buffer, int pos, int size) {
     return ((android::MidiIoWrapper*)handle)->readAt(buffer, pos, size);
diff --git a/media/libmedia/StringArray.cpp b/media/libmedia/StringArray.cpp
index b2e5907..7868b85 100644
--- a/media/libmedia/StringArray.cpp
+++ b/media/libmedia/StringArray.cpp
@@ -21,7 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "StringArray.h"
+#include <media/StringArray.h>
 
 namespace android {
 
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index a6eba86..e6c8f9c 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -375,7 +375,7 @@
 audio_channel_mask_t channelMaskFromString(const std::string &literalChannels)
 {
     audio_channel_mask_t channels;
-    if (!OutputChannelConverter::fromString(literalChannels, channels) ||
+    if (!OutputChannelConverter::fromString(literalChannels, channels) &&
             !InputChannelConverter::fromString(literalChannels, channels)) {
         return AUDIO_CHANNEL_INVALID;
     }
diff --git a/media/libmedia/include/media/DrmHal.h b/media/libmedia/include/media/DrmHal.h
index e031765..5d25e4d 100644
--- a/media/libmedia/include/media/DrmHal.h
+++ b/media/libmedia/include/media/DrmHal.h
@@ -39,6 +39,11 @@
 
 struct DrmSessionClientInterface;
 
+inline bool operator==(const Vector<uint8_t> &l, const Vector<uint8_t> &r) {
+    if (l.size() != r.size()) return false;
+    return memcmp(l.array(), r.array(), l.size()) == 0;
+}
+
 struct DrmHal : public BnDrm,
              public IBinder::DeathRecipient,
              public IDrmPluginListener {
@@ -161,6 +166,9 @@
     const Vector<sp<IDrmFactory>> mFactories;
     sp<IDrmPlugin> mPlugin;
 
+    Vector<Vector<uint8_t>> mOpenSessions;
+    void closeOpenSessions();
+
     /**
      * mInitCheck is:
      *   NO_INIT if a plugin hasn't been created yet
@@ -175,6 +183,11 @@
 
     void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
 
+    void reportMetrics() const;
+    status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
+    status_t getPropertyByteArrayInternal(String8 const &name,
+                                          Vector<uint8_t> &value) const;
+
     DISALLOW_EVIL_CONSTRUCTORS(DrmHal);
 };
 
diff --git a/media/libmedia/include/media/IDataSource.h b/media/libmedia/include/media/IDataSource.h
index 655f337..3858f78 100644
--- a/media/libmedia/include/media/IDataSource.h
+++ b/media/libmedia/include/media/IDataSource.h
@@ -35,7 +35,9 @@
     // Get the memory that readAt writes into.
     virtual sp<IMemory> getIMemory() = 0;
     // Read up to |size| bytes into the memory returned by getIMemory(). Returns
-    // the number of bytes read, or -1 on error. |size| must not be larger than
+    // the number of bytes read, or negative value on error (eg.
+    // ERROR_END_OF_STREAM indicating EOS. This is needed by CallbackDataSource
+    // to properly handle reading of last chunk). |size| must not be larger than
     // the buffer.
     virtual ssize_t readAt(off64_t offset, size_t size) = 0;
     // Get the size, or -1 if the size is unknown.
diff --git a/media/libmedia/include/media/IMediaCodecService.h b/media/libmedia/include/media/IMediaCodecService.h
index da3c5a03..59fb1c0 100644
--- a/media/libmedia/include/media/IMediaCodecService.h
+++ b/media/libmedia/include/media/IMediaCodecService.h
@@ -22,6 +22,7 @@
 #include <binder/Parcel.h>
 #include <media/IDataSource.h>
 #include <media/IOMX.h>
+#include <media/IOMXStore.h>
 
 namespace android {
 
@@ -31,6 +32,7 @@
     DECLARE_META_INTERFACE(MediaCodecService);
 
     virtual sp<IOMX> getOMX() = 0;
+    virtual sp<IOMXStore> getOMXStore() = 0;
 };
 
 class BnMediaCodecService: public BnInterface<IMediaCodecService>
diff --git a/media/libmedia/include/media/IMediaExtractor.h b/media/libmedia/include/media/IMediaExtractor.h
index ab40f53..0ac7673 100644
--- a/media/libmedia/include/media/IMediaExtractor.h
+++ b/media/libmedia/include/media/IMediaExtractor.h
@@ -20,14 +20,12 @@
 
 #include <media/IMediaSource.h>
 #include <media/stagefright/DataSource.h>
+#include <vector>
 
 namespace android {
 
 class MetaData;
-namespace media {
-class ICas;
-};
-using namespace media;
+typedef std::vector<uint8_t> HInterfaceToken;
 
 class IMediaExtractor : public IInterface {
 public:
@@ -65,11 +63,13 @@
     // for DRM
     virtual char* getDrmTrackInfo(size_t trackID, int *len)  = 0;
 
-    virtual status_t setMediaCas(const sp<ICas> &cas) = 0;
+    virtual status_t setMediaCas(const HInterfaceToken &casToken) = 0;
 
     virtual void setUID(uid_t uid)  = 0;
 
     virtual const char * name() = 0;
+
+    virtual void release() = 0;
 };
 
 
diff --git a/media/libmedia/include/media/IMediaMetadataRetriever.h b/media/libmedia/include/media/IMediaMetadataRetriever.h
index c90f254..ea95161 100644
--- a/media/libmedia/include/media/IMediaMetadataRetriever.h
+++ b/media/libmedia/include/media/IMediaMetadataRetriever.h
@@ -19,13 +19,12 @@
 #define ANDROID_IMEDIAMETADATARETRIEVER_H
 
 #include <binder/IInterface.h>
-#include <binder/Parcel.h>
 #include <binder/IMemory.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
 
 namespace android {
-
+class Parcel;
 class IDataSource;
 struct IMediaHTTPService;
 
@@ -41,8 +40,10 @@
             const KeyedVector<String8, String8> *headers = NULL) = 0;
 
     virtual status_t        setDataSource(int fd, int64_t offset, int64_t length) = 0;
-    virtual status_t        setDataSource(const sp<IDataSource>& dataSource) = 0;
-    virtual sp<IMemory>     getFrameAtTime(int64_t timeUs, int option) = 0;
+    virtual status_t        setDataSource(
+            const sp<IDataSource>& dataSource, const char *mime) = 0;
+    virtual sp<IMemory>     getFrameAtTime(
+            int64_t timeUs, int option, int colorFormat, bool metaOnly) = 0;
     virtual sp<IMemory>     extractAlbumArt() = 0;
     virtual const char*     extractMetadata(int keyCode) = 0;
 };
diff --git a/media/libmedia/include/media/IOMX.h b/media/libmedia/include/media/IOMX.h
index 9a0ada1..e69c02d 100644
--- a/media/libmedia/include/media/IOMX.h
+++ b/media/libmedia/include/media/IOMX.h
@@ -29,8 +29,9 @@
 #include <media/hardware/MetadataBufferType.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 
-#include <OMX_Core.h>
-#include <OMX_Video.h>
+#include <media/openmax/OMX_Core.h>
+#include <media/openmax/OMX_Video.h>
+#include <media/openmax/OMX_VideoExt.h>
 
 namespace android {
 
diff --git a/media/libmedia/include/media/IOMXStore.h b/media/libmedia/include/media/IOMXStore.h
new file mode 100644
index 0000000..628db70
--- /dev/null
+++ b/media/libmedia/include/media/IOMXStore.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IOMXSTORE_H_
+
+#define ANDROID_IOMXSTORE_H_
+
+#include <media/IOMX.h>
+#include <android/hardware/media/omx/1.0/IOmxStore.h>
+
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+
+#include <vector>
+#include <string>
+
+namespace android {
+
+using hardware::media::omx::V1_0::IOmxStore;
+
+class IOMXStore : public IInterface {
+public:
+    DECLARE_META_INTERFACE(OMXStore);
+
+    struct Attribute {
+        std::string key;
+        std::string value;
+    };
+
+    struct NodeInfo {
+        std::string name;
+        std::string owner;
+        std::vector<Attribute> attributes;
+    };
+
+    struct RoleInfo {
+        std::string role;
+        std::string type;
+        bool isEncoder;
+        bool preferPlatformNodes;
+        std::vector<NodeInfo> nodes;
+    };
+
+    virtual status_t listServiceAttributes(
+            std::vector<Attribute>* attributes) = 0;
+
+    virtual status_t getNodePrefix(std::string* prefix) = 0;
+
+    virtual status_t listRoles(std::vector<RoleInfo>* roleList) = 0;
+
+    virtual status_t getOmx(const std::string& name, sp<IOMX>* omx) = 0;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BnOMXStore : public BnInterface<IOMXStore> {
+public:
+    virtual status_t onTransact(
+            uint32_t code, const Parcel &data, Parcel *reply,
+            uint32_t flags = 0);
+};
+
+}  // namespace android
+
+#endif  // ANDROID_IOMX_H_
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index 6b50f22..ab2cd24 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -18,6 +18,7 @@
 
 #define MEDIA_CODEC_INFO_H_
 
+#include <android-base/macros.h>
 #include <binder/Parcel.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AString.h>
@@ -36,12 +37,20 @@
 
 typedef KeyedVector<AString, AString> CodecSettings;
 
+struct MediaCodecInfoWriter;
+struct MediaCodecListWriter;
+
 struct MediaCodecInfo : public RefBase {
     struct ProfileLevel {
         uint32_t mProfile;
         uint32_t mLevel;
+        bool operator <(const ProfileLevel &o) const {
+            return mProfile < o.mProfile || (mProfile == o.mProfile && mLevel < o.mLevel);
+        }
     };
 
+    struct CapabilitiesWriter;
+
     struct Capabilities : public RefBase {
         enum {
             // decoder flags
@@ -61,7 +70,9 @@
 
     protected:
         Vector<ProfileLevel> mProfileLevels;
+        SortedVector<ProfileLevel> mProfileLevelsSorted;
         Vector<uint32_t> mColorFormats;
+        SortedVector<uint32_t> mColorFormatsSorted;
         uint32_t mFlags;
         sp<AMessage> mDetails;
 
@@ -72,72 +83,191 @@
         static sp<Capabilities> FromParcel(const Parcel &parcel);
         status_t writeToParcel(Parcel *parcel) const;
 
-        DISALLOW_EVIL_CONSTRUCTORS(Capabilities);
+        DISALLOW_COPY_AND_ASSIGN(Capabilities);
 
         friend struct MediaCodecInfo;
+        friend struct MediaCodecInfoWriter;
+        friend struct CapabilitiesWriter;
     };
 
-    // Use a subclass to allow setting fields on construction without allowing
-    // to do the same throughout the framework.
-    struct CapabilitiesBuilder : public Capabilities {
+    /**
+     * This class is used for modifying information inside a `Capabilities`
+     * object. An object of type `CapabilitiesWriter` can be obtained by calling
+     * `MediaCodecInfoWriter::addMime()` or
+     * `MediaCodecInfoWriter::updateMime()`.
+     */
+    struct CapabilitiesWriter {
+        /**
+         * Add a key-value pair to the list of details. If the key already
+         * exists, the old value will be replaced.
+         *
+         * A pair added by this function will be accessible by
+         * `Capabilities::getDetails()`. Call `AMessage::getString()` with the
+         * same key to retrieve the value.
+         *
+         * @param key The key.
+         * @param value The string value.
+         */
+        void addDetail(const char* key, const char* value);
+        /**
+         * Add a key-value pair to the list of details. If the key already
+         * exists, the old value will be replaced.
+         *
+         * A pair added by this function will be accessible by
+         * `Capabilities::getDetails()`. Call `AMessage::getInt32()` with the
+         * same key to retrieve the value.
+         *
+         * @param key The key.
+         * @param value The `int32_t` value.
+         */
+        void addDetail(const char* key, int32_t value);
+        /**
+         * Add a profile-level pair. If this profile-level pair already exists,
+         * it will be ignored.
+         *
+         * @param profile The "profile" component.
+         * @param level The "level" component.
+         */
         void addProfileLevel(uint32_t profile, uint32_t level);
+        /**
+         * Add a color format. If this color format already exists, it will be
+         * ignored.
+         *
+         * @param format The color format.
+         */
         void addColorFormat(uint32_t format);
+        /**
+         * Add flags. The underlying operation is bitwise-or. In other words,
+         * bits that have already been set will be ignored.
+         *
+         * @param flags The additional flags.
+         */
         void addFlags(uint32_t flags);
+    private:
+        /**
+         * The associated `Capabilities` object.
+         */
+        Capabilities* mCap;
+        /**
+         * Construct a writer for the given `Capabilities` object.
+         *
+         * @param cap The `Capabilities` object to be written to.
+         */
+        CapabilitiesWriter(Capabilities* cap);
+
+        friend MediaCodecInfoWriter;
     };
 
     bool isEncoder() const;
-    bool hasQuirk(const char *name) const;
     void getSupportedMimes(Vector<AString> *mimes) const;
     const sp<Capabilities> getCapabilitiesFor(const char *mime) const;
     const char *getCodecName() const;
 
     /**
+     * Return the name of the service that hosts the codec. This value is not
+     * visible at the Java level.
+     *
+     * Currently, this is the "instance name" of the IOmx service.
+     */
+    const char *getOwnerName() const;
+
+    /**
      * Serialization over Binder
      */
     static sp<MediaCodecInfo> FromParcel(const Parcel &parcel);
     status_t writeToParcel(Parcel *parcel) const;
 
 private:
-    // variable set only in constructor - these are accessed by MediaCodecList
-    // to avoid duplication of same variables
     AString mName;
+    AString mOwner;
     bool mIsEncoder;
-    bool mHasSoleMime; // was initialized with mime
-
-    Vector<AString> mQuirks;
     KeyedVector<AString, sp<Capabilities> > mCaps;
 
-    sp<Capabilities> mCurrentCaps; // currently initalized capabilities
-
     ssize_t getCapabilityIndex(const char *mime) const;
 
-    /* Methods used by MediaCodecList to construct the info
-     * object from XML.
-     *
-     * After info object is created:
-     * - additional quirks can be added
-     * - additional mimes can be added
-     *   - OMX codec capabilities can be set for the current mime-type
-     *   - a capability detail can be set for the current mime-type
-     *   - a feature can be set for the current mime-type
-     *   - info object can be completed when parsing of a mime-type is done
+    /**
+     * Construct an `MediaCodecInfo` object. After the construction, its
+     * information can be set via an `MediaCodecInfoWriter` object obtained from
+     * `MediaCodecListWriter::addMediaCodecInfo()`.
      */
-    MediaCodecInfo(AString name, bool encoder, const char *mime);
-    void addQuirk(const char *name);
-    status_t addMime(const char *mime);
-    status_t updateMime(const char *mime);
+    MediaCodecInfo();
 
-    status_t initializeCapabilities(const sp<Capabilities> &caps);
-    void addDetail(const AString &key, const AString &value);
-    void addFeature(const AString &key, int32_t value);
-    void addFeature(const AString &key, const char *value);
-    void removeMime(const char *mime);
-    void complete();
+    DISALLOW_COPY_AND_ASSIGN(MediaCodecInfo);
 
-    DISALLOW_EVIL_CONSTRUCTORS(MediaCodecInfo);
-
-    friend struct MediaCodecList;
     friend class MediaCodecListOverridesTest;
+    friend struct MediaCodecInfoWriter;
+    friend struct MediaCodecListWriter;
+};
+
+/**
+ * This class is to be used by a `MediaCodecListBuilderBase` instance to
+ * populate information inside the associated `MediaCodecInfo` object.
+ *
+ * The only place where an instance of `MediaCodecInfoWriter` can be constructed
+ * is `MediaCodecListWriter::addMediaCodecInfo()`. A `MediaCodecListBuilderBase`
+ * instance should call `MediaCodecListWriter::addMediaCodecInfo()` on the given
+ * `MediaCodecListWriter` object given as an input to
+ * `MediaCodecListBuilderBase::buildMediaCodecList()`.
+ */
+struct MediaCodecInfoWriter {
+    /**
+     * Set the name of the codec.
+     *
+     * @param name The new name.
+     */
+    void setName(const char* name);
+    /**
+     * Set the owner name of the codec.
+     *
+     * This "owner name" is the name of the `IOmx` instance that supports this
+     * codec.
+     *
+     * @param owner The new owner name.
+     */
+    void setOwner(const char* owner);
+    /**
+     * Set whether this codec is an encoder or a decoder.
+     *
+     * @param isEncoder Whether this codec is an encoder or a decoder.
+     */
+    void setEncoder(bool isEncoder = true);
+    /**
+     * Add a mime to an indexed list and return a `CapabilitiesWriter` object
+     * that can be used for modifying the associated `Capabilities`.
+     *
+     * If the mime already exists, this function will return the
+     * `CapabilitiesWriter` associated with the mime.
+     *
+     * @param[in] mime The name of a new mime to add.
+     * @return writer The `CapabilitiesWriter` object for modifying the
+     * `Capabilities` associated with the mime. `writer` will be valid
+     * regardless of whether `mime` already exists or not.
+     */
+    std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> addMime(
+            const char* mime);
+    /**
+     * Remove a mime.
+     *
+     * @param mime The name of the mime to remove.
+     * @return `true` if `mime` is removed; `false` if `mime` is not found.
+     */
+    bool removeMime(const char* mime);
+private:
+    /**
+     * The associated `MediaCodecInfo`.
+     */
+    MediaCodecInfo* mInfo;
+    /**
+     * Construct the `MediaCodecInfoWriter` object associated with the given
+     * `MediaCodecInfo` object.
+     *
+     * @param info The underlying `MediaCodecInfo` object.
+     */
+    MediaCodecInfoWriter(MediaCodecInfo* info);
+
+    DISALLOW_COPY_AND_ASSIGN(MediaCodecInfoWriter);
+
+    friend struct MediaCodecListWriter;
 };
 
 }  // namespace android
diff --git a/media/libmedia/include/media/MediaMetadataRetrieverInterface.h b/media/libmedia/include/media/MediaMetadataRetrieverInterface.h
index a5e1350..257002d 100644
--- a/media/libmedia/include/media/MediaMetadataRetrieverInterface.h
+++ b/media/libmedia/include/media/MediaMetadataRetrieverInterface.h
@@ -41,8 +41,9 @@
             const KeyedVector<String8, String8> *headers = NULL) = 0;
 
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) = 0;
-    virtual status_t setDataSource(const sp<DataSource>& source) = 0;
-    virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) = 0;
+    virtual status_t setDataSource(const sp<DataSource>& source, const char *mime) = 0;
+    virtual VideoFrame* getFrameAtTime(
+            int64_t timeUs, int option, int colorFormat, bool metaOnly) = 0;
     virtual MediaAlbumArt* extractAlbumArt() = 0;
     virtual const char* extractMetadata(int keyCode) = 0;
 };
@@ -54,7 +55,9 @@
     MediaMetadataRetrieverInterface() {}
 
     virtual             ~MediaMetadataRetrieverInterface() {}
-    virtual VideoFrame* getFrameAtTime(int64_t /*timeUs*/, int /*option*/) { return NULL; }
+    virtual VideoFrame* getFrameAtTime(
+            int64_t /*timeUs*/, int /*option*/, int /*colorFormat*/, bool /*metaOnly*/)
+    { return NULL; }
     virtual MediaAlbumArt* extractAlbumArt() { return NULL; }
     virtual const char* extractMetadata(int /*keyCode*/) { return NULL; }
 };
diff --git a/media/libmedia/include/media/PluginMetricsReporting.h b/media/libmedia/include/media/PluginMetricsReporting.h
new file mode 100644
index 0000000..4a5a363
--- /dev/null
+++ b/media/libmedia/include/media/PluginMetricsReporting.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PLUGIN_METRICS_REPORTING_H_
+
+#define PLUGIN_METRICS_REPORTING_H_
+
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+status_t reportDrmPluginMetrics(const Vector<uint8_t>& serializedMetrics,
+                                const String8& vendorName,
+                                const String8& description);
+
+}  // namespace android
+
+#endif  // PLUGIN_METRICS_REPORTING_H_
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index 8ed07ee..65c266b 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -76,8 +76,10 @@
             const KeyedVector<String8, String8> *headers = NULL);
 
     status_t setDataSource(int fd, int64_t offset, int64_t length);
-    status_t setDataSource(const sp<IDataSource>& dataSource);
-    sp<IMemory> getFrameAtTime(int64_t timeUs, int option);
+    status_t setDataSource(
+            const sp<IDataSource>& dataSource, const char *mime = NULL);
+    sp<IMemory> getFrameAtTime(int64_t timeUs, int option,
+            int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
     sp<IMemory> extractAlbumArt();
     const char* extractMetadata(int keyCode);
 
diff --git a/include/media/omx/1.0/Conversion.h b/media/libmedia/include/media/omx/1.0/Conversion.h
similarity index 100%
rename from include/media/omx/1.0/Conversion.h
rename to media/libmedia/include/media/omx/1.0/Conversion.h
diff --git a/include/media/omx/1.0/WGraphicBufferSource.h b/media/libmedia/include/media/omx/1.0/WGraphicBufferSource.h
similarity index 100%
rename from include/media/omx/1.0/WGraphicBufferSource.h
rename to media/libmedia/include/media/omx/1.0/WGraphicBufferSource.h
diff --git a/include/media/omx/1.0/WOmx.h b/media/libmedia/include/media/omx/1.0/WOmx.h
similarity index 100%
rename from include/media/omx/1.0/WOmx.h
rename to media/libmedia/include/media/omx/1.0/WOmx.h
diff --git a/include/media/omx/1.0/WOmxBufferSource.h b/media/libmedia/include/media/omx/1.0/WOmxBufferSource.h
similarity index 98%
rename from include/media/omx/1.0/WOmxBufferSource.h
rename to media/libmedia/include/media/omx/1.0/WOmxBufferSource.h
index 86322da..086f648 100644
--- a/include/media/omx/1.0/WOmxBufferSource.h
+++ b/media/libmedia/include/media/omx/1.0/WOmxBufferSource.h
@@ -21,7 +21,7 @@
 #include <hidl/Status.h>
 
 #include <binder/Binder.h>
-#include <OMXFenceParcelable.h>
+#include <media/OMXFenceParcelable.h>
 
 #include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
 #include <android/BnOMXBufferSource.h>
diff --git a/include/media/omx/1.0/WOmxNode.h b/media/libmedia/include/media/omx/1.0/WOmxNode.h
similarity index 100%
rename from include/media/omx/1.0/WOmxNode.h
rename to media/libmedia/include/media/omx/1.0/WOmxNode.h
diff --git a/include/media/omx/1.0/WOmxObserver.h b/media/libmedia/include/media/omx/1.0/WOmxObserver.h
similarity index 100%
rename from include/media/omx/1.0/WOmxObserver.h
rename to media/libmedia/include/media/omx/1.0/WOmxObserver.h
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 08a9e6a..7d27d57 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -130,7 +130,7 @@
 }
 
 status_t MediaMetadataRetriever::setDataSource(
-    const sp<IDataSource>& dataSource)
+    const sp<IDataSource>& dataSource, const char *mime)
 {
     ALOGV("setDataSource(IDataSource)");
     Mutex::Autolock _l(mLock);
@@ -138,18 +138,20 @@
         ALOGE("retriever is not initialized");
         return INVALID_OPERATION;
     }
-    return mRetriever->setDataSource(dataSource);
+    return mRetriever->setDataSource(dataSource, mime);
 }
 
-sp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option)
+sp<IMemory> MediaMetadataRetriever::getFrameAtTime(
+        int64_t timeUs, int option, int colorFormat, bool metaOnly)
 {
-    ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d)", timeUs, option);
+    ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d) colorFormat(%d) metaOnly(%d)",
+            timeUs, option, colorFormat, metaOnly);
     Mutex::Autolock _l(mLock);
     if (mRetriever == 0) {
         ALOGE("retriever is not initialized");
         return NULL;
     }
-    return mRetriever->getFrameAtTime(timeUs, option);
+    return mRetriever->getFrameAtTime(timeUs, option, colorFormat, metaOnly);
 }
 
 const char* MediaMetadataRetriever::extractMetadata(int keyCode)
diff --git a/media/libmediametrics/IMediaAnalyticsService.cpp b/media/libmediametrics/IMediaAnalyticsService.cpp
index 68bafe1..28a7746 100644
--- a/media/libmediametrics/IMediaAnalyticsService.cpp
+++ b/media/libmediametrics/IMediaAnalyticsService.cpp
@@ -60,7 +60,7 @@
         data.writeInterfaceToken(IMediaAnalyticsService::getInterfaceDescriptor());
         err = remote()->transact(GENERATE_UNIQUE_SESSIONID, data, &reply);
         if (err != NO_ERROR) {
-            ALOGW("bad response from service");
+            ALOGW("bad response from service for generateSessionId, err=%d", err);
             return MediaAnalyticsItem::SessionIDInvalid;
         }
         sessionid = reply.readInt64();
@@ -94,6 +94,7 @@
 
         err = remote()->transact(SUBMIT_ITEM, data, &reply);
         if (err != NO_ERROR) {
+            ALOGW("bad response from service for submit, err=%d", err);
             return MediaAnalyticsItem::SessionIDInvalid;
         }
 
diff --git a/media/libmediametrics/MediaAnalyticsItem.cpp b/media/libmediametrics/MediaAnalyticsItem.cpp
index 43881b3..f968c09 100644
--- a/media/libmediametrics/MediaAnalyticsItem.cpp
+++ b/media/libmediametrics/MediaAnalyticsItem.cpp
@@ -59,6 +59,7 @@
 MediaAnalyticsItem::MediaAnalyticsItem()
     : mPid(-1),
       mUid(-1),
+      mPkgVersionCode(0),
       mSessionID(MediaAnalyticsItem::SessionIDNone),
       mTimestamp(0),
       mFinalized(0),
@@ -70,6 +71,7 @@
 MediaAnalyticsItem::MediaAnalyticsItem(MediaAnalyticsItem::Key key)
     : mPid(-1),
       mUid(-1),
+      mPkgVersionCode(0),
       mSessionID(MediaAnalyticsItem::SessionIDNone),
       mTimestamp(0),
       mFinalized(0),
@@ -98,7 +100,7 @@
 
     // clean attributes
     // contents of the attributes
-    for (size_t i = 0 ; i < mPropSize; i++ ) {
+    for (size_t i = 0 ; i < mPropCount; i++ ) {
         clearProp(&mProps[i]);
     }
     // the attribute records themselves
@@ -120,6 +122,8 @@
         // key as part of constructor
         dst->mPid = this->mPid;
         dst->mUid = this->mUid;
+        dst->mPkgName = this->mPkgName;
+        dst->mPkgVersionCode = this->mPkgVersionCode;
         dst->mSessionID = this->mSessionID;
         dst->mTimestamp = this->mTimestamp;
         dst->mFinalized = this->mFinalized;
@@ -201,6 +205,24 @@
     return mUid;
 }
 
+MediaAnalyticsItem &MediaAnalyticsItem::setPkgName(AString pkgName) {
+    mPkgName = pkgName;
+    return *this;
+}
+
+AString MediaAnalyticsItem::getPkgName() const {
+    return mPkgName;
+}
+
+MediaAnalyticsItem &MediaAnalyticsItem::setPkgVersionCode(int32_t pkgVersionCode) {
+    mPkgVersionCode = pkgVersionCode;
+    return *this;
+}
+
+int32_t MediaAnalyticsItem::getPkgVersionCode() const {
+    return mPkgVersionCode;
+}
+
 // this key is for the overall record -- "codec", "player", "drm", etc
 MediaAnalyticsItem &MediaAnalyticsItem::setKey(MediaAnalyticsItem::Key key) {
     mKey = key;
@@ -263,11 +285,30 @@
         i = mPropCount++;
         prop = &mProps[i];
         prop->setName(name, len);
+        prop->mType = kTypeNone;        // make caller set type info
     }
 
     return prop;
 }
 
+// used within the summarizers; return whether property existed
+bool MediaAnalyticsItem::removeProp(const char *name) {
+    size_t len = strlen(name);
+    size_t i = findPropIndex(name, len);
+    if (i < mPropCount) {
+        Prop *prop = &mProps[i];
+        clearProp(prop);
+        if (i != mPropCount-1) {
+            // in the middle, bring last one down to fill gap
+            copyProp(prop, &mProps[mPropCount-1]);
+            clearProp(&mProps[mPropCount-1]);
+        }
+        mPropCount--;
+        return true;
+    }
+    return false;
+}
+
 // set the values
 void MediaAnalyticsItem::setInt32(MediaAnalyticsItem::Attr name, int32_t value) {
     Prop *prop = allocateProp(name);
@@ -568,6 +609,10 @@
     // into 'this' object
     // .. we make a copy of the string to put away.
     mKey = data.readCString();
+    mPid = data.readInt32();
+    mUid = data.readInt32();
+    mPkgName = data.readCString();
+    mPkgVersionCode = data.readInt32();
     mSessionID = data.readInt64();
     mFinalized = data.readInt32();
     mTimestamp = data.readInt64();
@@ -611,6 +656,10 @@
 
 
     data->writeCString(mKey.c_str());
+    data->writeInt32(mPid);
+    data->writeInt32(mUid);
+    data->writeCString(mPkgName.c_str());
+    data->writeInt32(mPkgVersionCode);
     data->writeInt64(mSessionID);
     data->writeInt32(mFinalized);
     data->writeInt64(mTimestamp);
@@ -651,21 +700,54 @@
 
 
 AString MediaAnalyticsItem::toString() {
+   return toString(-1);
+}
 
-    AString result = "(";
+AString MediaAnalyticsItem::toString(int version) {
+
+    // v0 : released with 'o'
+    // v1 : bug fix (missing pid/finalized separator),
+    //      adds apk name, apk version code
+
+    if (version <= PROTO_FIRST) {
+        // default to original v0 format, until proper parsers are in place
+        version = PROTO_V0;
+    } else if (version > PROTO_LAST) {
+        version = PROTO_LAST;
+    }
+
+    AString result;
     char buffer[512];
 
+    if (version == PROTO_V0) {
+        result = "(";
+    } else {
+        snprintf(buffer, sizeof(buffer), "[%d:", version);
+        result.append(buffer);
+    }
+
     // same order as we spill into the parcel, although not required
     // key+session are our primary matching criteria
-    //RBE ALOGD("mKey.c_str");
     result.append(mKey.c_str());
-    //RBE ALOGD("post-mKey.c_str");
     result.append(":");
     snprintf(buffer, sizeof(buffer), "%" PRId64 ":", mSessionID);
     result.append(buffer);
 
-    // we need these internally, but don't want to upload them
-    snprintf(buffer, sizeof(buffer), "%d:%d", mUid, mPid);
+    snprintf(buffer, sizeof(buffer), "%d:", mUid);
+    result.append(buffer);
+
+    if (version >= PROTO_V1) {
+        result.append(mPkgName);
+        snprintf(buffer, sizeof(buffer), ":%d:", mPkgVersionCode);
+        result.append(buffer);
+    }
+
+    // in 'o' (v1) , the separator between pid and finalized was omitted
+    if (version <= PROTO_V0) {
+        snprintf(buffer, sizeof(buffer), "%d", mPid);
+    } else {
+        snprintf(buffer, sizeof(buffer), "%d:", mPid);
+    }
     result.append(buffer);
 
     snprintf(buffer, sizeof(buffer), "%d:", mFinalized);
@@ -713,7 +795,11 @@
             result.append(buffer);
     }
 
-    result.append(")");
+    if (version == PROTO_V0) {
+        result.append(")");
+    } else {
+        result.append("]");
+    }
 
     return result;
 }
@@ -734,11 +820,16 @@
     sp<IMediaAnalyticsService> svc = getInstance();
 
     if (svc != NULL) {
-        svc->submit(this, forcenew);
+        MediaAnalyticsItem::SessionID_t newid = svc->submit(this, forcenew);
+        if (newid == SessionIDInvalid) {
+            AString p = this->toString();
+            ALOGW("Failed to record: %s [forcenew=%d]", p.c_str(), forcenew);
+            return false;
+        }
         return true;
     } else {
         AString p = this->toString();
-        ALOGD("Unable to record: %s [forcenew=%d]", p.c_str(), forcenew);
+        ALOGW("Unable to record: %s [forcenew=%d]", p.c_str(), forcenew);
         return false;
     }
 }
@@ -747,6 +838,7 @@
 // static
 sp<IMediaAnalyticsService> MediaAnalyticsItem::sAnalyticsService;
 static Mutex sInitMutex;
+static int remainingBindAttempts = SVC_TRIES;
 
 //static
 bool MediaAnalyticsItem::isEnabled() {
@@ -764,10 +856,28 @@
     return true;
 }
 
+
+// monitor health of our connection to the metrics service
+class MediaMetricsDeathNotifier : public IBinder::DeathRecipient {
+        virtual void binderDied(const wp<IBinder> &) {
+            ALOGW("Reacquire service connection on next request");
+            MediaAnalyticsItem::dropInstance();
+        }
+};
+
+static sp<MediaMetricsDeathNotifier> sNotifier = NULL;
+
+// static
+void MediaAnalyticsItem::dropInstance() {
+    Mutex::Autolock _l(sInitMutex);
+    remainingBindAttempts = SVC_TRIES;
+    sAnalyticsService = NULL;
+}
+
 //static
 sp<IMediaAnalyticsService> MediaAnalyticsItem::getInstance() {
+
     static const char *servicename = "media.metrics";
-    static int tries_remaining = SVC_TRIES;
     int enabled = isEnabled();
 
     if (enabled == false) {
@@ -799,15 +909,20 @@
         Mutex::Autolock _l(sInitMutex);
         const char *badness = "";
 
-        // think of tries_remaining as telling us whether service==NULL because
+        // think of remainingBindAttempts as telling us whether service==NULL because
         // (1) we haven't tried to initialize it yet
         // (2) we've tried to initialize it, but failed.
-        if (sAnalyticsService == NULL && tries_remaining > 0) {
+        if (sAnalyticsService == NULL && remainingBindAttempts > 0) {
             sp<IServiceManager> sm = defaultServiceManager();
             if (sm != NULL) {
                 sp<IBinder> binder = sm->getService(String16(servicename));
                 if (binder != NULL) {
                     sAnalyticsService = interface_cast<IMediaAnalyticsService>(binder);
+                    if (sNotifier != NULL) {
+                        sNotifier = NULL;
+                    }
+                    sNotifier = new MediaMetricsDeathNotifier();
+                    binder->linkToDeath(sNotifier);
                 } else {
                     badness = "did not find service";
                 }
@@ -816,8 +931,8 @@
             }
 
             if (sAnalyticsService == NULL) {
-                if (tries_remaining > 0) {
-                    tries_remaining--;
+                if (remainingBindAttempts > 0) {
+                    remainingBindAttempts--;
                 }
                 if (DEBUG_SERVICEACCESS) {
                     ALOGD("Unable to bind to service %s: %s", servicename, badness);
@@ -829,7 +944,6 @@
     }
 }
 
-
 // merge the info from 'incoming' into this record.
 // we finish with a union of this+incoming and special handling for collisions
 bool MediaAnalyticsItem::merge(MediaAnalyticsItem *incoming) {
diff --git a/media/libmediametrics/include/MediaAnalyticsItem.h b/media/libmediametrics/include/MediaAnalyticsItem.h
index dc501b2..dd7452f 100644
--- a/media/libmediametrics/include/MediaAnalyticsItem.h
+++ b/media/libmediametrics/include/MediaAnalyticsItem.h
@@ -42,6 +42,7 @@
     friend class IMediaAnalyticsService;
     friend class MediaMetricsJNI;
     friend class MetricsSummarizer;
+    friend class MediaMetricsDeathNotifier;
 
     public:
 
@@ -75,6 +76,14 @@
         typedef const char *Attr;
 
 
+        enum {
+            PROTO_V0 = 0,
+            PROTO_FIRST = PROTO_V0,
+            PROTO_V1 = 1,
+            PROTO_LAST = PROTO_V1,
+        };
+
+
     public:
 
         // access functions for the class
@@ -161,11 +170,18 @@
         MediaAnalyticsItem &setUid(uid_t);
         uid_t getUid() const;
 
+        MediaAnalyticsItem &setPkgName(AString);
+        AString getPkgName() const;
+
+        MediaAnalyticsItem &setPkgVersionCode(int32_t);
+        int32_t getPkgVersionCode() const;
+
         // our serialization code for binder calls
         int32_t writeToParcel(Parcel *);
         int32_t readFromParcel(const Parcel&);
 
         AString toString();
+        AString toString(int version);
 
         // are we collecting analytics data
         static bool isEnabled();
@@ -188,10 +204,13 @@
         // to help validate that A doesn't mess with B's records
         pid_t     mPid;
         uid_t     mUid;
+        AString   mPkgName;
+        int32_t   mPkgVersionCode;
 
         // let's reuse a binder connection
         static sp<IMediaAnalyticsService> sAnalyticsService;
         static sp<IMediaAnalyticsService> getInstance();
+        static void dropInstance();
 
         // tracking information
         SessionID_t mSessionID;         // grouping similar records
@@ -228,6 +247,7 @@
         size_t findPropIndex(const char *name, size_t len);
         Prop *findProp(const char *name);
         Prop *allocateProp(const char *name);
+        bool removeProp(const char *name);
 
         size_t mPropCount;
         size_t mPropSize;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 942a8fc..496db0d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -77,7 +77,7 @@
 #include "TestPlayerStub.h"
 #include "nuplayer/NuPlayerDriver.h"
 
-#include <OMX.h>
+#include <media/stagefright/omx/OMX.h>
 
 #include "HDCP.h"
 #include "HTTPBase.h"
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 793f476..5a468f3 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -175,7 +175,7 @@
 }
 
 status_t MetadataRetrieverClient::setDataSource(
-        const sp<IDataSource>& source)
+        const sp<IDataSource>& source, const char *mime)
 {
     ALOGV("setDataSource(IDataSource)");
     Mutex::Autolock lock(mLock);
@@ -186,16 +186,18 @@
     ALOGV("player type = %d", playerType);
     sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
     if (p == NULL) return NO_INIT;
-    status_t ret = p->setDataSource(dataSource);
+    status_t ret = p->setDataSource(dataSource, mime);
     if (ret == NO_ERROR) mRetriever = p;
     return ret;
 }
 
 Mutex MetadataRetrieverClient::sLock;
 
-sp<IMemory> MetadataRetrieverClient::getFrameAtTime(int64_t timeUs, int option)
+sp<IMemory> MetadataRetrieverClient::getFrameAtTime(
+        int64_t timeUs, int option, int colorFormat, bool metaOnly)
 {
-    ALOGV("getFrameAtTime: time(%lld us) option(%d)", (long long)timeUs, option);
+    ALOGV("getFrameAtTime: time(%lld us) option(%d) colorFormat(%d), metaOnly(%d)",
+            (long long)timeUs, option, colorFormat, metaOnly);
     Mutex::Autolock lock(mLock);
     Mutex::Autolock glock(sLock);
     mThumbnail.clear();
@@ -203,12 +205,13 @@
         ALOGE("retriever is not initialized");
         return NULL;
     }
-    VideoFrame *frame = mRetriever->getFrameAtTime(timeUs, option);
+    VideoFrame *frame = mRetriever->getFrameAtTime(
+            timeUs, option, colorFormat, metaOnly);
     if (frame == NULL) {
         ALOGE("failed to capture a video frame");
         return NULL;
     }
-    size_t size = sizeof(VideoFrame) + frame->mSize;
+    size_t size = frame->getFlattenedSize();
     sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
     if (heap == NULL) {
         ALOGE("failed to create MemoryDealer");
@@ -222,16 +225,7 @@
         return NULL;
     }
     VideoFrame *frameCopy = static_cast<VideoFrame *>(mThumbnail->pointer());
-    frameCopy->mWidth = frame->mWidth;
-    frameCopy->mHeight = frame->mHeight;
-    frameCopy->mDisplayWidth = frame->mDisplayWidth;
-    frameCopy->mDisplayHeight = frame->mDisplayHeight;
-    frameCopy->mSize = frame->mSize;
-    frameCopy->mRotationAngle = frame->mRotationAngle;
-    ALOGV("rotation: %d", frameCopy->mRotationAngle);
-    frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);
-    memcpy(frameCopy->mData, frame->mData, frame->mSize);
-    frameCopy->mData = 0;
+    frameCopy->copyFlattened(*frame);
     delete frame;  // Fix memory leakage
     return mThumbnail;
 }
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index fe7547c..c78cd4b 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -49,8 +49,9 @@
             const KeyedVector<String8, String8> *headers);
 
     virtual status_t                setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t                setDataSource(const sp<IDataSource>& source);
-    virtual sp<IMemory>             getFrameAtTime(int64_t timeUs, int option);
+    virtual status_t                setDataSource(const sp<IDataSource>& source, const char *mime);
+    virtual sp<IMemory>             getFrameAtTime(
+            int64_t timeUs, int option, int colorFormat, bool metaOnly);
     virtual sp<IMemory>             extractAlbumArt();
     virtual const char*             extractMetadata(int keyCode);
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 6a09227..df36046 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1171,7 +1171,7 @@
                 if (mSource != nullptr) {
                     if (audio) {
                         if (mVideoDecoderError || mSource->getFormat(false /* audio */) == NULL
-                                || mSurface == NULL) {
+                                || mSurface == NULL || mVideoDecoder == NULL) {
                             // When both audio and video have error, or this stream has only audio
                             // which has error, notify client of error.
                             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
@@ -1182,7 +1182,7 @@
                         mAudioDecoderError = true;
                     } else {
                         if (mAudioDecoderError || mSource->getFormat(true /* audio */) == NULL
-                                || mAudioSink == NULL) {
+                                || mAudioSink == NULL || mAudioDecoder == NULL) {
                             // When both audio and video have error, or this stream has only video
                             // which has error, notify client of error.
                             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 8fe255b..ac187cc 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -343,7 +343,7 @@
             format, mSurface, crypto, 0 /* flags */);
 
     if (err != OK) {
-        ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
+        ALOGE("Failed to configure [%s] decoder (err=%d)", mComponentName.c_str(), err);
         mCodec->release();
         mCodec.clear();
         handleError(err);
@@ -372,7 +372,7 @@
 
     err = mCodec->start();
     if (err != OK) {
-        ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err);
+        ALOGE("Failed to start [%s] decoder (err=%d)", mComponentName.c_str(), err);
         mCodec->release();
         mCodec.clear();
         handleError(err);
@@ -460,6 +460,12 @@
     if (notifyComplete) {
         mResumePending = true;
     }
+
+    if (mCodec == NULL) {
+        ALOGE("[%s] onResume without a valid codec", mComponentName.c_str());
+        handleError(NO_INIT);
+        return;
+    }
     mCodec->start();
 }
 
@@ -481,7 +487,7 @@
     }
 
     if (err != OK) {
-        ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
+        ALOGE("failed to flush [%s] (err=%d)", mComponentName.c_str(), err);
         handleError(err);
         // finish with posting kWhatFlushCompleted.
         // we attempt to release the buffers even if flush fails.
@@ -530,7 +536,7 @@
     releaseAndResetMediaBuffers();
 
     if (err != OK) {
-        ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
+        ALOGE("failed to release [%s] (err=%d)", mComponentName.c_str(), err);
         handleError(err);
         // finish with posting kWhatShutdownCompleted.
     }
@@ -631,10 +637,17 @@
         return false;
     }
 
+    if (mCodec == NULL) {
+        ALOGE("[%s] handleAnInputBuffer without a valid codec", mComponentName.c_str());
+        handleError(NO_INIT);
+        return false;
+    }
+
     sp<MediaCodecBuffer> buffer;
     mCodec->getInputBuffer(index, &buffer);
 
     if (buffer == NULL) {
+        ALOGE("[%s] handleAnInputBuffer, failed to get input buffer", mComponentName.c_str());
         handleError(UNKNOWN_ERROR);
         return false;
     }
@@ -697,11 +710,18 @@
         size_t size,
         int64_t timeUs,
         int32_t flags) {
+    if (mCodec == NULL) {
+        ALOGE("[%s] handleAnOutputBuffer without a valid codec", mComponentName.c_str());
+        handleError(NO_INIT);
+        return false;
+    }
+
 //    CHECK_LT(bufferIx, mOutputBuffers.size());
     sp<MediaCodecBuffer> buffer;
     mCodec->getOutputBuffer(index, &buffer);
 
     if (buffer == NULL) {
+        ALOGE("[%s] handleAnOutputBuffer, failed to get output buffer", mComponentName.c_str());
         handleError(UNKNOWN_ERROR);
         return false;
     }
@@ -949,6 +969,12 @@
 }
 
 bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
+    if (mCodec == NULL) {
+        ALOGE("[%s] onInputBufferFetched without a valid codec", mComponentName.c_str());
+        handleError(NO_INIT);
+        return false;
+    }
+
     size_t bufferIx;
     CHECK(msg->findSize("buffer-ix", &bufferIx));
     CHECK_LT(bufferIx, mInputBuffers.size());
@@ -979,7 +1005,7 @@
         }
 
         if (streamErr != ERROR_END_OF_STREAM) {
-            ALOGE("Stream error for %s (err=%d), EOS %s queued",
+            ALOGE("Stream error for [%s] (err=%d), EOS %s queued",
                     mComponentName.c_str(),
                     streamErr,
                     err == OK ? "successfully" : "unsuccessfully");
@@ -1073,7 +1099,7 @@
         } // no cryptInfo
 
         if (err != OK) {
-            ALOGE("onInputBufferFetched: queue%sInputBuffer failed for %s (err=%d, %s)",
+            ALOGE("onInputBufferFetched: queue%sInputBuffer failed for [%s] (err=%d, %s)",
                     (cryptInfo != NULL ? "Secure" : ""),
                     mComponentName.c_str(), err, errorDetailMsg.c_str());
             handleError(err);
@@ -1102,7 +1128,9 @@
         }
     }
 
-    if (msg->findInt32("render", &render) && render) {
+    if (mCodec == NULL) {
+        err = NO_INIT;
+    } else if (msg->findInt32("render", &render) && render) {
         int64_t timestampNs;
         CHECK(msg->findInt64("timestampNs", &timestampNs));
         err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
@@ -1111,7 +1139,7 @@
         err = mCodec->releaseOutputBuffer(bufferIx);
     }
     if (err != OK) {
-        ALOGE("failed to release output buffer for %s (err=%d)",
+        ALOGE("failed to release output buffer for [%s] (err=%d)",
                 mComponentName.c_str(), err);
         handleError(err);
     }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index ad788f7..dc29761 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -69,6 +69,7 @@
       mPlayer(new NuPlayer(pid)),
       mPlayerFlags(0),
       mAnalyticsItem(NULL),
+      mClientUid(-1),
       mAtEOS(false),
       mLooping(false),
       mAutoLoop(false) {
@@ -109,6 +110,10 @@
 
 status_t NuPlayerDriver::setUID(uid_t uid) {
     mPlayer->setUID(uid);
+    mClientUid = uid;
+    if (mAnalyticsItem) {
+        mAnalyticsItem->setUid(mClientUid);
+    }
 
     return OK;
 }
@@ -601,6 +606,7 @@
         mAnalyticsItem = new MediaAnalyticsItem("nuplayer");
         if (mAnalyticsItem) {
             mAnalyticsItem->generateSessionID();
+            mAnalyticsItem->setUid(mClientUid);
         }
     } else {
         ALOGV("did not have anything to record");
@@ -639,11 +645,6 @@
         notifyListener_l(MEDIA_STOPPED);
     }
 
-    if (property_get_bool("persist.debug.sf.stats", false)) {
-        Vector<String16> args;
-        dump(-1, args);
-    }
-
     mState = STATE_RESET_IN_PROGRESS;
     mPlayer->resetAsync();
 
@@ -935,7 +936,10 @@
                     // don't send completion event when looping
                     return;
                 }
-
+                if (property_get_bool("persist.debug.sf.stats", false)) {
+                    Vector<String16> args;
+                    dump(-1, args);
+                }
                 mPlayer->pause();
                 mState = STATE_PAUSED;
             }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index c5ddcb0..d0cf1dd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -132,11 +132,13 @@
     uint32_t mPlayerFlags;
 
     MediaAnalyticsItem *mAnalyticsItem;
+    uid_t mClientUid;
 
     bool mAtEOS;
     bool mLooping;
     bool mAutoLoop;
 
+
     void updateMetrics(const char *where);
     void logMetrics(const char *where);
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 758db1f..bd866cb 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -840,7 +840,7 @@
         return;
     }
 
-    notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
+    notifyEOS_l(true /* audio */, ERROR_END_OF_STREAM);
 }
 
 size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
@@ -917,10 +917,10 @@
             if (mAudioSink->needsTrailingPadding()) {
                 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
             }
-            ALOGV("fillAudioBuffer: notifyEOS "
+            ALOGV("fillAudioBuffer: notifyEOS_l "
                     "mNumFramesWritten:%u  finalResult:%d  postEOSDelay:%lld",
                     mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
-            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
+            notifyEOS_l(true /* audio */, entry->mFinalResult, postEOSDelayUs);
         }
     }
     return sizeCopied;
@@ -1152,7 +1152,18 @@
             return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
         }
     }
-    return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
+
+    const int64_t audioSinkPlayedUs = mAudioSink->getPlayedOutDurationUs(nowUs);
+    int64_t pendingUs = writtenAudioDurationUs - audioSinkPlayedUs;
+    if (pendingUs < 0) {
+        // This shouldn't happen unless the timestamp is stale.
+        ALOGW("%s: pendingUs %lld < 0, clamping to zero, potential resume after pause "
+                "writtenAudioDurationUs: %lld, audioSinkPlayedUs: %lld",
+                __func__, (long long)pendingUs,
+                (long long)writtenAudioDurationUs, (long long)audioSinkPlayedUs);
+        pendingUs = 0;
+    }
+    return pendingUs;
 }
 
 int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
@@ -1408,6 +1419,11 @@
 }
 
 void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
+    Mutex::Autolock autoLock(mLock);
+    notifyEOS_l(audio, finalResult, delayUs);
+}
+
+void NuPlayer::Renderer::notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs) {
     if (audio && delayUs > 0) {
         sp<AMessage> msg = new AMessage(kWhatEOS, this);
         msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
@@ -1420,6 +1436,11 @@
     notify->setInt32("audio", static_cast<int32_t>(audio));
     notify->setInt32("finalResult", finalResult);
     notify->post(delayUs);
+
+    if (audio) {
+        // Video might outlive audio. Clear anchor to enable video only case.
+        mAnchorTimeMediaUs = -1;
+    }
 }
 
 void NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index e6850b5..f58b79c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -275,6 +275,7 @@
     void onChangeAudioFormat(const sp<AMessage> &meta, const sp<AMessage> &notify);
 
     void notifyEOS(bool audio, status_t finalResult, int64_t delayUs = 0);
+    void notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs = 0);
     void notifyFlushComplete(bool audio);
     void notifyPosition();
     void notifyVideoLateBy(int64_t lateByUs);
diff --git a/media/libnbaio/Android.bp b/media/libnbaio/Android.bp
index f511876..4220b77 100644
--- a/media/libnbaio/Android.bp
+++ b/media/libnbaio/Android.bp
@@ -1,15 +1,51 @@
+
+cc_defaults {
+    name: "libnbaio_mono_defaults",
+    srcs: [
+        "MonoPipe.cpp",
+        "MonoPipeReader.cpp",
+        "NBAIO.cpp",
+    ],
+    header_libs: [
+        "libaudioclient_headers",
+        "libaudio_system_headers",
+        "libmedia_headers",
+    ],
+    export_header_lib_headers: [
+        "libaudioclient_headers",
+        "libmedia_headers",
+    ],
+
+    shared_libs: [
+        "libaudioutils",
+        "liblog",
+        "libutils",
+    ],
+
+    export_include_dirs: ["include_mono"],
+}
+
+// libnbaio_mono is the part of libnbaio that is available for vendors to use. Vendor modules can't
+// link against libnbaio and system modules can't link against libnbaio_mono. The rest of libnbaio
+// pulls in too many other dependencies.
+cc_library_shared {
+    name: "libnbaio_mono",
+    vendor: true,
+    defaults: ["libnbaio_mono_defaults"],
+}
+
 cc_library_shared {
     name: "libnbaio",
+    defaults: ["libnbaio_mono_defaults"],
     srcs: [
         "AudioBufferProviderSource.cpp",
         "AudioStreamInSource.cpp",
         "AudioStreamOutSink.cpp",
-        "MonoPipe.cpp",
-        "MonoPipeReader.cpp",
-        "NBAIO.cpp",
         "NBLog.cpp",
+        "PerformanceAnalysis.cpp",
         "Pipe.cpp",
         "PipeReader.cpp",
+        "ReportPerformance.cpp",
         "SourceAudioBufferProvider.cpp",
     ],
 
@@ -24,8 +60,8 @@
         "libaudioutils",
         "libbinder",
         "libcutils",
-        "libutils",
         "liblog",
+        "libutils",
     ],
 
     cflags: [
@@ -35,7 +71,5 @@
 
     include_dirs: ["system/media/audio_utils/include"],
 
-    local_include_dirs: ["include"],
-
     export_include_dirs: ["include"],
 }
diff --git a/media/libnbaio/AudioStreamOutSink.cpp b/media/libnbaio/AudioStreamOutSink.cpp
index cbff87d..8564899 100644
--- a/media/libnbaio/AudioStreamOutSink.cpp
+++ b/media/libnbaio/AudioStreamOutSink.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include <utils/Log.h>
+#include <audio_utils/clock.h>
 #include <media/audiohal/StreamHalInterface.h>
 #include <media/nbaio/AudioStreamOutSink.h>
 
@@ -82,8 +83,7 @@
         return INVALID_OPERATION;
     }
     timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = position64;
-    timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
-            time.tv_sec * 1000000000LL + time.tv_nsec;
+    timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = audio_utils_ns_from_timespec(&time);
     return OK;
 }
 
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index ebb90c8..2f639d2 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -18,14 +18,14 @@
 * Documentation: Workflow summary for histogram data processing:
 * For more details on FIFO, please see system/media/audio_utils; doxygen
 * TODO: add this documentation to doxygen once it is further developed
-* 1) writing the data to a buffer
-* onWork
+* 1) Writing buffer period timestamp to the circular buffer
+* onWork()
 *     Called every period length (e.g., 4ms)
 *     Calls LOG_HIST_TS
 * LOG_HIST_TS
-*     Hashes file name and line number
-*     calls NBLOG::Writer::logHistTS once
-* NBLOG::Writer::logHistTS
+*     Hashes file name and line number, and writes single timestamp to buffer
+*     calls NBLOG::Writer::logEventHistTS once
+* NBLOG::Writer::logEventHistTS
 *     calls NBLOG::Writer::log on hash and current timestamp
 *     time is in CLOCK_MONOTONIC converted to ns
 * NBLOG::Writer::log(Event, const void*, size_t)
@@ -44,6 +44,8 @@
 * ssize_t audio_utils_fifo_reader::obtain
 *     Determines readable buffer section via pointer arithmetic on reader
 *     and writer pointers
+* Similarly, LOG_AUDIO_STATE() is called by onStateChange whenever audio is
+* turned on or off, and writes this notification to the FIFO.
 *
 * 2) reading the data from shared memory
 * Thread::threadloop()
@@ -51,6 +53,7 @@
 * NBLog::MergeThread::threadLoop()
 *     calls NBLog::Merger::merge
 * NBLog::Merger::merge
+*     Merges snapshots sorted by timestamp
 *     for each reader in vector of class NamedReader,
 *     callsNamedReader::reader()->getSnapshot
 *     TODO: check whether the rest of this function is relevant
@@ -59,11 +62,12 @@
 *     calls mFifoReader->obtain to find readable data
 *     sets snapshot.begin() and .end() iterators to boundaries of valid entries
 *     moves the fifo reader index to after the last entry read
-*     in this case, the buffer is in shared memory. in (3), the buffer is private
+*     in this case, the buffer is in shared memory. in (4), the buffer is private
 *
 * 3) reading the data from private buffer
 * MediaLogService::dump
-*     calls NBLog::Reader::dump(int) on instance of subclass mergeReader
+*     calls NBLog::Reader::dump(CONSOLE)
+*     The private buffer contains all logs for all readers in shared memory
 * NBLog::Reader::dump(int)
 *     calls getSnapshot on the current reader
 *     calls dump(int, size_t, Snapshot)
@@ -72,9 +76,10 @@
 *     (string, timestamp, etc...)
 *     In the case of EVENT_HISTOGRAM_ENTRY_TS, adds a list of timestamp sequences
 *     (histogram entry) to NBLog::mHists
-*     In the case of EVENT_HISTOGRAM_FLUSH, calls drawHistogram on each element in
-*     the list and erases it
-*     TODO: when do these events occur?
+*     TODO: add every HISTOGRAM_ENTRY_TS to two
+*     circular buffers: one short-term and one long-term (can add even longer-term
+*     structures in the future). When dump is called, print everything currently
+*     in the buffer.
 * NBLog::drawHistogram
 *     input: timestamp array
 *     buckets this to a histogram and prints
@@ -82,7 +87,7 @@
 */
 
 #define LOG_TAG "NBLog"
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
 
 #include <algorithm>
 #include <climits>
@@ -102,6 +107,8 @@
 #include <new>
 #include <audio_utils/roundup.h>
 #include <media/nbaio/NBLog.h>
+#include <media/nbaio/PerformanceAnalysis.h>
+#include <media/nbaio/ReportPerformance.h>
 // #include <utils/CallStack.h> // used to print callstack
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -134,7 +141,7 @@
     switch (type) {
     case EVENT_START_FMT:
         return std::make_unique<FormatEntry>(FormatEntry(ptr));
-    case EVENT_HISTOGRAM_FLUSH:
+    case EVENT_AUDIO_STATE:
     case EVENT_HISTOGRAM_ENTRY_TS:
         return std::make_unique<HistogramEntry>(HistogramEntry(ptr));
     default:
@@ -513,7 +520,7 @@
     log(EVENT_HASH, &hash, sizeof(hash));
 }
 
-void NBLog::Writer::logHistTS(log_hash_t hash)
+void NBLog::Writer::logEventHistTs(Event event, log_hash_t hash)
 {
     if (!mEnabled) {
         return;
@@ -522,22 +529,7 @@
     data.hash = hash;
     data.ts = get_monotonic_ns();
     if (data.ts > 0) {
-        log(EVENT_HISTOGRAM_ENTRY_TS, &data, sizeof(data));
-    } else {
-        ALOGE("Failed to get timestamp");
-    }
-}
-
-void NBLog::Writer::logHistFlush(log_hash_t hash)
-{
-    if (!mEnabled) {
-        return;
-    }
-    HistTsEntry data;
-    data.hash = hash;
-    data.ts = get_monotonic_ns();
-    if (data.ts > 0) {
-        log(EVENT_HISTOGRAM_FLUSH, &data, sizeof(data));
+        log(event, &data, sizeof(data));
     } else {
         ALOGE("Failed to get timestamp");
     }
@@ -771,15 +763,15 @@
                                                            NBLog::Event::EVENT_HISTOGRAM_ENTRY_TS};
 const std::set<NBLog::Event> NBLog::Reader::endingTypes   {NBLog::Event::EVENT_END_FMT,
                                                            NBLog::Event::EVENT_HISTOGRAM_ENTRY_TS,
-                                                           NBLog::Event::EVENT_HISTOGRAM_FLUSH};
+                                                           NBLog::Event::EVENT_AUDIO_STATE};
+
 NBLog::Reader::Reader(const void *shared, size_t size)
     : mShared((/*const*/ Shared *) shared), /*mIMemory*/
       mFd(-1), mIndent(0),
       mFifo(mShared != NULL ?
         new audio_utils_fifo(size, sizeof(uint8_t),
             mShared->mBuffer, mShared->mRear, NULL /*throttlesFront*/) : NULL),
-      mFifoReader(mFifo != NULL ? new audio_utils_fifo_reader(*mFifo) : NULL),
-      findGlitch(false)
+      mFifoReader(mFifo != NULL ? new audio_utils_fifo_reader(*mFifo) : NULL)
 {
 }
 
@@ -795,39 +787,6 @@
     delete mFifo;
 }
 
-inline static int deltaMs(int64_t ns1, int64_t ns2) {
-    return (ns2 - ns1) / (1000 * 1000);
-}
-
-// Produces a log warning if the timing of recent buffer periods caused a glitch
-// Computes sum of running window of three buffer periods
-// Checks whether the buffer periods leave enough CPU time for the next one
-// e.g. if a buffer period is expected to be 4 ms and a buffer requires 3 ms of CPU time,
-// here are some glitch cases:
-// 4 + 4 + 6 ; 5 + 4 + 5; 2 + 2 + 10
-// TODO: develop this code to track changes in histogram distribution in addition
-// to / instead of glitches
-void NBLog::Reader::alertIfGlitch(const std::vector<int64_t> &samples) {
-    //TODO: measure kPeriodLen and kRatio from the data as they may change.
-    static const int kPeriodLen = 4; // current period length is ideally 4 ms
-    static const double kRatio = 0.75; // estimate of CPU time as ratio of period length
-    // DAC processing time for 4 ms buffer
-    static const int kPeriodTime = static_cast<int>(round(kPeriodLen * kRatio));
-    static const int kNumBuff = 3; // number of buffers considered in local history
-    std::deque<int> periods(kNumBuff, kPeriodLen);
-    for (size_t i = 2; i < samples.size(); ++i) { // skip first time entry
-        periods.push_front(deltaMs(samples[i - 1], samples[i]));
-        periods.pop_back();
-        // TODO: check that all glitch cases are covered
-        if (std::accumulate(periods.begin(), periods.end(), 0) > kNumBuff * kPeriodLen +
-            kPeriodLen - kPeriodTime) {
-                ALOGW("A glitch occurred");
-                periods.assign(kNumBuff, kPeriodLen);
-        }
-    }
-    return;
-}
-
 const uint8_t *NBLog::Reader::findLastEntryOfTypes(const uint8_t *front, const uint8_t *back,
                                             const std::set<Event> &types) {
     while (back + Entry::kPreviousLengthOffset >= front) {
@@ -911,61 +870,17 @@
 
 }
 
-// writes sample deltas to file, either truncating or appending
-inline void writeHistToFile(const std::vector<int64_t> &samples, bool append) {
-    // name of file on audioserver
-    static const char* const kName = (char *)"/data/misc/audioserver/sample_results.txt";
-    // stores deltas between the samples
-    std::vector<int64_t> intervals;
-    for (size_t i = 1; i < samples.size(); ++i) {
-        intervals.push_back(deltaMs(samples[i - 1], samples[i]));
-    }
-    if (intervals.empty()) return;
-    // Deletes maximum value in a histogram. Temp quick fix.
-    // FIXME: need to find root cause of approx. 35th element from the end
-    // consistently being an outlier in the first histogram of a flush
-    // ALOGW("%" PRId64 "before", (int64_t) *(std::max_element(intervals.begin(), intervals.end())));
-    intervals.erase(std::max_element(intervals.begin(), intervals.end()));
-    // ALOGW("%" PRId64 "after", (int64_t) *(std::max_element(intervals.begin(), intervals.end())));
-    std::ofstream ofs;
-    ofs.open(kName, append ? std::ios::app : std::ios::trunc);
-    if (!ofs) {
-        ALOGW("couldn't open file %s", kName);
-        return;
-    }
-    for (size_t i = 0; i < intervals.size(); ++i) {
-        ofs << intervals[i] << "\n";
-    }
-    ofs.close();
-}
-
+// TODO: move this to PerformanceAnalysis
+// TODO: make call to dump periodic so that data in shared FIFO does not get overwritten
 void NBLog::Reader::dump(int fd, size_t indent, NBLog::Reader::Snapshot &snapshot)
 {
-  //  CallStack cs(LOG_TAG);
-#if 0
-    struct timespec ts;
-    time_t maxSec = -1;
-    while (entry - start >= (int) Entry::kOverhead) {
-        if (prevEntry - start < 0 || !prevEntry.hasConsistentLength()) {
-            break;
-        }
-        if (prevEntry->type == EVENT_TIMESTAMP) {
-            if (prevEntry->length != sizeof(struct timespec)) {
-                // corrupt
-                break;
-            }
-            prevEntry.copyData((uint8_t*) &ts);
-            if (ts.tv_sec > maxSec) {
-                maxSec = ts.tv_sec;
-            }
-        }
-        --entry;
-        --prevEntry;
-    }
-#endif
     mFd = fd;
     mIndent = indent;
     String8 timestamp, body;
+    // FIXME: this is not thread safe
+    // TODO: need a separate instance of performanceAnalysis for each thread
+    // used to store data and to call analysis functions
+    static ReportPerformance::PerformanceAnalysis performanceAnalysis;
     size_t lost = snapshot.lost() + (snapshot.begin() - EntryIterator(snapshot.data()));
     if (lost > 0) {
         body.appendFormat("warning: lost %zu bytes worth of events", lost);
@@ -973,85 +888,9 @@
         //      log to push it out.  Consider keeping the timestamp/body between calls to copyEntryDataAt().
         dumpLine(timestamp, body);
     }
-#if 0
-    size_t width = 1;
-    while (maxSec >= 10) {
-        ++width;
-        maxSec /= 10;
-    }
-    if (maxSec >= 0) {
-        timestamp.appendFormat("[%*s]", (int) width + 4, "");
-    }
-    bool deferredTimestamp = false;
-#endif
 
     for (auto entry = snapshot.begin(); entry != snapshot.end();) {
         switch (entry->type) {
-#if 0
-        case EVENT_STRING:
-            body.appendFormat("%.*s", (int) entry.length(), entry.data());
-            break;
-        case EVENT_TIMESTAMP: {
-            // already checked that length == sizeof(struct timespec);
-            entry.copyData((const uint8_t*) &ts);
-            long prevNsec = ts.tv_nsec;
-            long deltaMin = LONG_MAX;
-            long deltaMax = -1;
-            long deltaTotal = 0;
-            auto aux(entry);
-            for (;;) {
-                ++aux;
-                if (end - aux >= 0 || aux.type() != EVENT_TIMESTAMP) {
-                    break;
-                }
-                struct timespec tsNext;
-                aux.copyData((const uint8_t*) &tsNext);
-                if (tsNext.tv_sec != ts.tv_sec) {
-                    break;
-                }
-                long delta = tsNext.tv_nsec - prevNsec;
-                if (delta < 0) {
-                    break;
-                }
-                if (delta < deltaMin) {
-                    deltaMin = delta;
-                }
-                if (delta > deltaMax) {
-                    deltaMax = delta;
-                }
-                deltaTotal += delta;
-                prevNsec = tsNext.tv_nsec;
-            }
-            size_t n = (aux - entry) / (sizeof(struct timespec) + 3 /*Entry::kOverhead?*/);
-            if (deferredTimestamp) {
-                dumpLine(timestamp, body);
-                deferredTimestamp = false;
-            }
-            timestamp.clear();
-            if (n >= kSquashTimestamp) {
-                timestamp.appendFormat("[%d.%03d to .%.03d by .%.03d to .%.03d]",
-                        (int) ts.tv_sec, (int) (ts.tv_nsec / 1000000),
-                        (int) ((ts.tv_nsec + deltaTotal) / 1000000),
-                        (int) (deltaMin / 1000000), (int) (deltaMax / 1000000));
-                entry = aux;
-                // advance = 0;
-                break;
-            }
-            timestamp.appendFormat("[%d.%03d]", (int) ts.tv_sec,
-                    (int) (ts.tv_nsec / 1000000));
-            deferredTimestamp = true;
-            }
-            break;
-        case EVENT_INTEGER:
-            appendInt(&body, entry.data());
-            break;
-        case EVENT_FLOAT:
-            appendFloat(&body, entry.data());
-            break;
-        case EVENT_PID:
-            appendPID(&body, entry.data(), entry.length());
-            break;
-#endif
         case EVENT_START_FMT:
             entry = handleFormat(FormatEntry(entry), &timestamp, &body);
             break;
@@ -1063,40 +902,12 @@
             memcpy(&hash, &(data->hash), sizeof(hash));
             int64_t ts;
             memcpy(&ts, &data->ts, sizeof(ts));
-            const std::pair<log_hash_t, int> key(hash, data->author);
-            // TODO might want to filter excessively high outliers, which are usually caused
-            // by the thread being inactive.
-            mHists[key].push_back(ts);
+            performanceAnalysis.logTsEntry(ts);
             ++entry;
             break;
         }
-        // draws histograms stored in global Reader::mHists and erases them
-        case EVENT_HISTOGRAM_FLUSH: {
-            HistogramEntry histEntry(entry);
-            // Log timestamp
-            // Timestamp of call to drawHistogram, not when audio was generated
-            const int64_t ts = histEntry.timestamp();
-            timestamp.clear();
-            timestamp.appendFormat("[%d.%03d]", (int) (ts / (1000 * 1000 * 1000)),
-                            (int) ((ts / (1000 * 1000)) % 1000));
-            // Log histograms
-            setFindGlitch(true);
-            body.appendFormat("Histogram flush - ");
-            handleAuthor(histEntry, &body);
-            for (auto hist = mHists.begin(); hist != mHists.end();) {
-                if (hist->first.second == histEntry.author()) {
-                    body.appendFormat("%X", (int)hist->first.first);
-                    if (findGlitch) {
-                        alertIfGlitch(hist->second);
-                    }
-                    // set file to empty and write data for all histograms in this set
-                    writeHistToFile(hist->second, hist != mHists.begin());
-                    drawHistogram(&body, hist->second, true, indent);
-                    hist = mHists.erase(hist);
-                } else {
-                    ++hist;
-                }
-            }
+        case EVENT_AUDIO_STATE: {
+            performanceAnalysis.handleStateChange();
             ++entry;
             break;
         }
@@ -1110,10 +921,10 @@
             ++entry;
             break;
         }
-
-        if (!body.isEmpty()) {
-            dumpLine(timestamp, body);
-        }
+    }
+    performanceAnalysis.reportPerformance(&body);
+    if (!body.isEmpty()) {
+        dumpLine(timestamp, body);
     }
 }
 
@@ -1139,16 +950,6 @@
     return iMemory != 0 && mIMemory != 0 && iMemory->pointer() == mIMemory->pointer();
 }
 
-void NBLog::Reader::setFindGlitch(bool s)
-{
-    findGlitch = s;
-}
-
-bool NBLog::Reader::isFindGlitch() const
-{
-    return findGlitch;
-}
-
 // ---------------------------------------------------------------------------
 
 void NBLog::appendTimestamp(String8 *body, const void *data) {
@@ -1283,126 +1084,6 @@
     return arg;
 }
 
-static int widthOf(int x) {
-    int width = 0;
-    while (x > 0) {
-        ++width;
-        x /= 10;
-    }
-    return width;
-}
-
-static std::map<int, int> buildBuckets(const std::vector<int64_t> &samples) {
-    // TODO allow buckets of variable resolution
-    std::map<int, int> buckets;
-    for (size_t i = 1; i < samples.size(); ++i) {
-        ++buckets[deltaMs(samples[i - 1], samples[i])];
-    }
-    return buckets;
-}
-
-static inline uint32_t log2(uint32_t x) {
-    // This works for x > 0
-    return 31 - __builtin_clz(x);
-}
-
-// TODO put this function in separate file. Make it return a std::string instead of modifying body
-/*
-Example output:
-[54.234] Histogram flush - AudioOut_D:
-Histogram 33640BF1
-            [ 1][ 1][ 1][ 3][54][69][ 1][ 2][ 1]
-        64|                      []
-        32|                  []  []
-        16|                  []  []
-         8|                  []  []
-         4|                  []  []
-         2|______________[]__[]__[]______[]____
-              4   5   6   8   9  10  11  13  15
-Notice that all values that fall in the same row have the same height (65 and 127 are displayed
-identically). That's why exact counts are added at the top.
-*/
-void NBLog::Reader::drawHistogram(String8 *body,
-                                  const std::vector<int64_t> &samples,
-                                  bool logScale,
-                                  int indent,
-                                  int maxHeight) {
-    // this avoids some corner cases
-    if (samples.size() <= 1) {
-        return;
-    }
-    // temp code for debugging the outlier timestamp
-    const int kMaxMs = 100;
-    for (size_t i = 1; i < samples.size()-1; ++i) {
-        const int currDelta = deltaMs(samples[i - 1], samples[i]);
-        if (currDelta > kMaxMs) {
-            body->appendFormat("\nlocation: %zu, size: %zu, pos from end: %zu, %d\t", i,
-                           samples.size(), samples.size() - i, currDelta);
-        }
-    }
-    // FIXME: as can be seen when printing the values, the outlier timestamps typically occur
-    // in the first histogram 35 to 38 indices from the end (most often 35).
-    // TODO: build histogram buckets earlier and discard timestamps to save memory
-    std::map<int, int> buckets = buildBuckets(samples);
-    // TODO consider changing all ints to uint32_t or uint64_t
-
-    // underscores and spaces length corresponds to maximum width of histogram
-    static const int kLen = 40;
-    std::string underscores(kLen, '-');
-    std::string spaces(kLen, ' ');
-
-    auto it = buckets.begin();
-    int maxDelta = it->first;
-    int maxCount = it->second;
-    // Compute maximum values
-    while (++it != buckets.end()) {
-        if (it->first > maxDelta) {
-            maxDelta = it->first;
-        }
-        if (it->second > maxCount) {
-            maxCount = it->second;
-        }
-    }
-    int height = logScale ? log2(maxCount) + 1 : maxCount; // maxCount > 0, safe to call log2
-    const int leftPadding = widthOf(logScale ? pow(2, height) : maxCount);
-    const int colWidth = std::max(std::max(widthOf(maxDelta) + 1, 3), leftPadding + 2);
-    int scalingFactor = 1;
-    // scale data if it exceeds maximum height
-    if (height > maxHeight) {
-        scalingFactor = (height + maxHeight) / maxHeight;
-        height /= scalingFactor;
-    }
-    body->appendFormat("\n%*s", leftPadding + 11, "Occurrences");
-    // write histogram label line with bucket values
-    body->appendFormat("\n%*s", indent, " ");
-    body->appendFormat("%*s", leftPadding, " ");
-    for (auto const &x : buckets) {
-        body->appendFormat("%*d", colWidth, x.second);
-    }
-    // write histogram ascii art
-    body->appendFormat("\n%*s", indent, " ");
-    for (int row = height * scalingFactor; row >= 0; row -= scalingFactor) {
-        const int value = logScale ? (1 << row) : row;
-        body->appendFormat("%.*s", leftPadding, spaces.c_str());
-        for (auto const &x : buckets) {
-          body->appendFormat("%.*s%s", colWidth - 1, spaces.c_str(), x.second < value ? " " : "|");
-        }
-        body->appendFormat("\n%*s", indent, " ");
-    }
-    // print x-axis
-    const int columns = static_cast<int>(buckets.size());
-    body->appendFormat("%*c", leftPadding, ' ');
-    body->appendFormat("%.*s", (columns + 1) * colWidth, underscores.c_str());
-    body->appendFormat("\n%*s", indent, " ");
-
-    // write footer with bucket labels
-    body->appendFormat("%*s", leftPadding, " ");
-    for (auto const &x : buckets) {
-        body->appendFormat("%*d", colWidth, x.first);
-    }
-    body->appendFormat("%.*s%s", colWidth, spaces.c_str(), "ms\n");
-}
-
 NBLog::Merger::Merger(const void *shared, size_t size):
       mShared((Shared *) shared),
       mFifo(mShared != NULL ?
diff --git a/media/libnbaio/OWNERS b/media/libnbaio/OWNERS
new file mode 100644
index 0000000..f9cb567
--- /dev/null
+++ b/media/libnbaio/OWNERS
@@ -0,0 +1 @@
+gkasten@google.com
diff --git a/media/libnbaio/PerformanceAnalysis.cpp b/media/libnbaio/PerformanceAnalysis.cpp
new file mode 100644
index 0000000..fb3bddc
--- /dev/null
+++ b/media/libnbaio/PerformanceAnalysis.cpp
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#define LOG_TAG "PerformanceAnalysis"
+// #define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <climits>
+#include <deque>
+#include <iostream>
+#include <math.h>
+#include <numeric>
+#include <vector>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <time.h>
+#include <new>
+#include <audio_utils/roundup.h>
+#include <media/nbaio/NBLog.h>
+#include <media/nbaio/PerformanceAnalysis.h>
+#include <media/nbaio/ReportPerformance.h>
+// #include <utils/CallStack.h> // used to print callstack
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <queue>
+#include <utility>
+
+namespace android {
+
+namespace ReportPerformance {
+
+PerformanceAnalysis::PerformanceAnalysis() {
+    // These variables will be (FIXME) learned from the data
+    kPeriodMs = 4; // typical buffer period (mode)
+    // average number of Ms spent processing buffer
+    kPeriodMsCPU = static_cast<int>(kPeriodMs * kRatio);
+}
+
+// converts a time series into a map. key: buffer period length. value: count
+static std::map<int, int> buildBuckets(const std::vector<int64_t> &samples) {
+    // TODO allow buckets of variable resolution
+    std::map<int, int> buckets;
+    for (size_t i = 1; i < samples.size(); ++i) {
+        ++buckets[deltaMs(samples[i - 1], samples[i])];
+    }
+    return buckets;
+}
+
+static int widthOf(int x) {
+    int width = 0;
+    while (x > 0) {
+        ++width;
+        x /= 10;
+    }
+    return width;
+}
+
+// Given a series of audio processing wakeup timestamps,
+// buckets the time intervals into a histogram, searches for
+// outliers, analyzes the outlier series for unexpectedly
+// small or large values and stores these as peaks, and flushes
+// the timestamp series from memory.
+void PerformanceAnalysis::processAndFlushTimeStampSeries() {
+    // 1) analyze the series to store all outliers and their exact timestamps:
+    storeOutlierData(mTimeStampSeries);
+
+    // 2) detect peaks in the outlier series
+    detectPeaks();
+
+    // 3) compute its histogram, append to mRecentHists and clear the time series
+    mRecentHists.emplace_back(static_cast<timestamp>(mTimeStampSeries[0]),
+                              buildBuckets(mTimeStampSeries));
+    // do not let mRecentHists exceed capacity
+    // ALOGD("mRecentHists size: %d", static_cast<int>(mRecentHists.size()));
+    if (mRecentHists.size() >= kRecentHistsCapacity) {
+        //  ALOGD("popped back mRecentHists");
+        mRecentHists.pop_front();
+    }
+    mTimeStampSeries.clear();
+}
+
+// forces short-term histogram storage to avoid adding idle audio time interval
+// to buffer period data
+void PerformanceAnalysis::handleStateChange() {
+    ALOGD("handleStateChange");
+    processAndFlushTimeStampSeries();
+    return;
+}
+
+// Takes a single buffer period timestamp entry information and stores it in a
+// temporary series of timestamps. Once the series is full, the data is analyzed,
+// stored, and emptied.
+void PerformanceAnalysis::logTsEntry(int64_t ts) {
+    // TODO might want to filter excessively high outliers, which are usually caused
+    // by the thread being inactive.
+    // Store time series data for each reader in order to bucket it once there
+    // is enough data. Then, write to recentHists as a histogram.
+    mTimeStampSeries.push_back(ts);
+    // if length of the time series has reached kShortHistSize samples,
+    // analyze the data and flush the timestamp series from memory
+    if (mTimeStampSeries.size() >= kShortHistSize) {
+        processAndFlushTimeStampSeries();
+    }
+}
+
+// When the short-term histogram array mRecentHists has reached capacity,
+// merge histograms for data compression and store them in mLongTermHists
+// clears mRecentHists
+// TODO: have logTsEntry write directly to mLongTermHists, discard mRecentHists,
+// start a new histogram when a peak occurs
+void PerformanceAnalysis::processAndFlushRecentHists() {
+
+    // Buckets is used to aggregate short-term histograms.
+    Histogram buckets;
+    timestamp startingTs = mRecentHists[0].first;
+
+    for (const auto &shortHist: mRecentHists) {
+        // If the time between starting and ending timestamps has reached the maximum,
+        // add the current histogram (buckets) to the long-term histogram buffer,
+        // clear buckets, and start a new long-term histogram aggregation process.
+        if (deltaMs(startingTs, shortHist.first) >= kMaxHistTimespanMs) {
+            mLongTermHists.emplace_back(startingTs, std::move(buckets));
+            buckets.clear();
+            startingTs = shortHist.first;
+            // When memory is full, delete oldest histogram
+            // TODO use a circular buffer
+            if (mLongTermHists.size() >= kLongTermHistsCapacity) {
+                mLongTermHists.pop_front();
+            }
+        }
+
+        // add current histogram to buckets
+        for (const auto &countPair : shortHist.second) {
+            buckets[countPair.first] += countPair.second;
+        }
+    }
+    mRecentHists.clear();
+    // TODO: decide when/where to call writeToFile
+    // TODO: add a thread-specific extension to the file name
+    static const char* const kName = (const char *) "/data/misc/audioserver/sample_results.txt";
+    writeToFile(mOutlierData, mLongTermHists, kName, false);
+}
+
+// Given a series of outlier intervals (mOutlier data),
+// looks for changes in distribution (peaks), which can be either positive or negative.
+// The function sets the mean to the starting value and sigma to 0, and updates
+// them as long as no peak is detected. When a value is more than 'threshold'
+// standard deviations from the mean, a peak is detected and the mean and sigma
+// are set to the peak value and 0.
+void PerformanceAnalysis::detectPeaks() {
+    if (mOutlierData.empty()) {
+        return;
+    }
+
+    // compute mean of the distribution. Used to check whether a value is large
+    const double kTypicalDiff = std::accumulate(
+        mOutlierData.begin(), mOutlierData.end(), 0,
+        [](auto &a, auto &b){return a + b.first;}) / mOutlierData.size();
+    // ALOGD("typicalDiff %f", kTypicalDiff);
+
+    // iterator at the beginning of a sequence, or updated to the most recent peak
+    std::deque<std::pair<uint64_t, uint64_t>>::iterator start = mOutlierData.begin();
+    // the mean and standard deviation are updated every time a peak is detected
+    // initialize first time. The mean from the previous sequence is stored
+    // for the next sequence. Here, they are initialized for the first time.
+    if (mPeakDetectorMean < 0) {
+        mPeakDetectorMean = static_cast<double>(start->first);
+        mPeakDetectorSd = 0;
+    }
+    auto sqr = [](auto x){ return x * x; };
+    for (auto it = mOutlierData.begin(); it != mOutlierData.end(); ++it) {
+        // no surprise occurred:
+        // the new element is a small number of standard deviations from the mean
+        if ((fabs(it->first - mPeakDetectorMean) < kStddevThreshold * mPeakDetectorSd) ||
+             // or: right after peak has been detected, the delta is smaller than average
+            (mPeakDetectorSd == 0 && fabs(it->first - mPeakDetectorMean) < kTypicalDiff)) {
+            // update the mean and sd:
+            // count number of elements (distance between start interator and current)
+            const int kN = std::distance(start, it) + 1;
+            // usual formulas for mean and sd
+            mPeakDetectorMean = std::accumulate(start, it + 1, 0.0,
+                                   [](auto &a, auto &b){return a + b.first;}) / kN;
+            mPeakDetectorSd = sqrt(std::accumulate(start, it + 1, 0.0,
+                      [=](auto &a, auto &b){ return a + sqr(b.first - mPeakDetectorMean);})) /
+                      ((kN > 1)? kN - 1 : kN); // kN - 1: mean is correlated with variance
+        }
+        // surprising value: store peak timestamp and reset mean, sd, and start iterator
+        else {
+            mPeakTimestamps.emplace_back(it->second);
+            // TODO: remove pop_front once a circular buffer is in place
+            if (mPeakTimestamps.size() >= kPeakSeriesSize) {
+                mPeakTimestamps.pop_front();
+            }
+            mPeakDetectorMean = static_cast<double>(it->first);
+            mPeakDetectorSd = 0;
+            start = it;
+        }
+    }
+    return;
+}
+
+// Called by LogTsEntry. The input is a vector of timestamps.
+// Finds outliers and writes to mOutlierdata.
+// Each value in mOutlierdata consists of: <outlier timestamp, time elapsed since previous outlier>.
+// e.g. timestamps (ms) 1, 4, 5, 16, 18, 28 will produce pairs (4, 5), (13, 18).
+// This function is applied to the time series before it is converted into a histogram.
+void PerformanceAnalysis::storeOutlierData(const std::vector<int64_t> &timestamps) {
+    if (timestamps.size() < 1) {
+        return;
+    }
+    // first pass: need to initialize
+    if (mElapsed == 0) {
+        mPrevNs = timestamps[0];
+    }
+    for (const auto &ts: timestamps) {
+        const uint64_t diffMs = static_cast<uint64_t>(deltaMs(mPrevNs, ts));
+        if (diffMs >= static_cast<uint64_t>(kOutlierMs)) {
+            mOutlierData.emplace_back(mElapsed, static_cast<uint64_t>(mPrevNs));
+            // Remove oldest value if the vector is full
+            // TODO: remove pop_front once circular buffer is in place
+            // FIXME: make sure kShortHistSize is large enough that that data will never be lost
+            // before being written to file or to a FIFO
+            if (mOutlierData.size() >= kOutlierSeriesSize) {
+                mOutlierData.pop_front();
+            }
+            mElapsed = 0;
+        }
+        mElapsed += diffMs;
+        mPrevNs = ts;
+    }
+}
+
+
+// FIXME: delete this temporary test code, recycled for various new functions
+void PerformanceAnalysis::testFunction() {
+    // produces values (4: 5000000), (13: 18000000)
+    // ns timestamps of buffer periods
+    const std::vector<int64_t>kTempTestData = {1000000, 4000000, 5000000,
+                                               16000000, 18000000, 28000000};
+    PerformanceAnalysis::storeOutlierData(kTempTestData);
+    for (const auto &outlier: mOutlierData) {
+        ALOGE("PerformanceAnalysis test %lld: %lld",
+              static_cast<long long>(outlier.first), static_cast<long long>(outlier.second));
+    }
+    detectPeaks();
+}
+
+// TODO Make it return a std::string instead of modifying body --> is this still relevant?
+// TODO consider changing all ints to uint32_t or uint64_t
+// TODO: move this to ReportPerformance, probably make it a friend function of PerformanceAnalysis
+void PerformanceAnalysis::reportPerformance(String8 *body, int maxHeight) {
+    if (mRecentHists.size() < 1) {
+        ALOGD("reportPerformance: mRecentHists is empty");
+        return;
+    }
+    ALOGD("reportPerformance: hists size %d", static_cast<int>(mRecentHists.size()));
+    // TODO: more elaborate data analysis
+    std::map<int, int> buckets;
+    for (const auto &shortHist: mRecentHists) {
+        for (const auto &countPair : shortHist.second) {
+            buckets[countPair.first] += countPair.second;
+        }
+    }
+
+    // underscores and spaces length corresponds to maximum width of histogram
+    static const int kLen = 40;
+    std::string underscores(kLen, '_');
+    std::string spaces(kLen, ' ');
+
+    auto it = buckets.begin();
+    int maxDelta = it->first;
+    int maxCount = it->second;
+    // Compute maximum values
+    while (++it != buckets.end()) {
+        if (it->first > maxDelta) {
+            maxDelta = it->first;
+        }
+        if (it->second > maxCount) {
+            maxCount = it->second;
+        }
+    }
+    int height = log2(maxCount) + 1; // maxCount > 0, safe to call log2
+    const int leftPadding = widthOf(1 << height);
+    const int colWidth = std::max(std::max(widthOf(maxDelta) + 1, 3), leftPadding + 2);
+    int scalingFactor = 1;
+    // scale data if it exceeds maximum height
+    if (height > maxHeight) {
+        scalingFactor = (height + maxHeight) / maxHeight;
+        height /= scalingFactor;
+    }
+    body->appendFormat("\n%*s", leftPadding + 11, "Occurrences");
+    // write histogram label line with bucket values
+    body->appendFormat("\n%s", " ");
+    body->appendFormat("%*s", leftPadding, " ");
+    for (auto const &x : buckets) {
+        body->appendFormat("%*d", colWidth, x.second);
+    }
+    // write histogram ascii art
+    body->appendFormat("\n%s", " ");
+    for (int row = height * scalingFactor; row >= 0; row -= scalingFactor) {
+        const int value = 1 << row;
+        body->appendFormat("%.*s", leftPadding, spaces.c_str());
+        for (auto const &x : buckets) {
+          body->appendFormat("%.*s%s", colWidth - 1, spaces.c_str(), x.second < value ? " " : "|");
+        }
+        body->appendFormat("\n%s", " ");
+    }
+    // print x-axis
+    const int columns = static_cast<int>(buckets.size());
+    body->appendFormat("%*c", leftPadding, ' ');
+    body->appendFormat("%.*s", (columns + 1) * colWidth, underscores.c_str());
+    body->appendFormat("\n%s", " ");
+
+    // write footer with bucket labels
+    body->appendFormat("%*s", leftPadding, " ");
+    for (auto const &x : buckets) {
+        body->appendFormat("%*d", colWidth, x.first);
+    }
+    body->appendFormat("%.*s%s", colWidth, spaces.c_str(), "ms\n");
+
+    // Now report glitches
+    body->appendFormat("\ntime elapsed between glitches and glitch timestamps\n");
+    for (const auto &outlier: mOutlierData) {
+        body->appendFormat("%lld: %lld\n", static_cast<long long>(outlier.first),
+                           static_cast<long long>(outlier.second));
+    }
+
+}
+
+
+// Produces a log warning if the timing of recent buffer periods caused a glitch
+// Computes sum of running window of three buffer periods
+// Checks whether the buffer periods leave enough CPU time for the next one
+// e.g. if a buffer period is expected to be 4 ms and a buffer requires 3 ms of CPU time,
+// here are some glitch cases:
+// 4 + 4 + 6 ; 5 + 4 + 5; 2 + 2 + 10
+// TODO: develop this code to track changes in histogram distribution in addition
+// to / instead of glitches.
+void PerformanceAnalysis::alertIfGlitch(const std::vector<int64_t> &samples) {
+    std::deque<int> periods(kNumBuff, kPeriodMs);
+    for (size_t i = 2; i < samples.size(); ++i) { // skip first time entry
+        periods.push_front(deltaMs(samples[i - 1], samples[i]));
+        periods.pop_back();
+        // TODO: check that all glitch cases are covered
+        if (std::accumulate(periods.begin(), periods.end(), 0) > kNumBuff * kPeriodMs +
+            kPeriodMs - kPeriodMsCPU) {
+                ALOGW("A glitch occurred");
+                periods.assign(kNumBuff, kPeriodMs);
+        }
+    }
+    return;
+}
+
+} // namespace ReportPerformance
+
+}   // namespace android
diff --git a/media/libnbaio/ReportPerformance.cpp b/media/libnbaio/ReportPerformance.cpp
new file mode 100644
index 0000000..dc50ada
--- /dev/null
+++ b/media/libnbaio/ReportPerformance.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ReportPerformance"
+
+#include <fstream>
+#include <iostream>
+#include <queue>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <utility>
+#include <media/nbaio/NBLog.h>
+#include <media/nbaio/PerformanceAnalysis.h>
+#include <media/nbaio/ReportPerformance.h>
+// #include <utils/CallStack.h> // used to print callstack
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+namespace android {
+
+namespace ReportPerformance {
+
+// Writes outlier intervals, timestamps, and histograms spanning long time intervals to a file.
+// TODO: format the data efficiently and write different types of data to different files
+void writeToFile(std::deque<std::pair<outlierInterval, timestamp>> &outlierData,
+                                    std::deque<std::pair<timestamp, Histogram>> &hists,
+                                    const char * kName,
+                                    bool append) {
+    ALOGD("writing performance data to file");
+    if (outlierData.empty() || hists.empty()) {
+        return;
+    }
+
+    std::ofstream ofs;
+    ofs.open(kName, append ? std::ios::app : std::ios::trunc);
+    if (!ofs.is_open()) {
+        ALOGW("couldn't open file %s", kName);
+        return;
+    }
+    ofs << "Outlier data: interval and timestamp\n";
+    for (const auto &outlier : outlierData) {
+        ofs << outlier.first << ": " << outlier.second << "\n";
+    }
+    ofs << "Histogram data\n";
+    for (const auto &hist : hists) {
+        ofs << "\ttimestamp\n";
+        ofs << hist.first << "\n";
+        ofs << "\tbuckets and counts\n";
+        for (const auto &bucket : hist.second) {
+            ofs << bucket.first << ": " << bucket.second << "\n";
+        }
+    }
+    ofs.close();
+}
+
+} // namespace ReportPerformance
+
+}   // namespace android
diff --git a/media/libnbaio/include/AudioBufferProviderSource.h b/media/libnbaio/include/media/nbaio/AudioBufferProviderSource.h
similarity index 98%
rename from media/libnbaio/include/AudioBufferProviderSource.h
rename to media/libnbaio/include/media/nbaio/AudioBufferProviderSource.h
index 4747dcf..71182bb 100644
--- a/media/libnbaio/include/AudioBufferProviderSource.h
+++ b/media/libnbaio/include/media/nbaio/AudioBufferProviderSource.h
@@ -19,8 +19,8 @@
 #ifndef ANDROID_AUDIO_BUFFER_PROVIDER_SOURCE_H
 #define ANDROID_AUDIO_BUFFER_PROVIDER_SOURCE_H
 
-#include "NBAIO.h"
 #include <media/AudioBufferProvider.h>
+#include <media/nbaio/NBAIO.h>
 
 namespace android {
 
diff --git a/media/libnbaio/include/AudioStreamInSource.h b/media/libnbaio/include/media/nbaio/AudioStreamInSource.h
similarity index 98%
rename from media/libnbaio/include/AudioStreamInSource.h
rename to media/libnbaio/include/media/nbaio/AudioStreamInSource.h
index 508e0fe..8a3ffbe 100644
--- a/media/libnbaio/include/AudioStreamInSource.h
+++ b/media/libnbaio/include/media/nbaio/AudioStreamInSource.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_AUDIO_STREAM_IN_SOURCE_H
 #define ANDROID_AUDIO_STREAM_IN_SOURCE_H
 
-#include "NBAIO.h"
+#include <media/nbaio/NBAIO.h>
 
 namespace android {
 
diff --git a/media/libnbaio/include/AudioStreamOutSink.h b/media/libnbaio/include/media/nbaio/AudioStreamOutSink.h
similarity index 98%
rename from media/libnbaio/include/AudioStreamOutSink.h
rename to media/libnbaio/include/media/nbaio/AudioStreamOutSink.h
index 56a2a38..348b4f8 100644
--- a/media/libnbaio/include/AudioStreamOutSink.h
+++ b/media/libnbaio/include/media/nbaio/AudioStreamOutSink.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_AUDIO_STREAM_OUT_SINK_H
 #define ANDROID_AUDIO_STREAM_OUT_SINK_H
 
-#include "NBAIO.h"
+#include <media/nbaio/NBAIO.h>
 
 namespace android {
 
diff --git a/media/libnbaio/include/LibsndfileSink.h b/media/libnbaio/include/media/nbaio/LibsndfileSink.h
similarity index 97%
rename from media/libnbaio/include/LibsndfileSink.h
rename to media/libnbaio/include/media/nbaio/LibsndfileSink.h
index 97a57e0..535e3f5 100644
--- a/media/libnbaio/include/LibsndfileSink.h
+++ b/media/libnbaio/include/media/nbaio/LibsndfileSink.h
@@ -17,7 +17,8 @@
 #ifndef ANDROID_AUDIO_LIBSNDFILE_SINK_H
 #define ANDROID_AUDIO_LIBSNDFILE_SINK_H
 
-#include "NBAIO.h"
+#include <media/nbaio/NBAIO.h>
+
 #include "sndfile.h"
 
 // Implementation of NBAIO_Sink that wraps a libsndfile opened in SFM_WRITE mode
diff --git a/media/libnbaio/include/LibsndfileSource.h b/media/libnbaio/include/media/nbaio/LibsndfileSource.h
similarity index 97%
rename from media/libnbaio/include/LibsndfileSource.h
rename to media/libnbaio/include/media/nbaio/LibsndfileSource.h
index 4fbdb4b..bc6aa9d 100644
--- a/media/libnbaio/include/LibsndfileSource.h
+++ b/media/libnbaio/include/media/nbaio/LibsndfileSource.h
@@ -17,7 +17,8 @@
 #ifndef ANDROID_AUDIO_LIBSNDFILE_SOURCE_H
 #define ANDROID_AUDIO_LIBSNDFILE_SOURCE_H
 
-#include "NBAIO.h"
+#include <media/nbaio/NBAIO.h>
+
 #include "sndfile.h"
 
 // Implementation of NBAIO_Source that wraps a libsndfile opened in SFM_READ mode
diff --git a/media/libnbaio/include/NBLog.h b/media/libnbaio/include/media/nbaio/NBLog.h
similarity index 95%
rename from media/libnbaio/include/NBLog.h
rename to media/libnbaio/include/media/nbaio/NBLog.h
index 785b9c2..3e48ee1 100644
--- a/media/libnbaio/include/NBLog.h
+++ b/media/libnbaio/include/media/nbaio/NBLog.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -25,6 +25,7 @@
 #include <utils/threads.h>
 
 #include <map>
+#include <deque>
 #include <set>
 #include <vector>
 
@@ -43,8 +44,6 @@
 class Writer;
 class Reader;
 
-private:
-
 enum Event : uint8_t {
     EVENT_RESERVED,
     EVENT_STRING,               // ASCII string, not NUL-terminated
@@ -59,12 +58,13 @@
     EVENT_HASH,                 // unique HASH of log origin, originates from hash of file name
                                 // and line number
     EVENT_HISTOGRAM_ENTRY_TS,   // single datum for timestamp histogram
-    EVENT_HISTOGRAM_FLUSH,      // show histogram on log
+    EVENT_AUDIO_STATE,          // audio on/off event: logged upon FastMixer::onStateChange() call
     EVENT_END_FMT,              // end of logFormat argument list
 
     EVENT_UPPER_BOUND,          // to check for invalid events
 };
 
+private:
 
 // ---------------------------------------------------------------------------
 // API for handling format entry operations
@@ -248,6 +248,8 @@
     int author;
 }; //TODO __attribute__((packed));
 
+using StateTsEntryWithAuthor = HistTsEntryWithAuthor;
+
 struct HistIntEntry {
     log_hash_t hash;
     int value;
@@ -341,8 +343,7 @@
     virtual void    logStart(const char *fmt);
     virtual void    logEnd();
     virtual void    logHash(log_hash_t hash);
-    virtual void    logHistTS(log_hash_t hash);
-    virtual void    logHistFlush(log_hash_t hash);
+    virtual void    logEventHistTs(Event event, log_hash_t hash);
 
     virtual bool    isEnabled() const;
 
@@ -407,6 +408,7 @@
 public:
 
     // A snapshot of a readers buffer
+    // This is raw data. No analysis has been done on it
     class Snapshot {
     public:
         Snapshot() : mData(NULL), mLost(0) {}
@@ -443,20 +445,17 @@
 
     virtual ~Reader();
 
-    void alertIfGlitch(const std::vector<int64_t> &samples);
-
     // get snapshot of readers fifo buffer, effectively consuming the buffer
     std::unique_ptr<Snapshot> getSnapshot();
     // dump a particular snapshot of the reader
+    // TODO: move dump to PerformanceAnalysis. Model/view/controller design
     void     dump(int fd, size_t indent, Snapshot & snap);
     // dump the current content of the reader's buffer (call getSnapshot() and previous dump())
     void     dump(int fd, size_t indent = 0);
     bool     isIMemory(const sp<IMemory>& iMemory) const;
-    // if findGlitch is true, log warning when buffer periods caused glitch
-    void     setFindGlitch(bool s);
-    bool     isFindGlitch() const;
 
 private:
+
     static const std::set<Event> startingTypes;
     static const std::set<Event> endingTypes;
     /*const*/ Shared* const mShared;    // raw pointer to shared memory, actually const but not
@@ -469,10 +468,6 @@
     audio_utils_fifo_reader * const mFifoReader;    // used to read from FIFO,
                                                     // non-NULL unless constructor fails
 
-    // each pair contains a sequence of timestamps (one histogram's worth)
-    // pair's log_hash_t is the hash of the source code location where the timestamp was taken
-    // pair's int points to the Reader that originated the entry
-    std::map<std::pair<log_hash_t, int>, std::vector<int64_t>> mHists;
     // TODO: it might be clearer, instead of a direct map from source location to vector of
     // timestamps, if we instead first mapped from source location to an object that
     // represented that location. And one_of its fields would be a vector of timestamps.
@@ -485,17 +480,12 @@
     // dummy method for handling absent author entry
     virtual void handleAuthor(const AbstractEntry& /*fmtEntry*/, String8* /*body*/) {}
 
-    static void drawHistogram(String8 *body, const std::vector<int64_t> &samples,
-                              bool logScale, int indent = 0, int maxHeight = 10);
-
     // Searches for the last entry of type <type> in the range [front, back)
     // back has to be entry-aligned. Returns nullptr if none enconuntered.
     static const uint8_t *findLastEntryOfTypes(const uint8_t *front, const uint8_t *back,
                                          const std::set<Event> &types);
 
     static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
-
-    bool findGlitch; // alert if a local buffer period sequence caused an audio glitch
 };
 
 // Wrapper for a reader with a name. Contains a pointer to the reader and a pointer to the name
diff --git a/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h b/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h
new file mode 100644
index 0000000..b0dc148
--- /dev/null
+++ b/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+// Non-blocking event logger intended for safe communication between processes via shared memory
+
+#ifndef ANDROID_MEDIA_PERFORMANCEANALYSIS_H
+#define ANDROID_MEDIA_PERFORMANCEANALYSIS_H
+
+#include <map>
+#include <deque>
+#include <vector>
+#include "NBLog.h"
+#include "ReportPerformance.h"
+
+namespace android {
+
+namespace ReportPerformance {
+
+class PerformanceAnalysis {
+    // This class stores and analyzes audio processing wakeup timestamps from NBLog
+    // FIXME: currently, all performance data is stored in deques. Need to add a mutex.
+    // FIXME: continue this way until analysis is done in a separate thread. Then, use
+    // the fifo writer utilities.
+public:
+
+    PerformanceAnalysis();
+
+    // Given a series of audio processing wakeup timestamps,
+    // compresses and and analyzes the data, and flushes
+    // the timestamp series from memory.
+    void processAndFlushTimeStampSeries();
+
+    // Called when an audio on/off event is read from the buffer,
+    // e.g. EVENT_AUDIO_STATE.
+    // calls flushTimeStampSeries on the data up to the event,
+    // effectively discarding the idle audio time interval
+    void handleStateChange();
+
+    // When the short-term histogram array mRecentHists has reached capacity,
+    // merges histograms for data compression and stores them in mLongTermHists
+    void processAndFlushRecentHists();
+
+    // Writes wakeup timestamp entry to log and runs analysis
+    // TODO: make this thread safe. Each thread should have its own instance
+    // of PerformanceAnalysis.
+    void logTsEntry(timestamp_raw ts);
+
+    // FIXME: make peakdetector and storeOutlierData a single function
+    // Input: mOutlierData. Looks at time elapsed between outliers
+    // finds significant changes in the distribution
+    // writes timestamps of significant changes to mPeakTimestamps
+    void detectPeaks();
+
+    // runs analysis on timestamp series before it is converted to a histogram
+    // finds outliers
+    // writes to mOutlierData <time elapsed since previous outlier, outlier timestamp>
+    void storeOutlierData(const std::vector<timestamp_raw> &timestamps);
+
+    // input: series of short histograms. Generates a string of analysis of the buffer periods
+    // TODO: WIP write more detailed analysis
+    // FIXME: move this data visualization to a separate class. Model/view/controller
+    void reportPerformance(String8 *body, int maxHeight = 10);
+
+    // TODO: delete this. temp for testing
+    void testFunction();
+
+    // This function used to detect glitches in a time series
+    // TODO incorporate this into the analysis (currently unused)
+    void alertIfGlitch(const std::vector<timestamp_raw> &samples);
+
+private:
+
+    // stores outlier analysis: <elapsed time between outliers in ms, outlier timestamp>
+    std::deque<std::pair<outlierInterval, timestamp>> mOutlierData;
+
+    // stores each timestamp at which a peak was detected
+    // a peak is a moment at which the average outlier interval changed significantly
+    std::deque<timestamp> mPeakTimestamps;
+
+    // TODO: turn these into circular buffers for better data flow
+    // FIFO of small histograms
+    // stores fixed-size short buffer period histograms with timestamp of first sample
+    std::deque<std::pair<timestamp, Histogram>> mRecentHists;
+
+    // FIFO of small histograms
+    // stores fixed-size long-term buffer period histograms with timestamp of first sample
+    std::deque<std::pair<timestamp, Histogram>> mLongTermHists;
+
+    // vector of timestamps, collected from NBLog for a (TODO) specific thread
+    // when a vector reaches its maximum size, the data is processed and flushed
+    std::vector<timestamp_raw> mTimeStampSeries;
+
+    static const int kMsPerSec = 1000;
+
+    // Parameters used when detecting outliers
+    // TODO: learn some of these from the data, delete unused ones
+    // FIXME: decide whether to make kPeriodMs static.
+    static const int kNumBuff = 3; // number of buffers considered in local history
+    int kPeriodMs; // current period length is ideally 4 ms
+    static const int kOutlierMs = 7; // values greater or equal to this cause glitches
+    // DAC processing time for 4 ms buffer
+    static constexpr double kRatio = 0.75; // estimate of CPU time as ratio of period length
+    int kPeriodMsCPU; // compute based on kPeriodLen and kRatio
+
+    // Peak detection: number of standard deviations from mean considered a significant change
+    static const int kStddevThreshold = 5;
+
+    // capacity allocated to data structures
+    // TODO: adjust all of these values
+    static const int kRecentHistsCapacity = 100; // number of short-term histograms stored in memory
+    static const int kShortHistSize = 50; // number of samples in a short-term histogram
+    static const int kOutlierSeriesSize = 100; // number of values stored in outlier array
+    static const int kPeakSeriesSize = 100; // number of values stored in peak array
+    static const int kLongTermHistsCapacity = 20; // number of long-term histogram stored in memory
+    // maximum elapsed time between first and last timestamp of a long-term histogram
+    static const int kMaxHistTimespanMs = 5 * kMsPerSec;
+
+    // these variables are stored in-class to ensure continuity while analyzing the timestamp
+    // series one short sequence at a time: the variables are not re-initialized every time.
+    // FIXME: create inner class for these variables and decide which other ones to add to it
+    double mPeakDetectorMean = -1;
+    double mPeakDetectorSd = -1;
+    // variables for storeOutlierData
+    uint64_t mElapsed = 0;
+    int64_t mPrevNs = -1;
+
+};
+
+} // namespace ReportPerformance
+
+}   // namespace android
+
+#endif  // ANDROID_MEDIA_PERFORMANCEANALYSIS_H
diff --git a/media/libnbaio/include/Pipe.h b/media/libnbaio/include/media/nbaio/Pipe.h
similarity index 98%
rename from media/libnbaio/include/Pipe.h
rename to media/libnbaio/include/media/nbaio/Pipe.h
index 58b9750..0431976 100644
--- a/media/libnbaio/include/Pipe.h
+++ b/media/libnbaio/include/media/nbaio/Pipe.h
@@ -18,7 +18,7 @@
 #define ANDROID_AUDIO_PIPE_H
 
 #include <audio_utils/fifo.h>
-#include "NBAIO.h"
+#include <media/nbaio/NBAIO.h>
 
 namespace android {
 
diff --git a/media/libnbaio/include/PipeReader.h b/media/libnbaio/include/media/nbaio/PipeReader.h
similarity index 100%
rename from media/libnbaio/include/PipeReader.h
rename to media/libnbaio/include/media/nbaio/PipeReader.h
diff --git a/media/libnbaio/include/media/nbaio/ReportPerformance.h b/media/libnbaio/include/media/nbaio/ReportPerformance.h
new file mode 100644
index 0000000..27d2810
--- /dev/null
+++ b/media/libnbaio/include/media/nbaio/ReportPerformance.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_REPORTPERFORMANCE_H
+#define ANDROID_MEDIA_REPORTPERFORMANCE_H
+
+#include <deque>
+#include <map>
+#include <vector>
+
+namespace android {
+
+// This class is used by reportPerformance function
+// TODO move reportPerformance function to ReportPerformance.cpp
+class String8;
+
+namespace ReportPerformance {
+
+// stores a histogram: key: observed buffer period. value: count
+// TODO: unsigned, unsigned
+using Histogram = std::map<int, int>;
+
+using outlierInterval = uint64_t;
+// int64_t timestamps are converted to uint64_t in PerformanceAnalysis::storeOutlierData,
+// and all analysis functions use uint64_t.
+using timestamp = uint64_t;
+using timestamp_raw = int64_t;
+
+// FIXME: decide whether to use 64 or 32 bits
+// TODO: the code has a mix of typedef and using. Standardize to one or the other.
+typedef uint64_t log_hash_t;
+
+static inline int deltaMs(int64_t ns1, int64_t ns2) {
+    return (ns2 - ns1) / (1000 * 1000);
+}
+
+static inline uint32_t log2(uint32_t x) {
+    // This works for x > 0
+    return 31 - __builtin_clz(x);
+}
+
+// Writes outlier intervals, timestamps, and histograms spanning long time
+// intervals to a file.
+void writeToFile(std::deque<std::pair<outlierInterval, timestamp>> &outlierData,
+                 std::deque<std::pair<timestamp, Histogram>> &hists,
+                 const char * kName,
+                 bool append);
+
+} // namespace ReportPerformance
+
+}   // namespace android
+
+#endif  // ANDROID_MEDIA_REPORTPERFORMANCE_H
diff --git a/media/libnbaio/include/SourceAudioBufferProvider.h b/media/libnbaio/include/media/nbaio/SourceAudioBufferProvider.h
similarity index 98%
rename from media/libnbaio/include/SourceAudioBufferProvider.h
rename to media/libnbaio/include/media/nbaio/SourceAudioBufferProvider.h
index ae49903..cc2d019 100644
--- a/media/libnbaio/include/SourceAudioBufferProvider.h
+++ b/media/libnbaio/include/media/nbaio/SourceAudioBufferProvider.h
@@ -19,7 +19,7 @@
 #ifndef ANDROID_SOURCE_AUDIO_BUFFER_PROVIDER_H
 #define ANDROID_SOURCE_AUDIO_BUFFER_PROVIDER_H
 
-#include "NBAIO.h"
+#include <media/nbaio/NBAIO.h>
 #include <media/ExtendedAudioBufferProvider.h>
 
 namespace android {
diff --git a/media/libnbaio/include/MonoPipe.h b/media/libnbaio/include_mono/media/nbaio/MonoPipe.h
similarity index 98%
rename from media/libnbaio/include/MonoPipe.h
rename to media/libnbaio/include_mono/media/nbaio/MonoPipe.h
index 60ae92e..c51d0fe 100644
--- a/media/libnbaio/include/MonoPipe.h
+++ b/media/libnbaio/include_mono/media/nbaio/MonoPipe.h
@@ -20,7 +20,7 @@
 #include <time.h>
 #include <audio_utils/fifo.h>
 #include <media/SingleStateQueue.h>
-#include "NBAIO.h"
+#include <media/nbaio/NBAIO.h>
 
 namespace android {
 
diff --git a/media/libnbaio/include/MonoPipeReader.h b/media/libnbaio/include_mono/media/nbaio/MonoPipeReader.h
similarity index 100%
rename from media/libnbaio/include/MonoPipeReader.h
rename to media/libnbaio/include_mono/media/nbaio/MonoPipeReader.h
diff --git a/media/libnbaio/include/NBAIO.h b/media/libnbaio/include_mono/media/nbaio/NBAIO.h
similarity index 100%
rename from media/libnbaio/include/NBAIO.h
rename to media/libnbaio/include_mono/media/nbaio/NBAIO.h
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 6491ceb..c44e868 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -49,21 +49,18 @@
 
 #include <hidlmemory/mapping.h>
 
-#include <OMX_AudioExt.h>
-#include <OMX_VideoExt.h>
-#include <OMX_Component.h>
-#include <OMX_IndexExt.h>
-#include <OMX_AsString.h>
+#include <media/openmax/OMX_AudioExt.h>
+#include <media/openmax/OMX_VideoExt.h>
+#include <media/openmax/OMX_Component.h>
+#include <media/openmax/OMX_IndexExt.h>
+#include <media/openmax/OMX_AsString.h>
 
 #include "include/avc_utils.h"
 #include "include/ACodecBufferChannel.h"
 #include "include/DataConverter.h"
 #include "include/SecureBuffer.h"
 #include "include/SharedMemoryBuffer.h"
-#include "omx/OMXUtils.h"
-
-#include <android/hidl/allocator/1.0/IAllocator.h>
-#include <android/hidl/memory/1.0/IMemory.h>
+#include <media/stagefright/omx/OMXUtils.h>
 
 namespace android {
 
@@ -1866,16 +1863,15 @@
             mFlags |= kFlagIsGrallocUsageProtected;
             mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
         }
+    }
+    if (mFlags & kFlagIsSecure) {
+        // use native_handles for secure input buffers
+        err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer);
 
-        if (mFlags & kFlagIsSecure) {
-            // use native_handles for secure input buffers
-            err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer);
-
-            if (err != OK) {
-                ALOGI("falling back to non-native_handles");
-                setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
-                err = OK; // ignore error for now
-            }
+        if (err != OK) {
+            ALOGI("falling back to non-native_handles");
+            setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
+            err = OK; // ignore error for now
         }
     }
     if (haveNativeWindow) {
@@ -4174,11 +4170,12 @@
 // static
 int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
         int width, int height, int rate, int bitrate,
-        OMX_VIDEO_AVCPROFILETYPE profile) {
+        OMX_VIDEO_AVCPROFILEEXTTYPE profile) {
     // convert bitrate to main/baseline profile kbps equivalent
-    switch (profile) {
+    switch ((uint32_t)profile) {
         case OMX_VIDEO_AVCProfileHigh10:
             bitrate = divUp(bitrate, 3000); break;
+        case OMX_VIDEO_AVCProfileConstrainedHigh:
         case OMX_VIDEO_AVCProfileHigh:
             bitrate = divUp(bitrate, 1250); break;
         default:
@@ -4322,9 +4319,14 @@
         h264type.bUseHadamard = OMX_TRUE;
         h264type.nRefFrames = 2;
         h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
+
+        // disable B-frames until MPEG4Writer can guarantee finalizing files with B-frames
+        h264type.nRefFrames = 1;
+        h264type.nBFrames = 0;
+
         h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
         h264type.nAllowedPictureTypes =
-            OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB;
+            OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
         h264type.nRefIdx10ActiveMinus1 = 0;
         h264type.nRefIdx11ActiveMinus1 = 0;
         h264type.bEntropyCodingCABAC = OMX_TRUE;
@@ -6339,19 +6341,10 @@
 
     CHECK(mCodec->mOMXNode == NULL);
 
-    OMXClient client;
-    bool trebleFlag;
-    if (client.connect(&trebleFlag) != OK) {
-        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
-        return false;
-    }
-    mCodec->setTrebleFlag(trebleFlag);
-
-    sp<IOMX> omx = client.interface();
-
     sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
 
     Vector<AString> matchingCodecs;
+    Vector<AString> owners;
 
     AString mime;
 
@@ -6359,9 +6352,31 @@
     int32_t encoder = false;
     if (msg->findString("componentName", &componentName)) {
         sp<IMediaCodecList> list = MediaCodecList::getInstance();
-        if (list != NULL && list->findCodecByName(componentName.c_str()) >= 0) {
-            matchingCodecs.add(componentName);
+        if (list == nullptr) {
+            ALOGE("Unable to obtain MediaCodecList while "
+                    "attempting to create codec \"%s\"",
+                    componentName.c_str());
+            mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
+            return false;
         }
+        ssize_t index = list->findCodecByName(componentName.c_str());
+        if (index < 0) {
+            ALOGE("Unable to find codec \"%s\"",
+                    componentName.c_str());
+            mCodec->signalError(OMX_ErrorInvalidComponent, NAME_NOT_FOUND);
+            return false;
+        }
+        sp<MediaCodecInfo> info = list->getCodecInfo(index);
+        if (info == nullptr) {
+            ALOGE("Unexpected error (index out-of-bound) while "
+                    "retrieving information for codec \"%s\"",
+                    componentName.c_str());
+            mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
+            return false;
+        }
+        matchingCodecs.add(info->getCodecName());
+        owners.add(info->getOwnerName() == nullptr ?
+                "default" : info->getOwnerName());
     } else {
         CHECK(msg->findString("mime", &mime));
 
@@ -6373,10 +6388,12 @@
                 mime.c_str(),
                 encoder, // createEncoder
                 0,       // flags
-                &matchingCodecs);
+                &matchingCodecs,
+                &owners);
     }
 
     sp<CodecObserver> observer = new CodecObserver;
+    sp<IOMX> omx;
     sp<IOMXNode> omxNode;
 
     status_t err = NAME_NOT_FOUND;
@@ -6384,6 +6401,14 @@
             ++matchIndex) {
         componentName = matchingCodecs[matchIndex];
 
+        OMXClient client;
+        bool trebleFlag;
+        if (client.connect(owners[matchIndex].c_str(), &trebleFlag) != OK) {
+            mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
+            return false;
+        }
+        omx = client.interface();
+
         pid_t tid = gettid();
         int prevPriority = androidGetThreadPriority(tid);
         androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
@@ -6391,6 +6416,7 @@
         androidSetThreadPriority(tid, prevPriority);
 
         if (err == OK) {
+            mCodec->setTrebleFlag(trebleFlag);
             break;
         } else {
             ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
@@ -8214,16 +8240,15 @@
 }
 
 status_t ACodec::queryCapabilities(
-        const AString &name, const AString &mime, bool isEncoder,
-        sp<MediaCodecInfo::Capabilities> *caps) {
-    (*caps).clear();
-    const char *role = GetComponentRole(isEncoder, mime.c_str());
+        const char* owner, const char* name, const char* mime, bool isEncoder,
+        MediaCodecInfo::CapabilitiesWriter* caps) {
+    const char *role = GetComponentRole(isEncoder, mime);
     if (role == NULL) {
         return BAD_VALUE;
     }
 
     OMXClient client;
-    status_t err = client.connect();
+    status_t err = client.connect(owner);
     if (err != OK) {
         return err;
     }
@@ -8232,7 +8257,7 @@
     sp<CodecObserver> observer = new CodecObserver;
     sp<IOMXNode> omxNode;
 
-    err = omx->allocateNode(name.c_str(), observer, &omxNode);
+    err = omx->allocateNode(name, observer, &omxNode);
     if (err != OK) {
         client.disconnect();
         return err;
@@ -8245,8 +8270,7 @@
         return err;
     }
 
-    sp<MediaCodecInfo::CapabilitiesBuilder> builder = new MediaCodecInfo::CapabilitiesBuilder();
-    bool isVideo = mime.startsWithIgnoreCase("video/");
+    bool isVideo = strncasecmp(mime, "video/", 6) == 0;
 
     if (isVideo) {
         OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
@@ -8261,11 +8285,22 @@
             if (err != OK) {
                 break;
             }
-            builder->addProfileLevel(param.eProfile, param.eLevel);
+            caps->addProfileLevel(param.eProfile, param.eLevel);
+
+            // AVC components may not list the constrained profiles explicitly, but
+            // decoders that support a profile also support its constrained version.
+            // Encoders must explicitly support constrained profiles.
+            if (!isEncoder && strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
+                if (param.eProfile == OMX_VIDEO_AVCProfileHigh) {
+                    caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel);
+                } else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) {
+                    caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedBaseline, param.eLevel);
+                }
+            }
 
             if (index == kMaxIndicesToCheck) {
                 ALOGW("[%s] stopping checking profiles after %u: %x/%x",
-                        name.c_str(), index,
+                        name, index,
                         param.eProfile, param.eLevel);
             }
         }
@@ -8276,7 +8311,6 @@
         OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
         InitOMXParams(&portFormat);
         portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput;
-        Vector<uint32_t> supportedColors; // shadow copy to check for duplicates
         for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
             portFormat.nIndex = index;
             status_t err = omxNode->getParameter(
@@ -8290,28 +8324,17 @@
             if (IsFlexibleColorFormat(
                     omxNode, portFormat.eColorFormat, false /* usingNativeWindow */,
                     &flexibleEquivalent)) {
-                bool marked = false;
-                for (size_t i = 0; i < supportedColors.size(); ++i) {
-                    if (supportedColors[i] == flexibleEquivalent) {
-                        marked = true;
-                        break;
-                    }
-                }
-                if (!marked) {
-                    supportedColors.push(flexibleEquivalent);
-                    builder->addColorFormat(flexibleEquivalent);
-                }
+                caps->addColorFormat(flexibleEquivalent);
             }
-            supportedColors.push(portFormat.eColorFormat);
-            builder->addColorFormat(portFormat.eColorFormat);
+            caps->addColorFormat(portFormat.eColorFormat);
 
             if (index == kMaxIndicesToCheck) {
                 ALOGW("[%s] stopping checking formats after %u: %s(%x)",
-                        name.c_str(), index,
+                        name, index,
                         asString(portFormat.eColorFormat), portFormat.eColorFormat);
             }
         }
-    } else if (mime.equalsIgnoreCase(MEDIA_MIMETYPE_AUDIO_AAC)) {
+    } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
         // More audio codecs if they have profiles.
         OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param;
         InitOMXParams(&param);
@@ -8325,11 +8348,11 @@
                 break;
             }
             // For audio, level is ignored.
-            builder->addProfileLevel(param.eProfile, 0 /* level */);
+            caps->addProfileLevel(param.eProfile, 0 /* level */);
 
             if (index == kMaxIndicesToCheck) {
                 ALOGW("[%s] stopping checking profiles after %u: %x",
-                        name.c_str(), index,
+                        name, index,
                         param.eProfile);
             }
         }
@@ -8337,7 +8360,7 @@
         // NOTE: Without Android extensions, OMX does not provide a way to query
         // AAC profile support
         if (param.nProfileIndex == 0) {
-            ALOGW("component %s doesn't support profile query.", name.c_str());
+            ALOGW("component %s doesn't support profile query.", name);
         }
     }
 
@@ -8346,14 +8369,14 @@
         if (omxNode->configureVideoTunnelMode(
                 kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
             // tunneled playback includes adaptive playback
-            builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
+            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
                     | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
         } else if (omxNode->setPortMode(
                 kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
                 omxNode->prepareForAdaptivePlayback(
                 kPortIndexOutput, OMX_TRUE,
                 1280 /* width */, 720 /* height */) == OK) {
-            builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
+            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
         }
     }
 
@@ -8365,11 +8388,10 @@
         if (omxNode->getConfig(
                 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
                 &params, sizeof(params)) == OK) {
-            builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
+            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
         }
     }
 
-    *caps = builder;
     omxNode->freeNode();
     client.disconnect();
     return OK;
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 0d9696f..3c7ae3e 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -20,7 +20,7 @@
 
 #include <numeric>
 
-#include <android/media/IDescrambler.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
 #include <binder/MemoryDealer.h>
 #include <media/openmax/OMX_Core.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -34,8 +34,11 @@
 #include "include/SharedMemoryBuffer.h"
 
 namespace android {
-using binder::Status;
-using MediaDescrambler::DescrambleInfo;
+using hardware::hidl_handle;
+using hardware::hidl_string;
+using hardware::hidl_vec;
+using namespace hardware::cas::V1_0;
+using namespace hardware::cas::native::V1_0;
 using BufferInfo = ACodecBufferChannel::BufferInfo;
 using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
 
@@ -114,74 +117,97 @@
         return -ENOENT;
     }
 
-    ICrypto::DestinationBuffer destination;
+    native_handle_t *secureHandle = NULL;
     if (secure) {
         sp<SecureBuffer> secureData =
                 static_cast<SecureBuffer *>(it->mCodecBuffer.get());
-        destination.mType = secureData->getDestinationType();
-        if (destination.mType != ICrypto::kDestinationTypeNativeHandle) {
+        if (secureData->getDestinationType() != ICrypto::kDestinationTypeNativeHandle) {
             return BAD_VALUE;
         }
-        destination.mHandle =
-                static_cast<native_handle_t *>(secureData->getDestinationPointer());
-    } else {
-        destination.mType = ICrypto::kDestinationTypeSharedMemory;
-        destination.mSharedMemory = mDecryptDestination;
+        secureHandle = static_cast<native_handle_t *>(secureData->getDestinationPointer());
     }
-
-    ICrypto::SourceBuffer source;
-    source.mSharedMemory = it->mSharedEncryptedBuffer;
-    source.mHeapSeqNum = mHeapSeqNum;
-
     ssize_t result = -1;
     if (mCrypto != NULL) {
+        ICrypto::DestinationBuffer destination;
+        if (secure) {
+            destination.mType = ICrypto::kDestinationTypeNativeHandle;
+            destination.mHandle = secureHandle;
+        } else {
+            destination.mType = ICrypto::kDestinationTypeSharedMemory;
+            destination.mSharedMemory = mDecryptDestination;
+        }
+
+        ICrypto::SourceBuffer source;
+        source.mSharedMemory = it->mSharedEncryptedBuffer;
+        source.mHeapSeqNum = mHeapSeqNum;
+
         result = mCrypto->decrypt(key, iv, mode, pattern,
                 source, it->mClientBuffer->offset(),
                 subSamples, numSubSamples, destination, errorDetailMsg);
-    } else {
-        DescrambleInfo descrambleInfo;
-        descrambleInfo.dstType = destination.mType ==
-                ICrypto::kDestinationTypeSharedMemory ?
-                DescrambleInfo::kDestinationTypeVmPointer :
-                DescrambleInfo::kDestinationTypeNativeHandle;
-        descrambleInfo.scramblingControl = key != NULL ?
-                (DescramblerPlugin::ScramblingControl)key[0] :
-                DescramblerPlugin::kScrambling_Unscrambled;
-        descrambleInfo.numSubSamples = numSubSamples;
-        descrambleInfo.subSamples = (DescramblerPlugin::SubSample *)subSamples;
-        descrambleInfo.srcMem = it->mSharedEncryptedBuffer;
-        descrambleInfo.srcOffset = 0;
-        descrambleInfo.dstPtr = NULL;
-        descrambleInfo.dstOffset = 0;
-
-        int32_t descrambleResult = -1;
-        Status status = mDescrambler->descramble(descrambleInfo, &descrambleResult);
-
-        if (status.isOk()) {
-            result = descrambleResult;
-        }
 
         if (result < 0) {
-            ALOGE("descramble failed, exceptionCode=%d, err=%d, result=%zd",
-                    status.exceptionCode(), status.transactionError(), result);
-        } else {
-            ALOGV("descramble succeeded, result=%zd", result);
+            return result;
         }
 
-        if (result > 0 && destination.mType == ICrypto::kDestinationTypeSharedMemory) {
-            memcpy(destination.mSharedMemory->pointer(),
+        if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
+            memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
+        }
+    } else {
+        // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
+        // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
+        hidl_vec<SubSample> hidlSubSamples;
+        hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
+
+        ssize_t offset;
+        size_t size;
+        it->mSharedEncryptedBuffer->getMemory(&offset, &size);
+        hardware::cas::native::V1_0::SharedBuffer srcBuffer = {
+                .heapBase = mHidlMemory,
+                .offset = (uint64_t) offset,
+                .size = size
+        };
+
+        DestinationBuffer dstBuffer;
+        if (secure) {
+            dstBuffer.type = BufferType::NATIVE_HANDLE;
+            dstBuffer.secureMemory = hidl_handle(secureHandle);
+        } else {
+            dstBuffer.type = BufferType::SHARED_MEMORY;
+            dstBuffer.nonsecureMemory = srcBuffer;
+        }
+
+        Status status = Status::OK;
+        hidl_string detailedError;
+
+        auto returnVoid = mDescrambler->descramble(
+                key != NULL ? (ScramblingControl)key[0] : ScramblingControl::UNSCRAMBLED,
+                hidlSubSamples,
+                srcBuffer,
+                0,
+                dstBuffer,
+                0,
+                [&status, &result, &detailedError] (
+                        Status _status, uint32_t _bytesWritten,
+                        const hidl_string& _detailedError) {
+                    status = _status;
+                    result = (ssize_t)_bytesWritten;
+                    detailedError = _detailedError;
+                });
+
+        if (!returnVoid.isOk() || status != Status::OK || result < 0) {
+            ALOGE("descramble failed, trans=%s, status=%d, result=%zd",
+                    returnVoid.description().c_str(), status, result);
+            return UNKNOWN_ERROR;
+        }
+
+        ALOGV("descramble succeeded, %zd bytes", result);
+
+        if (dstBuffer.type == BufferType::SHARED_MEMORY) {
+            memcpy(it->mCodecBuffer->base(),
                     (uint8_t*)it->mSharedEncryptedBuffer->pointer(), result);
         }
     }
 
-    if (result < 0) {
-        return result;
-    }
-
-    if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
-        memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
-    }
-
     it->mCodecBuffer->setRange(0, result);
 
     // Copy metadata from client to codec buffer.
@@ -275,10 +301,21 @@
         int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
         if (seqNum >= 0) {
             mHeapSeqNum = seqNum;
-            ALOGD("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
+            ALOGV("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
         } else {
             mHeapSeqNum = -1;
-            ALOGD("setHeap failed, setting mHeapSeqNum=-1");
+            ALOGE("setHeap failed, setting mHeapSeqNum=-1");
+        }
+    } else if (mDescrambler != nullptr) {
+        sp<IMemoryHeap> heap = dealer->getMemoryHeap();
+        native_handle_t* nativeHandle = native_handle_create(1, 0);
+        if (nativeHandle != nullptr) {
+            int fd = heap->getHeapID();
+            nativeHandle->data[0] = fd;
+            mHidlMemory = hidl_memory("ashmem", hidl_handle(nativeHandle), heap->getSize());
+            ALOGV("created hidl_memory for descrambler");
+        } else {
+            ALOGE("failed to create hidl_memory for descrambler");
         }
     }
     return dealer;
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 81b4964..ac4e819 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -17,6 +17,7 @@
         "AudioPlayer.cpp",
         "AudioSource.cpp",
         "BufferImpl.cpp",
+        "CodecBase.cpp",
         "CallbackDataSource.cpp",
         "CameraSource.cpp",
         "CameraSourceTimeLapse.cpp",
@@ -29,6 +30,7 @@
         "FrameRenderTracker.cpp",
         "HTTPBase.cpp",
         "HevcUtils.cpp",
+        "ItemTable.cpp",
         "JPEGSource.cpp",
         "MP3Extractor.cpp",
         "MPEG2TSWriter.cpp",
@@ -49,6 +51,7 @@
         "NuCachedSource2.cpp",
         "NuMediaExtractor.cpp",
         "OMXClient.cpp",
+        "OmxInfoBuilder.cpp",
         "OggExtractor.cpp",
         "SampleIterator.cpp",
         "SampleTable.cpp",
@@ -67,11 +70,6 @@
         "avc_utils.cpp",
     ],
 
-    include_dirs: [
-        "frameworks/native/include/media/openmax",
-        "frameworks/native/include/media/hardware",
-    ],
-
     shared_libs: [
         "libaudioutils",
         "libbinder",
@@ -93,15 +91,22 @@
         "libutils",
         "libvorbisidec",
         "libmediadrm",
+        "libnativewindow",
 
         "libmedia_helper",
+        "libstagefright_omx_utils",
         "libstagefright_flacdec",
         "libstagefright_foundation",
+        "libstagefright_xmlparser",
         "libdl",
         "libRScpp",
         "libhidlbase",
         "libhidlmemory",
         "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "android.hidl.token@1.0-utils",
+        "android.hardware.cas@1.0",
+        "android.hardware.cas.native@1.0",
         "android.hardware.media.omx@1.0",
     ],
 
@@ -110,7 +115,6 @@
         "libyuv_static",
         "libstagefright_matroska",
         "libstagefright_mediafilter",
-        "libstagefright_omx_utils",
         "libstagefright_webm",
         "libstagefright_timedtext",
         "libvpx",
@@ -120,9 +124,12 @@
         "libFLAC",
     ],
 
-    export_shared_lib_headers: ["libmedia"],
+    export_shared_lib_headers: [
+        "libmedia",
+        "android.hidl.allocator@1.0",
+    ],
+
     export_include_dirs: [
-        ".",
         "include",
     ],
 
@@ -169,4 +176,5 @@
     "timedtext",
     "webm",
     "wifi-display",
+    "xmlparser",
 ]
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index 4309372..6dfe2de 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -127,10 +127,6 @@
 }
 
 ssize_t TinyCacheSource::readAt(off64_t offset, void* data, size_t size) {
-    if (size >= kCacheSize) {
-        return mSource->readAt(offset, data, size);
-    }
-
     // Check if the cache satisfies the read.
     if (mCachedOffset <= offset
             && offset < (off64_t) (mCachedOffset + mCachedSize)) {
@@ -154,6 +150,9 @@
         }
     }
 
+    if (size >= kCacheSize) {
+        return mSource->readAt(offset, data, size);
+    }
 
     // Fill the cache and copy to the caller.
     const ssize_t numRead = mSource->readAt(offset, mCache, kCacheSize);
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
new file mode 100644
index 0000000..d0610b2
--- /dev/null
+++ b/media/libstagefright/CodecBase.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CodecBase"
+
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <media/ICrypto.h>
+#include <media/stagefright/CodecBase.h>
+#include <utils/Log.h>
+
+namespace android {
+
+void BufferChannelBase::setCrypto(const sp<ICrypto> &crypto) {
+    mCrypto = crypto;
+}
+
+void BufferChannelBase::setDescrambler(const sp<IDescrambler> &descrambler) {
+    mDescrambler = descrambler;
+}
+
+} // namespace android
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index a5760d1..c22053e 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -92,6 +92,48 @@
     return true;
 }
 
+bool DataSource::getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
+    if (size == 2) {
+        return getUInt16(offset, x);
+    }
+    if (size == 1) {
+        uint8_t tmp;
+        if (readAt(offset, &tmp, 1) == 1) {
+            *x = tmp;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool DataSource::getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
+    if (size == 4) {
+        return getUInt32(offset, x);
+    }
+    if (size == 2) {
+        uint16_t tmp;
+        if (getUInt16(offset, &tmp)) {
+            *x = tmp;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool DataSource::getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
+    if (size == 8) {
+        return getUInt64(offset, x);
+    }
+    if (size == 4) {
+        uint32_t tmp;
+        if (getUInt32(offset, &tmp)) {
+            *x = tmp;
+            return true;
+        }
+    }
+    return false;
+}
+
 status_t DataSource::getSize(off64_t *size) {
     *size = 0;
 
diff --git a/media/libstagefright/FrameRenderTracker.cpp b/media/libstagefright/FrameRenderTracker.cpp
index 917870f..1aa3bad 100644
--- a/media/libstagefright/FrameRenderTracker.cpp
+++ b/media/libstagefright/FrameRenderTracker.cpp
@@ -88,7 +88,9 @@
 
 status_t FrameRenderTracker::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
     // ensure monotonic timestamps
-    if (mLastRenderTimeNs >= systemNano) {
+    if (mLastRenderTimeNs > systemNano ||
+        // EOS is normally marked on the last frame
+        (mLastRenderTimeNs == systemNano && mediaTimeUs != INT64_MAX)) {
         ALOGW("[%s] Ignoring out of order/stale system nano %lld for media time %lld from codec.",
                 mComponentName.c_str(), (long long)systemNano, (long long)mediaTimeUs);
         return BAD_VALUE;
diff --git a/media/libstagefright/ItemTable.cpp b/media/libstagefright/ItemTable.cpp
new file mode 100644
index 0000000..7bc4f3c
--- /dev/null
+++ b/media/libstagefright/ItemTable.cpp
@@ -0,0 +1,1560 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ItemTable"
+
+#include <include/ItemTable.h>
+#include <media/MediaDefs.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <utils/Log.h>
+
+namespace android {
+
+namespace heif {
+
+/////////////////////////////////////////////////////////////////////
+//
+//  struct to keep track of one image item
+//
+
+struct ImageItem {
+    friend struct ItemReference;
+    friend struct ItemProperty;
+
+    ImageItem() : ImageItem(0) {}
+    ImageItem(uint32_t _type) : type(_type),
+            rows(0), columns(0), width(0), height(0), rotation(0),
+            offset(0), size(0), nextTileIndex(0) {}
+
+    bool isGrid() const {
+        return type == FOURCC('g', 'r', 'i', 'd');
+    }
+
+    status_t getNextTileItemId(uint32_t *nextTileItemId, bool reset) {
+        if (reset) {
+            nextTileIndex = 0;
+        }
+        if (nextTileIndex >= dimgRefs.size()) {
+            return ERROR_END_OF_STREAM;
+        }
+        *nextTileItemId = dimgRefs[nextTileIndex++];
+        return OK;
+    }
+
+    uint32_t type;
+    int32_t rows;
+    int32_t columns;
+    int32_t width;
+    int32_t height;
+    int32_t rotation;
+    off64_t offset;
+    size_t size;
+    sp<ABuffer> hvcc;
+    sp<ABuffer> icc;
+
+    Vector<uint32_t> thumbnails;
+    Vector<uint32_t> dimgRefs;
+    size_t nextTileIndex;
+};
+
+
+/////////////////////////////////////////////////////////////////////
+//
+//  ISO boxes
+//
+
+struct Box {
+protected:
+    Box(const sp<DataSource> source, uint32_t type) :
+        mDataSource(source), mType(type) {}
+
+    virtual ~Box() {}
+
+    virtual status_t onChunkData(
+            uint32_t /*type*/, off64_t /*offset*/, size_t /*size*/) {
+        return OK;
+    }
+
+    inline uint32_t type() const { return mType; }
+
+    inline sp<DataSource> source() const { return mDataSource; }
+
+    status_t parseChunk(off64_t *offset);
+
+    status_t parseChunks(off64_t offset, size_t size);
+
+private:
+    sp<DataSource> mDataSource;
+    uint32_t mType;
+};
+
+status_t Box::parseChunk(off64_t *offset) {
+    if (*offset < 0) {
+        ALOGE("b/23540914");
+        return ERROR_MALFORMED;
+    }
+    uint32_t hdr[2];
+    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
+        return ERROR_IO;
+    }
+    uint64_t chunk_size = ntohl(hdr[0]);
+    int32_t chunk_type = ntohl(hdr[1]);
+    off64_t data_offset = *offset + 8;
+
+    if (chunk_size == 1) {
+        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
+            return ERROR_IO;
+        }
+        chunk_size = ntoh64(chunk_size);
+        data_offset += 8;
+
+        if (chunk_size < 16) {
+            // The smallest valid chunk is 16 bytes long in this case.
+            return ERROR_MALFORMED;
+        }
+    } else if (chunk_size == 0) {
+        // This shouldn't happen since we should never be top level
+        ALOGE("invalid chunk size 0 for non-top level box");
+        return ERROR_MALFORMED;
+    } else if (chunk_size < 8) {
+        // The smallest valid chunk is 8 bytes long.
+        ALOGE("invalid chunk size: %lld", (long long)chunk_size);
+        return ERROR_MALFORMED;
+    }
+
+    char chunk[5];
+    MakeFourCCString(chunk_type, chunk);
+    ALOGV("chunk: %s @ %lld", chunk, (long long)*offset);
+
+    off64_t chunk_data_size = chunk_size - (data_offset - *offset);
+    if (chunk_data_size < 0) {
+        ALOGE("b/23540914");
+        return ERROR_MALFORMED;
+    }
+
+    status_t err = onChunkData(chunk_type, data_offset, chunk_data_size);
+
+    if (err != OK) {
+        return err;
+    }
+    *offset += chunk_size;
+    return OK;
+}
+
+status_t Box::parseChunks(off64_t offset, size_t size) {
+    off64_t stopOffset = offset + size;
+    while (offset < stopOffset) {
+        status_t err = parseChunk(&offset);
+        if (err != OK) {
+            return err;
+        }
+    }
+    if (offset != stopOffset) {
+        return ERROR_MALFORMED;
+    }
+    return OK;
+}
+
+///////////////////////////////////////////////////////////////////////
+
+struct FullBox : public Box {
+protected:
+    FullBox(const sp<DataSource> source, uint32_t type) :
+        Box(source, type), mVersion(0), mFlags(0) {}
+
+    inline uint8_t version() const { return mVersion; }
+
+    inline uint32_t flags() const { return mFlags; }
+
+    status_t parseFullBoxHeader(off64_t *offset, size_t *size);
+
+private:
+    uint8_t mVersion;
+    uint32_t mFlags;
+};
+
+status_t FullBox::parseFullBoxHeader(off64_t *offset, size_t *size) {
+    if (*size < 4) {
+        return ERROR_MALFORMED;
+    }
+    if (!source()->readAt(*offset, &mVersion, 1)) {
+        return ERROR_IO;
+    }
+    if (!source()->getUInt24(*offset + 1, &mFlags)) {
+        return ERROR_IO;
+    }
+    *offset += 4;
+    *size -= 4;
+    return OK;
+}
+
+/////////////////////////////////////////////////////////////////////
+//
+//  PrimaryImage box
+//
+
+struct PitmBox : public FullBox {
+    PitmBox(const sp<DataSource> source) :
+        FullBox(source, FOURCC('p', 'i', 't', 'm')) {}
+
+    status_t parse(off64_t offset, size_t size, uint32_t *primaryItemId);
+};
+
+status_t PitmBox::parse(off64_t offset, size_t size, uint32_t *primaryItemId) {
+    status_t err = parseFullBoxHeader(&offset, &size);
+    if (err != OK) {
+        return err;
+    }
+
+    size_t itemIdSize = (version() == 0) ? 2 : 4;
+    if (size < itemIdSize) {
+        return ERROR_MALFORMED;
+    }
+    uint32_t itemId;
+    if (!source()->getUInt32Var(offset, &itemId, itemIdSize)) {
+        return ERROR_IO;
+    }
+
+    ALOGV("primary id %d", itemId);
+    *primaryItemId = itemId;
+
+    return OK;
+}
+
+/////////////////////////////////////////////////////////////////////
+//
+//  ItemLocation related boxes
+//
+
+struct ExtentEntry {
+    uint64_t extentIndex;
+    uint64_t extentOffset;
+    uint64_t extentLength;
+};
+
+struct ItemLoc {
+    ItemLoc() : ItemLoc(0, 0, 0, 0) {}
+    ItemLoc(uint32_t item_id, uint16_t construction_method,
+            uint16_t data_reference_index, uint64_t base_offset) :
+        itemId(item_id),
+        constructionMethod(construction_method),
+        dataReferenceIndex(data_reference_index),
+        baseOffset(base_offset) {}
+
+    void addExtent(const ExtentEntry& extent) {
+        extents.push_back(extent);
+    }
+
+    status_t getLoc(off64_t *offset, size_t *size,
+            off64_t idatOffset, size_t idatSize) const {
+        // TODO: fix extent handling, fix constructionMethod = 2
+        CHECK(extents.size() == 1);
+        if (constructionMethod == 0) {
+            *offset = baseOffset + extents[0].extentOffset;
+            *size = extents[0].extentLength;
+            return OK;
+        } else if (constructionMethod == 1) {
+            if (baseOffset + extents[0].extentOffset + extents[0].extentLength
+                    > idatSize) {
+                return ERROR_MALFORMED;
+            }
+            *offset = baseOffset + extents[0].extentOffset + idatOffset;
+            *size = extents[0].extentLength;
+            return OK;
+        }
+        return ERROR_UNSUPPORTED;
+    }
+
+    // parsed info
+    uint32_t itemId;
+    uint16_t constructionMethod;
+    uint16_t dataReferenceIndex;
+    off64_t baseOffset;
+    Vector<ExtentEntry> extents;
+};
+
+struct IlocBox : public FullBox {
+    IlocBox(const sp<DataSource> source, KeyedVector<uint32_t, ItemLoc> *itemLocs) :
+        FullBox(source, FOURCC('i', 'l', 'o', 'c')),
+        mItemLocs(itemLocs), mHasConstructMethod1(false) {}
+
+    status_t parse(off64_t offset, size_t size);
+
+    bool hasConstructMethod1() { return mHasConstructMethod1; }
+
+private:
+    static bool isSizeFieldValid(uint32_t offset_size) {
+        return offset_size == 0 || offset_size == 4 || offset_size == 8;
+    }
+    KeyedVector<uint32_t, ItemLoc> *mItemLocs;
+    bool mHasConstructMethod1;
+};
+
+status_t IlocBox::parse(off64_t offset, size_t size) {
+    status_t err = parseFullBoxHeader(&offset, &size);
+    if (err != OK) {
+        return err;
+    }
+    if (version() > 2) {
+        ALOGE("%s: invalid version %d", __FUNCTION__, version());
+        return ERROR_MALFORMED;
+    }
+
+    if (size < 2) {
+        return ERROR_MALFORMED;
+    }
+    uint8_t offset_size;
+    if (!source()->readAt(offset++, &offset_size, 1)) {
+        return ERROR_IO;
+    }
+    uint8_t length_size = (offset_size & 0xF);
+    offset_size >>= 4;
+
+    uint8_t base_offset_size;
+    if (!source()->readAt(offset++, &base_offset_size, 1)) {
+        return ERROR_IO;
+    }
+    uint8_t index_size = 0;
+    if (version() == 1 || version() == 2) {
+        index_size = (base_offset_size & 0xF);
+    }
+    base_offset_size >>= 4;
+    size -= 2;
+
+    if (!isSizeFieldValid(offset_size)
+            || !isSizeFieldValid(length_size)
+            || !isSizeFieldValid(base_offset_size)
+            || !isSizeFieldValid((index_size))) {
+        ALOGE("%s: offset size not valid: %d, %d, %d, %d", __FUNCTION__,
+                offset_size, length_size, base_offset_size, index_size);
+        return ERROR_MALFORMED;
+    }
+
+    uint32_t item_count;
+    size_t itemFieldSize = version() < 2 ? 2 : 4;
+    if (size < itemFieldSize) {
+        return ERROR_MALFORMED;
+    }
+    if (!source()->getUInt32Var(offset, &item_count, itemFieldSize)) {
+        return ERROR_IO;
+    }
+
+    ALOGV("item_count %lld", (long long) item_count);
+    offset += itemFieldSize;
+    size -= itemFieldSize;
+
+    for (size_t i = 0; i < item_count; i++) {
+        uint32_t item_id;
+        if (!source()->getUInt32Var(offset, &item_id, itemFieldSize)) {
+            return ERROR_IO;
+        }
+        ALOGV("item[%zu]: id %lld", i, (long long)item_id);
+        offset += itemFieldSize;
+
+        uint8_t construction_method = 0;
+        if (version() == 1 || version() == 2) {
+            uint8_t buf[2];
+            if (!source()->readAt(offset, buf, 2)) {
+                return ERROR_IO;
+            }
+            construction_method = (buf[1] & 0xF);
+            ALOGV("construction_method %d", construction_method);
+            if (construction_method == 1) {
+                mHasConstructMethod1 = true;
+            }
+
+            offset += 2;
+        }
+
+        uint16_t data_reference_index;
+        if (!source()->getUInt16(offset, &data_reference_index)) {
+            return ERROR_IO;
+        }
+        ALOGV("data_reference_index %d", data_reference_index);
+        if (data_reference_index != 0) {
+            // we don't support reference to other files
+            return ERROR_UNSUPPORTED;
+        }
+        offset += 2;
+
+        uint64_t base_offset = 0;
+        if (base_offset_size != 0) {
+            if (!source()->getUInt64Var(offset, &base_offset, base_offset_size)) {
+                return ERROR_IO;
+            }
+            offset += base_offset_size;
+        }
+        ALOGV("base_offset %lld", (long long) base_offset);
+
+        ssize_t index = mItemLocs->add(item_id, ItemLoc(
+                item_id, construction_method, data_reference_index, base_offset));
+        ItemLoc &item = mItemLocs->editValueAt(index);
+
+        uint16_t extent_count;
+        if (!source()->getUInt16(offset, &extent_count)) {
+            return ERROR_IO;
+        }
+        ALOGV("extent_count %d", extent_count);
+
+        if (extent_count > 1 && (offset_size == 0 || length_size == 0)) {
+            // if the item is dividec into more than one extents, offset and
+            // length must be present.
+            return ERROR_MALFORMED;
+        }
+        offset += 2;
+
+        for (size_t j = 0; j < extent_count; j++) {
+            uint64_t extent_index = 1; // default=1
+            if ((version() == 1 || version() == 2) && (index_size > 0)) {
+                if (!source()->getUInt64Var(offset, &extent_index, index_size)) {
+                    return ERROR_IO;
+                }
+                // TODO: add support for this mode
+                offset += index_size;
+                ALOGV("extent_index %lld", (long long)extent_index);
+            }
+
+            uint64_t extent_offset = 0; // default=0
+            if (offset_size > 0) {
+                if (!source()->getUInt64Var(offset, &extent_offset, offset_size)) {
+                    return ERROR_IO;
+                }
+                offset += offset_size;
+            }
+            ALOGV("extent_offset %lld", (long long)extent_offset);
+
+            uint64_t extent_length = 0; // this indicates full length of file
+            if (length_size > 0) {
+                if (!source()->getUInt64Var(offset, &extent_length, length_size)) {
+                    return ERROR_IO;
+                }
+                offset += length_size;
+            }
+            ALOGV("extent_length %lld", (long long)extent_length);
+
+            item.addExtent({ extent_index, extent_offset, extent_length });
+        }
+    }
+    return OK;
+}
+
+/////////////////////////////////////////////////////////////////////
+//
+//  ItemReference related boxes
+//
+
+struct ItemReference : public Box, public RefBase {
+    ItemReference(const sp<DataSource> source, uint32_t type, uint32_t itemIdSize) :
+        Box(source, type), mItemId(0), mRefIdSize(itemIdSize) {}
+
+    status_t parse(off64_t offset, size_t size);
+
+    uint32_t itemId() { return mItemId; }
+
+    void apply(KeyedVector<uint32_t, ImageItem> &itemIdToImageMap) const {
+        ssize_t imageIndex = itemIdToImageMap.indexOfKey(mItemId);
+
+        // ignore non-image items
+        if (imageIndex < 0) {
+            return;
+        }
+
+        ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId);
+
+        if (type() == FOURCC('d', 'i', 'm', 'g')) {
+            ImageItem &image = itemIdToImageMap.editValueAt(imageIndex);
+            if (!image.dimgRefs.empty()) {
+                ALOGW("dimgRefs if not clean!");
+            }
+            image.dimgRefs.appendVector(mRefs);
+        } else if (type() == FOURCC('t', 'h', 'm', 'b')) {
+            for (size_t i = 0; i < mRefs.size(); i++) {
+                imageIndex = itemIdToImageMap.indexOfKey(mRefs[i]);
+
+                // ignore non-image items
+                if (imageIndex < 0) {
+                    continue;
+                }
+                ALOGV("Image item id %d uses thumbnail item id %d", mRefs[i], mItemId);
+                ImageItem &image = itemIdToImageMap.editValueAt(imageIndex);
+                if (!image.thumbnails.empty()) {
+                    ALOGW("already has thumbnails!");
+                }
+                image.thumbnails.push_back(mItemId);
+            }
+        } else {
+            ALOGW("ignoring unsupported ref type 0x%x", type());
+        }
+    }
+
+private:
+    uint32_t mItemId;
+    uint32_t mRefIdSize;
+    Vector<uint32_t> mRefs;
+
+    DISALLOW_EVIL_CONSTRUCTORS(ItemReference);
+};
+
+status_t ItemReference::parse(off64_t offset, size_t size) {
+    if (size < mRefIdSize + 2) {
+        return ERROR_MALFORMED;
+    }
+    if (!source()->getUInt32Var(offset, &mItemId, mRefIdSize)) {
+        return ERROR_IO;
+    }
+    offset += mRefIdSize;
+
+    uint16_t count;
+    if (!source()->getUInt16(offset, &count)) {
+        return ERROR_IO;
+    }
+    offset += 2;
+    size -= (mRefIdSize + 2);
+
+    if (size < count * mRefIdSize) {
+        return ERROR_MALFORMED;
+    }
+
+    for (size_t i = 0; i < count; i++) {
+        uint32_t refItemId;
+        if (!source()->getUInt32Var(offset, &refItemId, mRefIdSize)) {
+            return ERROR_IO;
+        }
+        offset += mRefIdSize;
+        mRefs.push_back(refItemId);
+        ALOGV("item id %d: referencing item id %d", mItemId, refItemId);
+    }
+
+    return OK;
+}
+
+struct IrefBox : public FullBox {
+    IrefBox(const sp<DataSource> source, Vector<sp<ItemReference> > *itemRefs) :
+        FullBox(source, FOURCC('i', 'r', 'e', 'f')), mRefIdSize(0), mItemRefs(itemRefs) {}
+
+    status_t parse(off64_t offset, size_t size);
+
+protected:
+    status_t onChunkData(uint32_t type, off64_t offset, size_t size) override;
+
+private:
+    uint32_t mRefIdSize;
+    Vector<sp<ItemReference> > *mItemRefs;
+};
+
+status_t IrefBox::parse(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+    status_t err = parseFullBoxHeader(&offset, &size);
+    if (err != OK) {
+        return err;
+    }
+
+    mRefIdSize = (version() == 0) ? 2 : 4;
+    return parseChunks(offset, size);
+}
+
+status_t IrefBox::onChunkData(uint32_t type, off64_t offset, size_t size) {
+    sp<ItemReference> itemRef = new ItemReference(source(), type, mRefIdSize);
+
+    status_t err = itemRef->parse(offset, size);
+    if (err != OK) {
+        return err;
+    }
+    mItemRefs->push_back(itemRef);
+    return OK;
+}
+
+/////////////////////////////////////////////////////////////////////
+//
+//  ItemProperty related boxes
+//
+
+struct AssociationEntry {
+    uint32_t itemId;
+    bool essential;
+    uint16_t index;
+};
+
+struct ItemProperty : public RefBase {
+    ItemProperty() {}
+
+    virtual void attachTo(ImageItem &/*image*/) const {
+        ALOGW("Unrecognized property");
+    }
+    virtual status_t parse(off64_t /*offset*/, size_t /*size*/) {
+        ALOGW("Unrecognized property");
+        return OK;
+    }
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(ItemProperty);
+};
+
+struct IspeBox : public FullBox, public ItemProperty {
+    IspeBox(const sp<DataSource> source) :
+        FullBox(source, FOURCC('i', 's', 'p', 'e')), mWidth(0), mHeight(0) {}
+
+    status_t parse(off64_t offset, size_t size) override;
+
+    void attachTo(ImageItem &image) const override {
+        image.width = mWidth;
+        image.height = mHeight;
+    }
+
+private:
+    uint32_t mWidth;
+    uint32_t mHeight;
+};
+
+status_t IspeBox::parse(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    status_t err = parseFullBoxHeader(&offset, &size);
+    if (err != OK) {
+        return err;
+    }
+
+    if (size < 8) {
+        return ERROR_MALFORMED;
+    }
+    if (!source()->getUInt32(offset, &mWidth)
+            || !source()->getUInt32(offset + 4, &mHeight)) {
+        return ERROR_IO;
+    }
+    ALOGV("property ispe: %dx%d", mWidth, mHeight);
+
+    return OK;
+}
+
+struct HvccBox : public Box, public ItemProperty {
+    HvccBox(const sp<DataSource> source) :
+        Box(source, FOURCC('h', 'v', 'c', 'C')) {}
+
+    status_t parse(off64_t offset, size_t size) override;
+
+    void attachTo(ImageItem &image) const override {
+        image.hvcc = mHVCC;
+    }
+
+private:
+    sp<ABuffer> mHVCC;
+};
+
+status_t HvccBox::parse(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    mHVCC = new ABuffer(size);
+
+    if (mHVCC->data() == NULL) {
+        ALOGE("b/28471206");
+        return NO_MEMORY;
+    }
+
+    if (source()->readAt(offset, mHVCC->data(), size) < (ssize_t)size) {
+        return ERROR_IO;
+    }
+
+    ALOGV("property hvcC");
+
+    return OK;
+}
+
+struct IrotBox : public Box, public ItemProperty {
+    IrotBox(const sp<DataSource> source) :
+        Box(source, FOURCC('i', 'r', 'o', 't')), mAngle(0) {}
+
+    status_t parse(off64_t offset, size_t size) override;
+
+    void attachTo(ImageItem &image) const override {
+        image.rotation = mAngle * 90;
+    }
+
+private:
+    uint8_t mAngle;
+};
+
+status_t IrotBox::parse(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    if (size < 1) {
+        return ERROR_MALFORMED;
+    }
+    if (source()->readAt(offset, &mAngle, 1) != 1) {
+        return ERROR_IO;
+    }
+    mAngle &= 0x3;
+    ALOGV("property irot: %d", mAngle);
+
+    return OK;
+}
+
+struct ColrBox : public Box, public ItemProperty {
+    ColrBox(const sp<DataSource> source) :
+        Box(source, FOURCC('c', 'o', 'l', 'r')) {}
+
+    status_t parse(off64_t offset, size_t size) override;
+
+    void attachTo(ImageItem &image) const override {
+        image.icc = mICCData;
+    }
+
+private:
+    sp<ABuffer> mICCData;
+};
+
+status_t ColrBox::parse(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    if (size < 4) {
+        return ERROR_MALFORMED;
+    }
+    uint32_t colour_type;
+    if (!source()->getUInt32(offset, &colour_type)) {
+        return ERROR_IO;
+    }
+    offset += 4;
+    size -= 4;
+    if (colour_type == FOURCC('n', 'c', 'l', 'x')) {
+        return OK;
+    }
+    if ((colour_type != FOURCC('r', 'I', 'C', 'C')) &&
+        (colour_type != FOURCC('p', 'r', 'o', 'f'))) {
+        return ERROR_MALFORMED;
+    }
+
+    mICCData = new ABuffer(size);
+    if (mICCData->data() == NULL) {
+        ALOGE("b/28471206");
+        return NO_MEMORY;
+    }
+
+    if (source()->readAt(offset, mICCData->data(), size) != (ssize_t)size) {
+        return ERROR_IO;
+    }
+
+    ALOGV("property Colr: size %zd", size);
+    return OK;
+}
+
+struct IpmaBox : public FullBox {
+    IpmaBox(const sp<DataSource> source, Vector<AssociationEntry> *associations) :
+        FullBox(source, FOURCC('i', 'p', 'm', 'a')), mAssociations(associations) {}
+
+    status_t parse(off64_t offset, size_t size);
+private:
+    Vector<AssociationEntry> *mAssociations;
+};
+
+status_t IpmaBox::parse(off64_t offset, size_t size) {
+    status_t err = parseFullBoxHeader(&offset, &size);
+    if (err != OK) {
+        return err;
+    }
+
+    if (size < 4) {
+        return ERROR_MALFORMED;
+    }
+    uint32_t entryCount;
+    if (!source()->getUInt32(offset, &entryCount)) {
+        return ERROR_IO;
+    }
+    offset += 4;
+    size -= 4;
+
+    for (size_t k = 0; k < entryCount; ++k) {
+        uint32_t itemId = 0;
+        size_t itemIdSize = (version() < 1) ? 2 : 4;
+
+        if (size < itemIdSize + 1) {
+            return ERROR_MALFORMED;
+        }
+
+        if (!source()->getUInt32Var(offset, &itemId, itemIdSize)) {
+            return ERROR_IO;
+        }
+        offset += itemIdSize;
+        size -= itemIdSize;
+
+        uint8_t associationCount;
+        if (!source()->readAt(offset, &associationCount, 1)) {
+            return ERROR_IO;
+        }
+        offset++;
+        size--;
+
+        for (size_t i = 0; i < associationCount; ++i) {
+            size_t propIndexSize = (flags() & 1) ? 2 : 1;
+            if (size < propIndexSize) {
+                return ERROR_MALFORMED;
+            }
+            uint16_t propIndex;
+            if (!source()->getUInt16Var(offset, &propIndex, propIndexSize)) {
+                return ERROR_IO;
+            }
+            offset += propIndexSize;
+            size -= propIndexSize;
+            uint16_t bitmask = (1 << (8 * propIndexSize - 1));
+            AssociationEntry entry = {
+                    .itemId = itemId,
+                    .essential = !!(propIndex & bitmask),
+                    .index = (uint16_t) (propIndex & ~bitmask)
+            };
+
+            ALOGV("item id %d associated to property %d (essential %d)",
+                    itemId, entry.index, entry.essential);
+
+            mAssociations->push_back(entry);
+        }
+    }
+
+    return OK;
+}
+
+struct IpcoBox : public Box {
+    IpcoBox(const sp<DataSource> source, Vector<sp<ItemProperty> > *properties) :
+        Box(source, FOURCC('i', 'p', 'c', 'o')), mItemProperties(properties) {}
+
+    status_t parse(off64_t offset, size_t size);
+protected:
+    status_t onChunkData(uint32_t type, off64_t offset, size_t size) override;
+
+private:
+    Vector<sp<ItemProperty> > *mItemProperties;
+};
+
+status_t IpcoBox::parse(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+    // push dummy as the index is 1-based
+    mItemProperties->push_back(new ItemProperty());
+    return parseChunks(offset, size);
+}
+
+status_t IpcoBox::onChunkData(uint32_t type, off64_t offset, size_t size) {
+    sp<ItemProperty> itemProperty;
+    switch(type) {
+        case FOURCC('h', 'v', 'c', 'C'):
+        {
+            itemProperty = new HvccBox(source());
+            break;
+        }
+        case FOURCC('i', 's', 'p', 'e'):
+        {
+            itemProperty = new IspeBox(source());
+            break;
+        }
+        case FOURCC('i', 'r', 'o', 't'):
+        {
+            itemProperty = new IrotBox(source());
+            break;
+        }
+        case FOURCC('c', 'o', 'l', 'r'):
+        {
+            itemProperty = new ColrBox(source());
+            break;
+        }
+        default:
+        {
+            // push dummy to maintain correct item property index
+            itemProperty = new ItemProperty();
+            break;
+        }
+    }
+    status_t err = itemProperty->parse(offset, size);
+    if (err != OK) {
+        return err;
+    }
+    mItemProperties->push_back(itemProperty);
+    return OK;
+}
+
+struct IprpBox : public Box {
+    IprpBox(const sp<DataSource> source,
+            Vector<sp<ItemProperty> > *properties,
+            Vector<AssociationEntry> *associations) :
+        Box(source, FOURCC('i', 'p', 'r', 'p')),
+        mProperties(properties), mAssociations(associations) {}
+
+    status_t parse(off64_t offset, size_t size);
+protected:
+    status_t onChunkData(uint32_t type, off64_t offset, size_t size) override;
+
+private:
+    Vector<sp<ItemProperty> > *mProperties;
+    Vector<AssociationEntry> *mAssociations;
+};
+
+status_t IprpBox::parse(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    status_t err = parseChunks(offset, size);
+    if (err != OK) {
+        return err;
+    }
+    return OK;
+}
+
+status_t IprpBox::onChunkData(uint32_t type, off64_t offset, size_t size) {
+    switch(type) {
+        case FOURCC('i', 'p', 'c', 'o'):
+        {
+            IpcoBox ipcoBox(source(), mProperties);
+            return ipcoBox.parse(offset, size);
+        }
+        case FOURCC('i', 'p', 'm', 'a'):
+        {
+            IpmaBox ipmaBox(source(), mAssociations);
+            return ipmaBox.parse(offset, size);
+        }
+        default:
+        {
+            ALOGW("Unrecognized box.");
+            break;
+        }
+    }
+    return OK;
+}
+
+/////////////////////////////////////////////////////////////////////
+//
+//  ItemInfo related boxes
+//
+struct ItemInfo {
+    uint32_t itemId;
+    uint32_t itemType;
+};
+
+struct InfeBox : public FullBox {
+    InfeBox(const sp<DataSource> source) :
+        FullBox(source, FOURCC('i', 'n', 'f', 'e')) {}
+
+    status_t parse(off64_t offset, size_t size, ItemInfo *itemInfo);
+
+private:
+    bool parseNullTerminatedString(off64_t *offset, size_t *size, String8 *out);
+};
+
+bool InfeBox::parseNullTerminatedString(
+        off64_t *offset, size_t *size, String8 *out) {
+    char tmp[256];
+    size_t len = 0;
+    off64_t newOffset = *offset;
+    off64_t stopOffset = *offset + *size;
+    while (newOffset < stopOffset) {
+        if (!source()->readAt(newOffset++, &tmp[len], 1)) {
+            return false;
+        }
+        if (tmp[len] == 0) {
+            out->append(tmp, len);
+
+            *offset = newOffset;
+            *size = stopOffset - newOffset;
+
+            return true;
+        }
+        if (++len >= sizeof(tmp)) {
+            out->append(tmp, len);
+            len = 0;
+        }
+    }
+    return false;
+}
+
+status_t InfeBox::parse(off64_t offset, size_t size, ItemInfo *itemInfo) {
+    status_t err = parseFullBoxHeader(&offset, &size);
+    if (err != OK) {
+        return err;
+    }
+
+    if (version() == 0 || version() == 1) {
+        if (size < 4) {
+            return ERROR_MALFORMED;
+        }
+        uint16_t item_id;
+        if (!source()->getUInt16(offset, &item_id)) {
+            return ERROR_IO;
+        }
+        ALOGV("item_id %d", item_id);
+        uint16_t item_protection_index;
+        if (!source()->getUInt16(offset + 2, &item_protection_index)) {
+            return ERROR_IO;
+        }
+        offset += 4;
+        size -= 4;
+
+        String8 item_name;
+        if (!parseNullTerminatedString(&offset, &size, &item_name)) {
+            return ERROR_MALFORMED;
+        }
+
+        String8 content_type;
+        if (!parseNullTerminatedString(&offset, &size, &content_type)) {
+            return ERROR_MALFORMED;
+        }
+
+        String8 content_encoding;
+        if (!parseNullTerminatedString(&offset, &size, &content_encoding)) {
+            return ERROR_MALFORMED;
+        }
+
+        if (version() == 1) {
+            uint32_t extension_type;
+            if (!source()->getUInt32(offset, &extension_type)) {
+                return ERROR_IO;
+            }
+            offset++;
+            size--;
+            // TODO: handle this case
+        }
+    } else { // version >= 2
+        uint32_t item_id;
+        size_t itemIdSize = (version() == 2) ? 2 : 4;
+        if (size < itemIdSize + 6) {
+            return ERROR_MALFORMED;
+        }
+        if (!source()->getUInt32Var(offset, &item_id, itemIdSize)) {
+            return ERROR_IO;
+        }
+        ALOGV("item_id %d", item_id);
+        offset += itemIdSize;
+        uint16_t item_protection_index;
+        if (!source()->getUInt16(offset, &item_protection_index)) {
+            return ERROR_IO;
+        }
+        ALOGV("item_protection_index %d", item_protection_index);
+        offset += 2;
+        uint32_t item_type;
+        if (!source()->getUInt32(offset, &item_type)) {
+            return ERROR_IO;
+        }
+
+        itemInfo->itemId = item_id;
+        itemInfo->itemType = item_type;
+
+        char itemTypeString[5];
+        MakeFourCCString(item_type, itemTypeString);
+        ALOGV("item_type %s", itemTypeString);
+        offset += 4;
+        size -= itemIdSize + 6;
+
+        String8 item_name;
+        if (!parseNullTerminatedString(&offset, &size, &item_name)) {
+            return ERROR_MALFORMED;
+        }
+        ALOGV("item_name %s", item_name.c_str());
+
+        if (item_type == FOURCC('m', 'i', 'm', 'e')) {
+            String8 content_type;
+            if (!parseNullTerminatedString(&offset, &size, &content_type)) {
+                return ERROR_MALFORMED;
+            }
+
+            String8 content_encoding;
+            if (!parseNullTerminatedString(&offset, &size, &content_encoding)) {
+                return ERROR_MALFORMED;
+            }
+        } else if (item_type == FOURCC('u', 'r', 'i', ' ')) {
+            String8 item_uri_type;
+            if (!parseNullTerminatedString(&offset, &size, &item_uri_type)) {
+                return ERROR_MALFORMED;
+            }
+        }
+    }
+    return OK;
+}
+
+struct IinfBox : public FullBox {
+    IinfBox(const sp<DataSource> source, Vector<ItemInfo> *itemInfos) :
+        FullBox(source, FOURCC('i', 'i', 'n', 'f')),
+        mItemInfos(itemInfos), mHasGrids(false) {}
+
+    status_t parse(off64_t offset, size_t size);
+
+    bool hasGrids() { return mHasGrids; }
+
+protected:
+    status_t onChunkData(uint32_t type, off64_t offset, size_t size) override;
+
+private:
+    Vector<ItemInfo> *mItemInfos;
+    bool mHasGrids;
+};
+
+status_t IinfBox::parse(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    status_t err = parseFullBoxHeader(&offset, &size);
+    if (err != OK) {
+        return err;
+    }
+
+    size_t entryCountSize = version() == 0 ? 2 : 4;
+    if (size < entryCountSize) {
+        return ERROR_MALFORMED;
+    }
+    uint32_t entry_count;
+    if (!source()->getUInt32Var(offset, &entry_count, entryCountSize)) {
+        return ERROR_IO;
+    }
+    ALOGV("entry_count %d", entry_count);
+
+    off64_t stopOffset = offset + size;
+    offset += entryCountSize;
+    for (size_t i = 0; i < entry_count && offset < stopOffset; i++) {
+        ALOGV("entry %zu", i);
+        status_t err = parseChunk(&offset);
+        if (err != OK) {
+            return err;
+        }
+    }
+    if (offset != stopOffset) {
+        return ERROR_MALFORMED;
+    }
+
+    return OK;
+}
+
+status_t IinfBox::onChunkData(uint32_t type, off64_t offset, size_t size) {
+    if (type != FOURCC('i', 'n', 'f', 'e')) {
+        return OK;
+    }
+
+    InfeBox infeBox(source());
+    ItemInfo itemInfo;
+    status_t err = infeBox.parse(offset, size, &itemInfo);
+    if (err != OK) {
+        return err;
+    }
+    mItemInfos->push_back(itemInfo);
+    mHasGrids |= (itemInfo.itemType == FOURCC('g', 'r', 'i', 'd'));
+    return OK;
+}
+
+//////////////////////////////////////////////////////////////////
+
+ItemTable::ItemTable(const sp<DataSource> &source)
+    : mDataSource(source),
+      mPrimaryItemId(0),
+      mIdatOffset(0),
+      mIdatSize(0),
+      mImageItemsValid(false),
+      mCurrentImageIndex(0) {
+    mRequiredBoxes.insert('iprp');
+    mRequiredBoxes.insert('iloc');
+    mRequiredBoxes.insert('pitm');
+    mRequiredBoxes.insert('iinf');
+}
+
+ItemTable::~ItemTable() {}
+
+status_t ItemTable::parse(uint32_t type, off64_t data_offset, size_t chunk_data_size) {
+    switch(type) {
+        case FOURCC('i', 'l', 'o', 'c'):
+        {
+            return parseIlocBox(data_offset, chunk_data_size);
+        }
+        case FOURCC('i', 'i', 'n', 'f'):
+        {
+            return parseIinfBox(data_offset, chunk_data_size);
+        }
+        case FOURCC('i', 'p', 'r', 'p'):
+        {
+            return parseIprpBox(data_offset, chunk_data_size);
+        }
+        case FOURCC('p', 'i', 't', 'm'):
+        {
+            return parsePitmBox(data_offset, chunk_data_size);
+        }
+        case FOURCC('i', 'd', 'a', 't'):
+        {
+            return parseIdatBox(data_offset, chunk_data_size);
+        }
+        case FOURCC('i', 'r', 'e', 'f'):
+        {
+            return parseIrefBox(data_offset, chunk_data_size);
+        }
+        case FOURCC('i', 'p', 'r', 'o'):
+        {
+            ALOGW("ipro box not supported!");
+            break;
+        }
+        default:
+        {
+            ALOGW("unrecognized box type: 0x%x", type);
+            break;
+        }
+    }
+    return ERROR_UNSUPPORTED;
+}
+
+status_t ItemTable::parseIlocBox(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    IlocBox ilocBox(mDataSource, &mItemLocs);
+    status_t err = ilocBox.parse(offset, size);
+    if (err != OK) {
+        return err;
+    }
+
+    if (ilocBox.hasConstructMethod1()) {
+        mRequiredBoxes.insert('idat');
+    }
+
+    return buildImageItemsIfPossible('iloc');
+}
+
+status_t ItemTable::parseIinfBox(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    IinfBox iinfBox(mDataSource, &mItemInfos);
+    status_t err = iinfBox.parse(offset, size);
+    if (err != OK) {
+        return err;
+    }
+
+    if (iinfBox.hasGrids()) {
+        mRequiredBoxes.insert('iref');
+    }
+
+    return buildImageItemsIfPossible('iinf');
+}
+
+status_t ItemTable::parsePitmBox(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    PitmBox pitmBox(mDataSource);
+    status_t err = pitmBox.parse(offset, size, &mPrimaryItemId);
+    if (err != OK) {
+        return err;
+    }
+
+    return buildImageItemsIfPossible('pitm');
+}
+
+status_t ItemTable::parseIprpBox(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    IprpBox iprpBox(mDataSource, &mItemProperties, &mAssociations);
+    status_t err = iprpBox.parse(offset, size);
+    if (err != OK) {
+        return err;
+    }
+
+    return buildImageItemsIfPossible('iprp');
+}
+
+status_t ItemTable::parseIdatBox(off64_t offset, size_t size) {
+    ALOGV("%s: idat offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    // only remember the offset and size of idat box for later use
+    mIdatOffset = offset;
+    mIdatSize = size;
+
+    return buildImageItemsIfPossible('idat');
+}
+
+status_t ItemTable::parseIrefBox(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    IrefBox irefBox(mDataSource, &mItemReferences);
+    status_t err = irefBox.parse(offset, size);
+    if (err != OK) {
+        return err;
+    }
+
+    return buildImageItemsIfPossible('iref');
+}
+
+status_t ItemTable::buildImageItemsIfPossible(uint32_t type) {
+    if (mImageItemsValid) {
+        return OK;
+    }
+
+    mBoxesSeen.insert(type);
+
+    // need at least 'iprp', 'iloc', 'pitm', 'iinf';
+    // need 'idat' if any items used construction_method of 2;
+    // need 'iref' if there are grids.
+    if (!std::includes(
+            mBoxesSeen.begin(), mBoxesSeen.end(),
+            mRequiredBoxes.begin(), mRequiredBoxes.end())) {
+        return OK;
+    }
+
+    ALOGV("building image table...");
+
+    for (size_t i = 0; i < mItemInfos.size(); i++) {
+        const ItemInfo &info = mItemInfos[i];
+
+
+        // ignore non-image items
+        if (info.itemType != FOURCC('g', 'r', 'i', 'd') &&
+            info.itemType != FOURCC('h', 'v', 'c', '1')) {
+            continue;
+        }
+
+        ssize_t imageIndex = mItemIdToImageMap.indexOfKey(info.itemId);
+        if (imageIndex >= 0) {
+            ALOGW("ignoring duplicate image item id %d", info.itemId);
+            continue;
+        }
+
+        ssize_t ilocIndex = mItemLocs.indexOfKey(info.itemId);
+        if (ilocIndex < 0) {
+            ALOGE("iloc missing for image item id %d", info.itemId);
+            continue;
+        }
+        const ItemLoc &iloc = mItemLocs[ilocIndex];
+
+        off64_t offset;
+        size_t size;
+        if (iloc.getLoc(&offset, &size, mIdatOffset, mIdatSize) != OK) {
+            return ERROR_MALFORMED;
+        }
+
+        ImageItem image(info.itemType);
+
+        ALOGV("adding %s: itemId %d", image.isGrid() ? "grid" : "image", info.itemId);
+
+        if (image.isGrid()) {
+            if (size > 12) {
+                return ERROR_MALFORMED;
+            }
+            uint8_t buf[12];
+            if (!mDataSource->readAt(offset, buf, size)) {
+                return ERROR_IO;
+            }
+
+            image.rows = buf[2] + 1;
+            image.columns = buf[3] + 1;
+
+            ALOGV("rows %d, columans %d", image.rows, image.columns);
+        } else {
+            image.offset = offset;
+            image.size = size;
+        }
+        mItemIdToImageMap.add(info.itemId, image);
+    }
+
+    for (size_t i = 0; i < mAssociations.size(); i++) {
+        attachProperty(mAssociations[i]);
+    }
+
+    for (size_t i = 0; i < mItemReferences.size(); i++) {
+        mItemReferences[i]->apply(mItemIdToImageMap);
+    }
+
+    mImageItemsValid = true;
+    return OK;
+}
+
+void ItemTable::attachProperty(const AssociationEntry &association) {
+    ssize_t imageIndex = mItemIdToImageMap.indexOfKey(association.itemId);
+
+    // ignore non-image items
+    if (imageIndex < 0) {
+        return;
+    }
+
+    uint16_t propertyIndex = association.index;
+    if (propertyIndex >= mItemProperties.size()) {
+        ALOGW("Ignoring invalid property index %d", propertyIndex);
+        return;
+    }
+
+    ALOGV("attach property %d to item id %d)",
+            propertyIndex, association.itemId);
+
+    mItemProperties[propertyIndex]->attachTo(
+            mItemIdToImageMap.editValueAt(imageIndex));
+}
+
+sp<MetaData> ItemTable::getImageMeta() {
+    if (!mImageItemsValid) {
+        return NULL;
+    }
+
+    ssize_t imageIndex = mItemIdToImageMap.indexOfKey(mPrimaryItemId);
+    if (imageIndex < 0) {
+        ALOGE("Primary item id %d not found!", mPrimaryItemId);
+        return NULL;
+    }
+
+    ALOGV("primary image index %zu", imageIndex);
+
+    const ImageItem *image = &mItemIdToImageMap[imageIndex];
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
+
+    ALOGV("setting image size %dx%d", image->width, image->height);
+    meta->setInt32(kKeyWidth, image->width);
+    meta->setInt32(kKeyHeight, image->height);
+    if (image->rotation != 0) {
+        // Rotation angle in HEIF is CCW, convert to CW here to be
+        // consistent with the other media formats.
+        switch(image->rotation) {
+            case 90: meta->setInt32(kKeyRotation, 270); break;
+            case 180: meta->setInt32(kKeyRotation, 180); break;
+            case 270: meta->setInt32(kKeyRotation, 90); break;
+            default: break; // don't set if invalid
+        }
+    }
+    meta->setInt32(kKeyMaxInputSize, image->width * image->height * 1.5);
+
+    if (!image->thumbnails.empty()) {
+        ssize_t thumbnailIndex = mItemIdToImageMap.indexOfKey(image->thumbnails[0]);
+        if (thumbnailIndex >= 0) {
+            const ImageItem &thumbnail = mItemIdToImageMap[thumbnailIndex];
+
+            meta->setInt32(kKeyThumbnailWidth, thumbnail.width);
+            meta->setInt32(kKeyThumbnailHeight, thumbnail.height);
+            meta->setData(kKeyThumbnailHVCC, kTypeHVCC,
+                    thumbnail.hvcc->data(), thumbnail.hvcc->size());
+            ALOGV("thumbnail meta: %dx%d, index %zd",
+                    thumbnail.width, thumbnail.height, thumbnailIndex);
+        } else {
+            ALOGW("Referenced thumbnail does not exist!");
+        }
+    }
+
+    if (image->isGrid()) {
+        ssize_t tileIndex = mItemIdToImageMap.indexOfKey(image->dimgRefs[0]);
+        if (tileIndex < 0) {
+            return NULL;
+        }
+        // when there are tiles, (kKeyWidth, kKeyHeight) is the full tiled area,
+        // and (kKeyDisplayWidth, kKeyDisplayHeight) may be smaller than that.
+        meta->setInt32(kKeyDisplayWidth, image->width);
+        meta->setInt32(kKeyDisplayHeight, image->height);
+        int32_t gridRows = image->rows, gridCols = image->columns;
+
+        // point image to the first tile for grid size and HVCC
+        image = &mItemIdToImageMap.editValueAt(tileIndex);
+        meta->setInt32(kKeyWidth, image->width * gridCols);
+        meta->setInt32(kKeyHeight, image->height * gridRows);
+        meta->setInt32(kKeyGridWidth, image->width);
+        meta->setInt32(kKeyGridHeight, image->height);
+        meta->setInt32(kKeyMaxInputSize, image->width * image->height * 1.5);
+    }
+
+    if (image->hvcc == NULL) {
+        ALOGE("hvcc is missing!");
+        return NULL;
+    }
+    meta->setData(kKeyHVCC, kTypeHVCC, image->hvcc->data(), image->hvcc->size());
+
+    if (image->icc != NULL) {
+        meta->setData(kKeyIccProfile, 0, image->icc->data(), image->icc->size());
+    }
+    return meta;
+}
+
+uint32_t ItemTable::countImages() const {
+    return mImageItemsValid ? mItemIdToImageMap.size() : 0;
+}
+
+status_t ItemTable::findPrimaryImage(uint32_t *imageIndex) {
+    if (!mImageItemsValid) {
+        return INVALID_OPERATION;
+    }
+
+    ssize_t index = mItemIdToImageMap.indexOfKey(mPrimaryItemId);
+    if (index < 0) {
+        return ERROR_MALFORMED;
+    }
+
+    *imageIndex = index;
+    return OK;
+}
+
+status_t ItemTable::findThumbnail(uint32_t *imageIndex) {
+    if (!mImageItemsValid) {
+        return INVALID_OPERATION;
+    }
+
+    ssize_t primaryIndex = mItemIdToImageMap.indexOfKey(mPrimaryItemId);
+    if (primaryIndex < 0) {
+        ALOGE("Primary item id %d not found!", mPrimaryItemId);
+        return ERROR_MALFORMED;
+    }
+
+    const ImageItem &primaryImage = mItemIdToImageMap[primaryIndex];
+    if (primaryImage.thumbnails.empty()) {
+        ALOGW("Using primary in place of thumbnail.");
+        *imageIndex = primaryIndex;
+        return OK;
+    }
+
+    ssize_t thumbnailIndex = mItemIdToImageMap.indexOfKey(
+            primaryImage.thumbnails[0]);
+    if (thumbnailIndex < 0) {
+        ALOGE("Thumbnail item id %d not found!", primaryImage.thumbnails[0]);
+        return ERROR_MALFORMED;
+    }
+
+    *imageIndex = thumbnailIndex;
+    return OK;
+}
+
+status_t ItemTable::getImageOffsetAndSize(
+        uint32_t *imageIndex, off64_t *offset, size_t *size) {
+    if (!mImageItemsValid) {
+        return INVALID_OPERATION;
+    }
+
+    if (imageIndex != NULL) {
+        if (*imageIndex >= mItemIdToImageMap.size()) {
+            ALOGE("Bad image index!");
+            return BAD_VALUE;
+        }
+        mCurrentImageIndex = *imageIndex;
+    }
+
+    ImageItem &image = mItemIdToImageMap.editValueAt(mCurrentImageIndex);
+    if (image.isGrid()) {
+        uint32_t tileItemId;
+        status_t err = image.getNextTileItemId(&tileItemId, imageIndex != NULL);
+        if (err != OK) {
+            return err;
+        }
+        ssize_t tileImageIndex = mItemIdToImageMap.indexOfKey(tileItemId);
+        if (tileImageIndex < 0) {
+            return ERROR_END_OF_STREAM;
+        }
+        *offset = mItemIdToImageMap[tileImageIndex].offset;
+        *size = mItemIdToImageMap[tileImageIndex].size;
+    } else {
+        if (imageIndex == NULL) {
+            // For single images, we only allow it to be read once, after that
+            // it's EOS.  New image index must be requested each time.
+            return ERROR_END_OF_STREAM;
+        }
+        *offset = mItemIdToImageMap[mCurrentImageIndex].offset;
+        *size = mItemIdToImageMap[mCurrentImageIndex].size;
+    }
+
+    return OK;
+}
+
+} // namespace heif
+
+}  // namespace android
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 445a861..104b324 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -28,6 +28,7 @@
 
 #include "include/MPEG4Extractor.h"
 #include "include/SampleTable.h"
+#include "include/ItemTable.h"
 #include "include/ESDS.h"
 
 #include <media/stagefright/foundation/ABitReader.h>
@@ -36,6 +37,7 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/foundation/ColorUtils.h>
+#include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
@@ -72,7 +74,8 @@
                 const sp<SampleTable> &sampleTable,
                 Vector<SidxEntry> &sidx,
                 const Trex *trex,
-                off64_t firstMoofOffset);
+                off64_t firstMoofOffset,
+                const sp<ItemTable> &itemTable);
     virtual status_t init();
 
     virtual status_t start(MetaData *params = NULL);
@@ -134,6 +137,9 @@
 
     uint8_t *mSrcBuffer;
 
+    bool mIsHEIF;
+    sp<ItemTable> mItemTable;
+
     size_t parseNALSize(const uint8_t *data) const;
     status_t parseChunk(off64_t *offset);
     status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
@@ -285,45 +291,6 @@
 
 static const bool kUseHexDump = false;
 
-static void hexdump(const void *_data, size_t size) {
-    const uint8_t *data = (const uint8_t *)_data;
-    size_t offset = 0;
-    while (offset < size) {
-        printf("0x%04zx  ", offset);
-
-        size_t n = size - offset;
-        if (n > 16) {
-            n = 16;
-        }
-
-        for (size_t i = 0; i < 16; ++i) {
-            if (i == 8) {
-                printf(" ");
-            }
-
-            if (offset + i < size) {
-                printf("%02x ", data[offset + i]);
-            } else {
-                printf("   ");
-            }
-        }
-
-        printf(" ");
-
-        for (size_t i = 0; i < n; ++i) {
-            if (isprint(data[offset + i])) {
-                printf("%c", data[offset + i]);
-            } else {
-                printf(".");
-            }
-        }
-
-        printf("\n");
-
-        offset += 16;
-    }
-}
-
 static const char *FourCC2MIME(uint32_t fourcc) {
     switch (fourcc) {
         case FOURCC('m', 'p', '4', 'a'):
@@ -378,6 +345,7 @@
       mInitCheck(NO_INIT),
       mHeaderTimescale(0),
       mIsQT(false),
+      mIsHEIF(false),
       mFirstTrack(NULL),
       mLastTrack(NULL),
       mFileMetaData(new MetaData),
@@ -386,6 +354,10 @@
 }
 
 MPEG4Extractor::~MPEG4Extractor() {
+    release();
+}
+
+void MPEG4Extractor::release() {
     Track *track = mFirstTrack;
     while (track) {
         Track *next = track->next;
@@ -407,6 +379,12 @@
     for (size_t i = 0; i < mPssh.size(); i++) {
         delete [] mPssh[i].data;
     }
+    mPssh.clear();
+
+    if (mDataSource != NULL) {
+        mDataSource->close();
+        mDataSource.clear();
+    }
 }
 
 uint32_t MPEG4Extractor::flags() const {
@@ -572,14 +550,6 @@
     return track->meta;
 }
 
-static void MakeFourCCString(uint32_t x, char *s) {
-    s[0] = x >> 24;
-    s[1] = (x >> 16) & 0xff;
-    s[2] = (x >> 8) & 0xff;
-    s[3] = x & 0xff;
-    s[4] = '\0';
-}
-
 status_t MPEG4Extractor::readMetaData() {
     if (mInitCheck != NO_INIT) {
         return mInitCheck;
@@ -589,7 +559,8 @@
     status_t err;
     bool sawMoovOrSidx = false;
 
-    while (!(sawMoovOrSidx && (mMdatFound || mMoofFound))) {
+    while (!((sawMoovOrSidx && (mMdatFound || mMoofFound)) ||
+            (mIsHEIF && (mItemTable != NULL) && mItemTable->isValid()))) {
         off64_t orig_offset = offset;
         err = parseChunk(&offset, 0);
 
@@ -641,6 +612,29 @@
         mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
         free(buf);
     }
+
+    if (mIsHEIF) {
+        sp<MetaData> meta = mItemTable->getImageMeta();
+        if (meta == NULL) {
+            return ERROR_MALFORMED;
+        }
+
+        Track *track = mLastTrack;
+        if (track != NULL) {
+            ALOGW("track is set before metadata is fully processed");
+        } else {
+            track = new Track;
+            track->next = NULL;
+            mFirstTrack = mLastTrack = track;
+        }
+
+        track->meta = meta;
+        track->meta->setInt32(kKeyTrackID, 0);
+        track->includes_expensive_metadata = false;
+        track->skipTrack = false;
+        track->timescale = 0;
+    }
+
     return mInitCheck;
 }
 
@@ -1027,8 +1021,9 @@
                     }
                 }
 
-                if (mLastTrack == NULL)
+                if (mLastTrack == NULL) {
                     return ERROR_MALFORMED;
+                }
 
                 mLastTrack->sampleTable = new SampleTable(mDataSource);
             }
@@ -1184,8 +1179,9 @@
             original_fourcc = ntohl(original_fourcc);
             ALOGV("read original format: %d", original_fourcc);
 
-            if (mLastTrack == NULL)
+            if (mLastTrack == NULL) {
                 return ERROR_MALFORMED;
+            }
 
             mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
             uint32_t num_channels = 0;
@@ -1625,8 +1621,9 @@
         case FOURCC('s', 't', 'c', 'o'):
         case FOURCC('c', 'o', '6', '4'):
         {
-            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
+            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL)) {
                 return ERROR_MALFORMED;
+            }
 
             status_t err =
                 mLastTrack->sampleTable->setChunkOffsetParams(
@@ -1662,8 +1659,9 @@
         case FOURCC('s', 't', 's', 'z'):
         case FOURCC('s', 't', 'z', '2'):
         {
-            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
+            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL)) {
                 return ERROR_MALFORMED;
+            }
 
             status_t err =
                 mLastTrack->sampleTable->setSampleSizeParams(
@@ -1722,6 +1720,9 @@
                     // ratio. Use compression ratio of 1.
                     max_size = width * height * 3 / 2;
                 }
+                // HACK: allow 10% overhead
+                // TODO: read sample size from traf atom for fragmented MPEG4.
+                max_size += max_size / 10;
                 mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
             }
 
@@ -2079,6 +2080,28 @@
             break;
         }
 
+        case FOURCC('i', 'l', 'o', 'c'):
+        case FOURCC('i', 'i', 'n', 'f'):
+        case FOURCC('i', 'p', 'r', 'p'):
+        case FOURCC('p', 'i', 't', 'm'):
+        case FOURCC('i', 'd', 'a', 't'):
+        case FOURCC('i', 'r', 'e', 'f'):
+        case FOURCC('i', 'p', 'r', 'o'):
+        {
+            if (mIsHEIF) {
+                if (mItemTable == NULL) {
+                    mItemTable = new ItemTable(mDataSource);
+                }
+                status_t err = mItemTable->parse(
+                        chunk_type, data_offset, chunk_data_size);
+                if (err != OK) {
+                    return err;
+                }
+            }
+            *offset += chunk_size;
+            break;
+        }
+
         case FOURCC('m', 'e', 'a', 'n'):
         case FOURCC('n', 'a', 'm', 'e'):
         case FOURCC('d', 'a', 't', 'a'):
@@ -2426,6 +2449,7 @@
 
             off64_t stop_offset = *offset + chunk_size;
             uint32_t numCompatibleBrands = (chunk_data_size - 8) / 4;
+            std::set<uint32_t> brandSet;
             for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
                 if (i == 1) {
                     // Skip this index, it refers to the minorVersion,
@@ -2439,10 +2463,15 @@
                 }
 
                 brand = ntohl(brand);
-                if (brand == FOURCC('q', 't', ' ', ' ')) {
-                    mIsQT = true;
-                    break;
-                }
+                brandSet.insert(brand);
+            }
+
+            if (brandSet.count(FOURCC('q', 't', ' ', ' ')) > 0) {
+                mIsQT = true;
+            } else if (brandSet.count(FOURCC('m', 'i', 'f', '1')) > 0
+                    && brandSet.count(FOURCC('h', 'e', 'i', 'c')) > 0) {
+                mIsHEIF = true;
+                ALOGV("identified HEIF image");
             }
 
             *offset = stop_offset;
@@ -3391,7 +3420,7 @@
 
     sp<MPEG4Source> source =  new MPEG4Source(this,
             track->meta, mDataSource, track->timescale, track->sampleTable,
-            mSidxEntries, trex, mMoofOffset);
+            mSidxEntries, trex, mMoofOffset, mItemTable);
     if (source->init() != OK) {
         return NULL;
     }
@@ -3792,7 +3821,8 @@
         const sp<SampleTable> &sampleTable,
         Vector<SidxEntry> &sidx,
         const Trex *trex,
-        off64_t firstMoofOffset)
+        off64_t firstMoofOffset,
+        const sp<ItemTable> &itemTable)
     : mOwner(owner),
       mFormat(format),
       mDataSource(dataSource),
@@ -3817,7 +3847,9 @@
       mGroup(NULL),
       mBuffer(NULL),
       mWantsNALFragments(false),
-      mSrcBuffer(NULL) {
+      mSrcBuffer(NULL),
+      mIsHEIF(itemTable != NULL),
+      mItemTable(itemTable) {
 
     memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
 
@@ -4592,77 +4624,93 @@
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-        uint32_t findFlags = 0;
-        switch (mode) {
-            case ReadOptions::SEEK_PREVIOUS_SYNC:
-                findFlags = SampleTable::kFlagBefore;
-                break;
-            case ReadOptions::SEEK_NEXT_SYNC:
-                findFlags = SampleTable::kFlagAfter;
-                break;
-            case ReadOptions::SEEK_CLOSEST_SYNC:
-            case ReadOptions::SEEK_CLOSEST:
-                findFlags = SampleTable::kFlagClosest;
-                break;
-            default:
-                CHECK(!"Should not be here.");
-                break;
-        }
+        if (mIsHEIF) {
+            CHECK(mSampleTable == NULL);
+            CHECK(mItemTable != NULL);
 
-        uint32_t sampleIndex;
-        status_t err = mSampleTable->findSampleAtTime(
-                seekTimeUs, 1000000, mTimescale,
-                &sampleIndex, findFlags);
-
-        if (mode == ReadOptions::SEEK_CLOSEST) {
-            // We found the closest sample already, now we want the sync
-            // sample preceding it (or the sample itself of course), even
-            // if the subsequent sync sample is closer.
-            findFlags = SampleTable::kFlagBefore;
-        }
-
-        uint32_t syncSampleIndex;
-        if (err == OK) {
-            err = mSampleTable->findSyncSampleNear(
-                    sampleIndex, &syncSampleIndex, findFlags);
-        }
-
-        uint32_t sampleTime;
-        if (err == OK) {
-            err = mSampleTable->getMetaDataForSample(
-                    sampleIndex, NULL, NULL, &sampleTime);
-        }
-
-        if (err != OK) {
-            if (err == ERROR_OUT_OF_RANGE) {
-                // An attempt to seek past the end of the stream would
-                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
-                // this all the way to the MediaPlayer would cause abnormal
-                // termination. Legacy behaviour appears to be to behave as if
-                // we had seeked to the end of stream, ending normally.
-                err = ERROR_END_OF_STREAM;
+            status_t err;
+            if (seekTimeUs >= 0) {
+                err = mItemTable->findPrimaryImage(&mCurrentSampleIndex);
+            } else {
+                err = mItemTable->findThumbnail(&mCurrentSampleIndex);
             }
-            ALOGV("end of stream");
-            return err;
-        }
+            if (err != OK) {
+                return err;
+            }
+        } else {
+            uint32_t findFlags = 0;
+            switch (mode) {
+                case ReadOptions::SEEK_PREVIOUS_SYNC:
+                    findFlags = SampleTable::kFlagBefore;
+                    break;
+                case ReadOptions::SEEK_NEXT_SYNC:
+                    findFlags = SampleTable::kFlagAfter;
+                    break;
+                case ReadOptions::SEEK_CLOSEST_SYNC:
+                case ReadOptions::SEEK_CLOSEST:
+                    findFlags = SampleTable::kFlagClosest;
+                    break;
+                default:
+                    CHECK(!"Should not be here.");
+                    break;
+            }
 
-        if (mode == ReadOptions::SEEK_CLOSEST) {
-            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
-        }
+            uint32_t sampleIndex;
+            status_t err = mSampleTable->findSampleAtTime(
+                    seekTimeUs, 1000000, mTimescale,
+                    &sampleIndex, findFlags);
+
+            if (mode == ReadOptions::SEEK_CLOSEST) {
+                // We found the closest sample already, now we want the sync
+                // sample preceding it (or the sample itself of course), even
+                // if the subsequent sync sample is closer.
+                findFlags = SampleTable::kFlagBefore;
+            }
+
+            uint32_t syncSampleIndex;
+            if (err == OK) {
+                err = mSampleTable->findSyncSampleNear(
+                        sampleIndex, &syncSampleIndex, findFlags);
+            }
+
+            uint32_t sampleTime;
+            if (err == OK) {
+                err = mSampleTable->getMetaDataForSample(
+                        sampleIndex, NULL, NULL, &sampleTime);
+            }
+
+            if (err != OK) {
+                if (err == ERROR_OUT_OF_RANGE) {
+                    // An attempt to seek past the end of the stream would
+                    // normally cause this ERROR_OUT_OF_RANGE error. Propagating
+                    // this all the way to the MediaPlayer would cause abnormal
+                    // termination. Legacy behaviour appears to be to behave as if
+                    // we had seeked to the end of stream, ending normally.
+                    err = ERROR_END_OF_STREAM;
+                }
+                ALOGV("end of stream");
+                return err;
+            }
+
+            if (mode == ReadOptions::SEEK_CLOSEST) {
+                targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
+            }
 
 #if 0
-        uint32_t syncSampleTime;
-        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
-                    syncSampleIndex, NULL, NULL, &syncSampleTime));
+            uint32_t syncSampleTime;
+            CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
+                        syncSampleIndex, NULL, NULL, &syncSampleTime));
 
-        ALOGI("seek to time %lld us => sample at time %lld us, "
-             "sync sample at time %lld us",
-             seekTimeUs,
-             sampleTime * 1000000ll / mTimescale,
-             syncSampleTime * 1000000ll / mTimescale);
+            ALOGI("seek to time %lld us => sample at time %lld us, "
+                 "sync sample at time %lld us",
+                 seekTimeUs,
+                 sampleTime * 1000000ll / mTimescale,
+                 syncSampleTime * 1000000ll / mTimescale);
 #endif
 
-        mCurrentSampleIndex = syncSampleIndex;
+            mCurrentSampleIndex = syncSampleIndex;
+        }
+
         if (mBuffer != NULL) {
             mBuffer->release();
             mBuffer = NULL;
@@ -4679,9 +4727,19 @@
     if (mBuffer == NULL) {
         newBuffer = true;
 
-        status_t err =
-            mSampleTable->getMetaDataForSample(
+        status_t err;
+        if (!mIsHEIF) {
+            err = mSampleTable->getMetaDataForSample(
                     mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
+        } else {
+            err = mItemTable->getImageOffsetAndSize(
+                    options && options->getSeekTo(&seekTimeUs, &mode) ?
+                            &mCurrentSampleIndex : NULL, &offset, &size);
+
+            cts = stts = 0;
+            isSyncSample = 0;
+            ALOGV("image offset %lld, size %zu", (long long)offset, size);
+        }
 
         if (err != OK) {
             return err;
@@ -4695,6 +4753,8 @@
         }
         if (size > mBuffer->size()) {
             ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
+            mBuffer->release();
+            mBuffer = NULL;
             return ERROR_BUFFER_TOO_SMALL;
         }
     }
@@ -4987,6 +5047,8 @@
         }
         if (size > mBuffer->size()) {
             ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
+            mBuffer->release();
+            mBuffer = NULL;
             return ERROR_BUFFER_TOO_SMALL;
         }
     }
@@ -5235,6 +5297,7 @@
 
 void MPEG4Extractor::populateMetrics() {
     ALOGV("MPEG4Extractor::populateMetrics");
+    // write into mAnalyticsItem
 }
 
 static bool LegacySniffMPEG4(
@@ -5251,7 +5314,8 @@
         || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
         || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
         || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
-        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
+        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)
+        || !memcmp(header, "ftypmif1", 8) || !memcmp(header, "ftypheic", 8)) {
         *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
         *confidence = 0.4;
 
@@ -5280,6 +5344,8 @@
 
         FOURCC('3', 'g', '2', 'a'),  // 3GPP2
         FOURCC('3', 'g', '2', 'b'),
+        FOURCC('m', 'i', 'f', '1'),  // HEIF image
+        FOURCC('h', 'e', 'i', 'c'),  // HEIF image
     };
 
     for (size_t i = 0;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 93d4f57..7786c4d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -432,7 +432,7 @@
 };
 
 MPEG4Writer::MPEG4Writer(int fd) {
-    initInternal(fd);
+    initInternal(fd, true /*isFirstSession*/);
 }
 
 MPEG4Writer::~MPEG4Writer() {
@@ -451,19 +451,26 @@
     }
 }
 
-void MPEG4Writer::initInternal(int fd) {
+void MPEG4Writer::initInternal(int fd, bool isFirstSession) {
     ALOGV("initInternal");
     mFd = dup(fd);
     mNextFd = -1;
     mInitCheck = mFd < 0? NO_INIT: OK;
-    mIsRealTimeRecording = true;
-    mUse4ByteNalLength = true;
-    mUse32BitOffset = true;
-    mIsFileSizeLimitExplicitlyRequested = false;
+
+    mInterleaveDurationUs = 1000000;
+
+    mStartTimestampUs = -1ll;
+    mStartTimeOffsetMs = -1;
     mPaused = false;
     mStarted = false;
     mWriterThreadStarted = false;
     mSendNotify = false;
+
+    // Reset following variables for all the sessions and they will be
+    // initialized in start(MetaData *param).
+    mIsRealTimeRecording = true;
+    mUse4ByteNalLength = true;
+    mUse32BitOffset = true;
     mOffset = 0;
     mMdatOffset = 0;
     mMoovBoxBuffer = NULL;
@@ -472,17 +479,21 @@
     mFreeBoxOffset = 0;
     mStreamableFile = false;
     mEstimatedMoovBoxSize = 0;
-    mMoovExtraSize = 0;
-    mInterleaveDurationUs = 1000000;
     mTimeScale = -1;
-    mStartTimestampUs = -1ll;
-    mLatitudex10000 = 0;
-    mLongitudex10000 = 0;
-    mAreGeoTagsAvailable = false;
-    mStartTimeOffsetMs = -1;
-    mSwitchPending = false;
-    mMetaKeys = new AMessage();
-    addDeviceMeta();
+
+    // Following variables only need to be set for the first recording session.
+    // And they will stay the same for all the recording sessions.
+    if (isFirstSession) {
+        mMoovExtraSize = 0;
+        mMetaKeys = new AMessage();
+        addDeviceMeta();
+        mLatitudex10000 = 0;
+        mLongitudex10000 = 0;
+        mAreGeoTagsAvailable = false;
+        mSwitchPending = false;
+        mIsFileSizeLimitExplicitlyRequested = false;
+    }
+
     // Verify mFd is seekable
     off64_t off = lseek64(mFd, 0, SEEK_SET);
     if (off < 0) {
@@ -873,19 +884,8 @@
 }
 
 status_t MPEG4Writer::pause() {
-    if (mInitCheck != OK) {
-        return OK;
-    }
-    mPaused = true;
-    status_t err = OK;
-    for (List<Track *>::iterator it = mTracks.begin();
-         it != mTracks.end(); ++it) {
-        status_t status = (*it)->pause();
-        if (status != OK) {
-            err = status;
-        }
-    }
-    return err;
+    ALOGW("MPEG4Writer: pause is not supported");
+    return ERROR_UNSUPPORTED;
 }
 
 void MPEG4Writer::stopWriterThread() {
@@ -1833,7 +1833,7 @@
             int fd = mNextFd;
             mNextFd = -1;
             mLock.unlock();
-            initInternal(fd);
+            initInternal(fd, false /*isFirstSession*/);
             start(mStartMeta.get());
             mSwitchPending = false;
             notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index bd71632..759e42d 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -23,7 +23,8 @@
 #include "include/SharedMemoryBuffer.h"
 #include "include/SoftwareRenderer.h"
 
-#include <android/media/IDescrambler.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+
 #include <binder/IMemory.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
@@ -72,6 +73,13 @@
 static const char *kCodecCrypto = "android.media.mediacodec.crypto";   /* 0,1 */
 static const char *kCodecEncoder = "android.media.mediacodec.encoder"; /* 0,1 */
 
+static const char *kCodecBytesIn = "android.media.mediacodec.bytesin";  /* 0..n */
+static const char *kCodecProfile = "android.media.mediacodec.profile";  /* 0..n */
+static const char *kCodecLevel = "android.media.mediacodec.level";  /* 0..n */
+static const char *kCodecMaxWidth = "android.media.mediacodec.maxwidth";  /* 0..n */
+static const char *kCodecMaxHeight = "android.media.mediacodec.maxheight";  /* 0..n */
+static const char *kCodecError = "android.media.mediacodec.errcode";
+static const char *kCodecErrorState = "android.media.mediacodec.errstate";
 
 
 static int64_t getId(const sp<IResourceManagerClient> &client) {
@@ -428,22 +436,6 @@
 }
 
 // static
-status_t MediaCodec::QueryCapabilities(
-        const AString &name, const AString &mime, bool isEncoder,
-        sp<MediaCodecInfo::Capabilities> *caps /* nonnull */) {
-    // TRICKY: this method is used by MediaCodecList/Info during its
-    // initialization. As such, we cannot create a MediaCodec instance
-    // because that requires an initialized MediaCodecList.
-
-    sp<CodecBase> codec = GetCodecBase(name);
-    if (codec == NULL) {
-        return NAME_NOT_FOUND;
-    }
-
-    return codec->queryCapabilities(name, mime, isEncoder, caps);
-}
-
-// static
 sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
     OMXClient client;
     if (client.connect() != OK) {
@@ -475,6 +467,7 @@
       mFlags(0),
       mStickyError(OK),
       mSoftRenderer(NULL),
+      mAnalyticsItem(NULL),
       mResourceManagerClient(new ResourceManagerClient(this)),
       mResourceManagerService(new ResourceManagerServiceProxy(pid)),
       mBatteryStatNotified(false),
@@ -493,6 +486,18 @@
     } else {
         mUid = uid;
     }
+    initAnalyticsItem();
+}
+
+MediaCodec::~MediaCodec() {
+    CHECK_EQ(mState, UNINITIALIZED);
+    mResourceManagerService->removeResource(getId(mResourceManagerClient));
+
+    flushAnalyticsItem();
+}
+
+void MediaCodec::initAnalyticsItem() {
+    CHECK(mAnalyticsItem == NULL);
     // set up our new record, get a sessionID, put it into the in-progress list
     mAnalyticsItem = new MediaAnalyticsItem(kCodecKeyName);
     if (mAnalyticsItem != NULL) {
@@ -502,11 +507,9 @@
     }
 }
 
-MediaCodec::~MediaCodec() {
-    CHECK_EQ(mState, UNINITIALIZED);
-    mResourceManagerService->removeResource(getId(mResourceManagerClient));
-
-    if (mAnalyticsItem != NULL ) {
+void MediaCodec::flushAnalyticsItem() {
+    if (mAnalyticsItem != NULL) {
+        // don't log empty records
         if (mAnalyticsItem->count() > 0) {
             mAnalyticsItem->setFinalized(true);
             mAnalyticsItem->selfrecord();
@@ -699,10 +702,21 @@
         uint32_t flags) {
     sp<AMessage> msg = new AMessage(kWhatConfigure, this);
 
+    if (mAnalyticsItem != NULL) {
+        int32_t profile = 0;
+        if (format->findInt32("profile", &profile)) {
+            mAnalyticsItem->setInt32(kCodecProfile, profile);
+        }
+        int32_t level = 0;
+        if (format->findInt32("level", &level)) {
+            mAnalyticsItem->setInt32(kCodecLevel, level);
+        }
+    }
+
     if (mIsVideo) {
         format->findInt32("width", &mVideoWidth);
         format->findInt32("height", &mVideoHeight);
-        if (!format->findInt32(kCodecRotation, &mRotationDegrees)) {
+        if (!format->findInt32("rotation-degrees", &mRotationDegrees)) {
             mRotationDegrees = 0;
         }
 
@@ -710,6 +724,14 @@
             mAnalyticsItem->setInt32(kCodecWidth, mVideoWidth);
             mAnalyticsItem->setInt32(kCodecHeight, mVideoHeight);
             mAnalyticsItem->setInt32(kCodecRotation, mRotationDegrees);
+            int32_t maxWidth = 0;
+            if (format->findInt32("max-width", &maxWidth)) {
+                mAnalyticsItem->setInt32(kCodecMaxWidth, maxWidth);
+            }
+            int32_t maxHeight = 0;
+            if (format->findInt32("max-height", &maxHeight)) {
+                mAnalyticsItem->setInt32(kCodecMaxHeight, maxHeight);
+            }
         }
 
         // Prevent possible integer overflow in downstream code.
@@ -1416,6 +1438,12 @@
 
                         case CONFIGURING:
                         {
+                            if (actionCode == ACTION_CODE_FATAL) {
+                                mAnalyticsItem->setInt32(kCodecError, err);
+                                mAnalyticsItem->setInt32(kCodecErrorState, mState);
+                                flushAnalyticsItem();
+                                initAnalyticsItem();
+                            }
                             setState(actionCode == ACTION_CODE_FATAL ?
                                     UNINITIALIZED : INITIALIZED);
                             break;
@@ -1423,6 +1451,12 @@
 
                         case STARTING:
                         {
+                            if (actionCode == ACTION_CODE_FATAL) {
+                                mAnalyticsItem->setInt32(kCodecError, err);
+                                mAnalyticsItem->setInt32(kCodecErrorState, mState);
+                                flushAnalyticsItem();
+                                initAnalyticsItem();
+                            }
                             setState(actionCode == ACTION_CODE_FATAL ?
                                     UNINITIALIZED : CONFIGURED);
                             break;
@@ -1459,6 +1493,11 @@
                         case FLUSHING:
                         {
                             if (actionCode == ACTION_CODE_FATAL) {
+                                mAnalyticsItem->setInt32(kCodecError, err);
+                                mAnalyticsItem->setInt32(kCodecErrorState, mState);
+                                flushAnalyticsItem();
+                                initAnalyticsItem();
+
                                 setState(UNINITIALIZED);
                             } else {
                                 setState(
@@ -1487,6 +1526,10 @@
                                 setState(INITIALIZED);
                                 break;
                             default:
+                                mAnalyticsItem->setInt32(kCodecError, err);
+                                mAnalyticsItem->setInt32(kCodecErrorState, mState);
+                                flushAnalyticsItem();
+                                initAnalyticsItem();
                                 setState(UNINITIALIZED);
                                 break;
                             }
@@ -1591,6 +1634,19 @@
                     }
                     setState(CONFIGURED);
                     (new AMessage)->postReply(mReplyID);
+
+                    // augment our media metrics info, now that we know more things
+                    if (mAnalyticsItem != NULL) {
+                        sp<AMessage> format;
+                        if (mConfigureMsg != NULL &&
+                            mConfigureMsg->findMessage("format", &format)) {
+                                // format includes: mime
+                                AString mime;
+                                if (format->findString("mime", &mime)) {
+                                    mAnalyticsItem->setCString(kCodecMime, mime.c_str());
+                                }
+                            }
+                    }
                     break;
                 }
 
@@ -2816,6 +2872,9 @@
         Mutex::Autolock al(mBufferLock);
         info->mOwnedByClient = false;
         info->mData.clear();
+        if (mAnalyticsItem != NULL) {
+            mAnalyticsItem->addInt64(kCodecBytesIn, size);
+        }
     }
 
     return err;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 1dcba29..4652594 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -24,17 +24,17 @@
 
 #include <media/IMediaCodecList.h>
 #include <media/IMediaPlayerService.h>
-#include <media/IResourceManagerService.h>
+#include <media/IMediaCodecService.h>
 #include <media/MediaCodecInfo.h>
-#include <media/MediaResourcePolicy.h>
+#include <media/MediaDefs.h>
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/ACodec.h>
-#include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OmxInfoBuilder.h>
+#include <media/stagefright/omx/OMXUtils.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
 
 #include <sys/stat.h>
 #include <utils/threads.h>
@@ -42,20 +42,20 @@
 #include <cutils/properties.h>
 #include <expat.h>
 
+#include <algorithm>
+
 namespace android {
 
-static Mutex sInitMutex;
+namespace {
 
-static bool parseBoolean(const char *s) {
-    if (!strcasecmp(s, "true") || !strcasecmp(s, "yes") || !strcasecmp(s, "y")) {
-        return true;
-    }
-    char *end;
-    unsigned long res = strtoul(s, &end, 10);
-    return *s != '\0' && *end == '\0' && res > 0;
-}
+Mutex sInitMutex;
 
-static bool isProfilingNeeded() {
+Mutex sRemoteInitMutex;
+
+constexpr const char* kProfilingResults =
+        MediaCodecsXmlParser::defaultProfilingResultsXmlPath;
+
+bool isProfilingNeeded() {
     int8_t value = property_get_bool("debug.stagefright.profilecodec", 0);
     if (value == 0) {
         return false;
@@ -78,6 +78,10 @@
     return profilingNeeded;
 }
 
+OmxInfoBuilder sOmxInfoBuilder;
+
+}  // unnamed namespace
+
 // static
 sp<IMediaCodecList> MediaCodecList::sCodecList;
 
@@ -86,42 +90,42 @@
     ALOGV("Enter profilerThreadWrapper.");
     remove(kProfilingResults);  // remove previous result so that it won't be loaded to
                                 // the new MediaCodecList
-    MediaCodecList *codecList = new MediaCodecList();
+    sp<MediaCodecList> codecList(new MediaCodecList(&sOmxInfoBuilder));
     if (codecList->initCheck() != OK) {
         ALOGW("Failed to create a new MediaCodecList, skipping codec profiling.");
-        delete codecList;
-        return NULL;
+        return nullptr;
     }
 
-    Vector<sp<MediaCodecInfo>> infos;
-    for (size_t i = 0; i < codecList->countCodecs(); ++i) {
-        infos.push_back(codecList->getCodecInfo(i));
-    }
+    const auto& infos = codecList->mCodecInfos;
     ALOGV("Codec profiling started.");
-    profileCodecs(infos);
+    profileCodecs(infos, kProfilingResults);
     ALOGV("Codec profiling completed.");
-    codecList->parseTopLevelXMLFile(kProfilingResults, true /* ignore_errors */);
+    codecList = new MediaCodecList(&sOmxInfoBuilder);
+    if (codecList->initCheck() != OK) {
+        ALOGW("Failed to parse profiling results.");
+        return nullptr;
+    }
 
     {
         Mutex::Autolock autoLock(sInitMutex);
         sCodecList = codecList;
     }
-    return NULL;
+    return nullptr;
 }
 
 // static
 sp<IMediaCodecList> MediaCodecList::getLocalInstance() {
     Mutex::Autolock autoLock(sInitMutex);
 
-    if (sCodecList == NULL) {
-        MediaCodecList *codecList = new MediaCodecList;
+    if (sCodecList == nullptr) {
+        MediaCodecList *codecList = new MediaCodecList(&sOmxInfoBuilder);
         if (codecList->initCheck() == OK) {
             sCodecList = codecList;
 
             if (isProfilingNeeded()) {
                 ALOGV("Codec profiling needed, will be run in separated thread.");
                 pthread_t profiler;
-                if (pthread_create(&profiler, NULL, profilerThreadWrapper, NULL) != 0) {
+                if (pthread_create(&profiler, nullptr, profilerThreadWrapper, nullptr) != 0) {
                     ALOGW("Failed to create thread for codec profiling.");
                 }
             }
@@ -134,8 +138,6 @@
     return sCodecList;
 }
 
-static Mutex sRemoteInitMutex;
-
 sp<IMediaCodecList> MediaCodecList::sRemoteList;
 
 sp<MediaCodecList::BinderDeathObserver> MediaCodecList::sBinderDeathObserver;
@@ -149,19 +151,19 @@
 // static
 sp<IMediaCodecList> MediaCodecList::getInstance() {
     Mutex::Autolock _l(sRemoteInitMutex);
-    if (sRemoteList == NULL) {
+    if (sRemoteList == nullptr) {
         sp<IBinder> binder =
             defaultServiceManager()->getService(String16("media.player"));
         sp<IMediaPlayerService> service =
             interface_cast<IMediaPlayerService>(binder);
-        if (service.get() != NULL) {
+        if (service.get() != nullptr) {
             sRemoteList = service->getCodecList();
-            if (sRemoteList != NULL) {
+            if (sRemoteList != nullptr) {
                 sBinderDeathObserver = new BinderDeathObserver();
                 binder->linkToDeath(sBinderDeathObserver.get());
             }
         }
-        if (sRemoteList == NULL) {
+        if (sRemoteList == nullptr) {
             // if failed to get remote list, create local list
             sRemoteList = getLocalInstance();
         }
@@ -169,175 +171,11 @@
     return sRemoteList;
 }
 
-// Treblized media codec list will be located in /odm/etc or /vendor/etc.
-static const char *kConfigLocationList[] =
-        {"/odm/etc", "/vendor/etc", "/etc"};
-static const int kConfigLocationListSize =
-        (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
-
-#define MEDIA_CODECS_CONFIG_FILE_PATH_MAX_LENGTH 128
-
-static bool findMediaCodecListFileFullPath(const char *file_name, char *out_path) {
-    for (int i = 0; i < kConfigLocationListSize; i++) {
-        snprintf(out_path,
-                 MEDIA_CODECS_CONFIG_FILE_PATH_MAX_LENGTH,
-                 "%s/%s",
-                 kConfigLocationList[i],
-                 file_name);
-        struct stat file_stat;
-        if (stat(out_path, &file_stat) == 0 && S_ISREG(file_stat.st_mode)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-MediaCodecList::MediaCodecList()
-    : mInitCheck(NO_INIT),
-      mUpdate(false),
-      mGlobalSettings(new AMessage()) {
-    char config_file_path[MEDIA_CODECS_CONFIG_FILE_PATH_MAX_LENGTH];
-    if (findMediaCodecListFileFullPath("media_codecs.xml", config_file_path)) {
-        parseTopLevelXMLFile(config_file_path);
-    }
-    if (findMediaCodecListFileFullPath("media_codecs_performance.xml",
-                                       config_file_path)) {
-        parseTopLevelXMLFile(config_file_path, true/* ignore_errors */);
-    }
-    parseTopLevelXMLFile(kProfilingResults, true/* ignore_errors */);
-}
-
-void MediaCodecList::parseTopLevelXMLFile(const char *codecs_xml, bool ignore_errors) {
-    // get href_base
-    const char *href_base_end = strrchr(codecs_xml, '/');
-    if (href_base_end != NULL) {
-        mHrefBase = AString(codecs_xml, href_base_end - codecs_xml + 1);
-    }
-
-    mInitCheck = OK; // keeping this here for safety
-    mCurrentSection = SECTION_TOPLEVEL;
-    mDepth = 0;
-
-    OMXClient client;
-    mInitCheck = client.connect();
-    if (mInitCheck != OK) {
-        return;  // this may fail if IMediaPlayerService is not available.
-    }
-    parseXMLFile(codecs_xml);
-
-    if (mInitCheck != OK) {
-        if (ignore_errors) {
-            mInitCheck = OK;
-            return;
-        }
-        mCodecInfos.clear();
-        return;
-    }
-
-    Vector<MediaResourcePolicy> policies;
-    AString value;
-    if (mGlobalSettings->findString(kPolicySupportsMultipleSecureCodecs, &value)) {
-        policies.push_back(
-                MediaResourcePolicy(
-                        String8(kPolicySupportsMultipleSecureCodecs),
-                        String8(value.c_str())));
-    }
-    if (mGlobalSettings->findString(kPolicySupportsSecureWithNonSecureCodec, &value)) {
-        policies.push_back(
-                MediaResourcePolicy(
-                        String8(kPolicySupportsSecureWithNonSecureCodec),
-                        String8(value.c_str())));
-    }
-    if (policies.size() > 0) {
-        sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
-        sp<IResourceManagerService> service = interface_cast<IResourceManagerService>(binder);
-        if (service == NULL) {
-            ALOGE("MediaCodecList: failed to get ResourceManagerService");
-        } else {
-            service->config(policies);
-        }
-    }
-
-    for (size_t i = mCodecInfos.size(); i > 0;) {
-        i--;
-        const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get();
-        if (info.mCaps.size() == 0) {
-            // No types supported by this component???
-            ALOGW("Component %s does not support any type of media?",
-                  info.mName.c_str());
-
-            mCodecInfos.removeAt(i);
-#if LOG_NDEBUG == 0
-        } else {
-            for (size_t type_ix = 0; type_ix < info.mCaps.size(); ++type_ix) {
-                AString mime = info.mCaps.keyAt(type_ix);
-                const sp<MediaCodecInfo::Capabilities> &caps = info.mCaps.valueAt(type_ix);
-
-                ALOGV("%s codec info for %s: %s", info.mName.c_str(), mime.c_str(),
-                        caps->getDetails()->debugString().c_str());
-                ALOGV("    flags=%d", caps->getFlags());
-                {
-                    Vector<uint32_t> colorFormats;
-                    caps->getSupportedColorFormats(&colorFormats);
-                    AString nice;
-                    for (size_t ix = 0; ix < colorFormats.size(); ix++) {
-                        if (ix > 0) {
-                            nice.append(", ");
-                        }
-                        nice.append(colorFormats.itemAt(ix));
-                    }
-                    ALOGV("    colors=[%s]", nice.c_str());
-                }
-                {
-                    Vector<MediaCodecInfo::ProfileLevel> profileLevels;
-                    caps->getSupportedProfileLevels(&profileLevels);
-                    AString nice;
-                    for (size_t ix = 0; ix < profileLevels.size(); ix++) {
-                        if (ix > 0) {
-                            nice.append(", ");
-                        }
-                        const MediaCodecInfo::ProfileLevel &pl =
-                            profileLevels.itemAt(ix);
-                        nice.append(pl.mProfile);
-                        nice.append("/");
-                        nice.append(pl.mLevel);
-                    }
-                    ALOGV("    levels=[%s]", nice.c_str());
-                }
-                {
-                    AString quirks;
-                    for (size_t ix = 0; ix < info.mQuirks.size(); ix++) {
-                        if (ix > 0) {
-                            quirks.append(", ");
-                        }
-                        quirks.append(info.mQuirks[ix]);
-                    }
-                    ALOGV("    quirks=[%s]", quirks.c_str());
-                }
-            }
-#endif
-        }
-    }
-
-#if 0
-    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
-        const CodecInfo &info = mCodecInfos.itemAt(i);
-
-        AString line = info.mName;
-        line.append(" supports ");
-        for (size_t j = 0; j < mTypes.size(); ++j) {
-            uint32_t value = mTypes.valueAt(j);
-
-            if (info.mTypes & (1ul << value)) {
-                line.append(mTypes.keyAt(j));
-                line.append(" ");
-            }
-        }
-
-        ALOGI("%s", line.c_str());
-    }
-#endif
+MediaCodecList::MediaCodecList(MediaCodecListBuilderBase* builder) {
+    mGlobalSettings = new AMessage();
+    mCodecInfos.clear();
+    MediaCodecListWriter writer(this);
+    mInitCheck = builder->buildMediaCodecList(&writer);
 }
 
 MediaCodecList::~MediaCodecList() {
@@ -347,531 +185,21 @@
     return mInitCheck;
 }
 
-void MediaCodecList::parseXMLFile(const char *path) {
-    FILE *file = fopen(path, "r");
-
-    if (file == NULL) {
-        ALOGW("unable to open media codecs configuration xml file: %s", path);
-        mInitCheck = NAME_NOT_FOUND;
-        return;
-    }
-
-    XML_Parser parser = ::XML_ParserCreate(NULL);
-    CHECK(parser != NULL);
-
-    ::XML_SetUserData(parser, this);
-    ::XML_SetElementHandler(
-            parser, StartElementHandlerWrapper, EndElementHandlerWrapper);
-
-    const int BUFF_SIZE = 512;
-    while (mInitCheck == OK) {
-        void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
-        if (buff == NULL) {
-            ALOGE("failed in call to XML_GetBuffer()");
-            mInitCheck = UNKNOWN_ERROR;
-            break;
-        }
-
-        int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);
-        if (bytes_read < 0) {
-            ALOGE("failed in call to read");
-            mInitCheck = ERROR_IO;
-            break;
-        }
-
-        XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0);
-        if (status != XML_STATUS_OK) {
-            ALOGE("malformed (%s)", ::XML_ErrorString(::XML_GetErrorCode(parser)));
-            mInitCheck = ERROR_MALFORMED;
-            break;
-        }
-
-        if (bytes_read == 0) {
-            break;
-        }
-    }
-
-    ::XML_ParserFree(parser);
-
-    fclose(file);
-    file = NULL;
+MediaCodecListWriter::MediaCodecListWriter(MediaCodecList* list) :
+    mList(list) {
 }
 
-// static
-void MediaCodecList::StartElementHandlerWrapper(
-        void *me, const char *name, const char **attrs) {
-    static_cast<MediaCodecList *>(me)->startElementHandler(name, attrs);
+void MediaCodecListWriter::addGlobalSetting(
+        const char* key, const char* value) {
+    mList->mGlobalSettings->setString(key, value);
 }
 
-// static
-void MediaCodecList::EndElementHandlerWrapper(void *me, const char *name) {
-    static_cast<MediaCodecList *>(me)->endElementHandler(name);
-}
-
-status_t MediaCodecList::includeXMLFile(const char **attrs) {
-    const char *href = NULL;
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "href")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            href = attrs[i + 1];
-            ++i;
-        } else {
-            return -EINVAL;
-        }
-        ++i;
-    }
-
-    // For security reasons and for simplicity, file names can only contain
-    // [a-zA-Z0-9_.] and must start with  media_codecs_ and end with .xml
-    for (i = 0; href[i] != '\0'; i++) {
-        if (href[i] == '.' || href[i] == '_' ||
-                (href[i] >= '0' && href[i] <= '9') ||
-                (href[i] >= 'A' && href[i] <= 'Z') ||
-                (href[i] >= 'a' && href[i] <= 'z')) {
-            continue;
-        }
-        ALOGE("invalid include file name: %s", href);
-        return -EINVAL;
-    }
-
-    AString filename = href;
-    if (!filename.startsWith("media_codecs_") ||
-        !filename.endsWith(".xml")) {
-        ALOGE("invalid include file name: %s", href);
-        return -EINVAL;
-    }
-    filename.insert(mHrefBase, 0);
-
-    parseXMLFile(filename.c_str());
-    return mInitCheck;
-}
-
-void MediaCodecList::startElementHandler(
-        const char *name, const char **attrs) {
-    if (mInitCheck != OK) {
-        return;
-    }
-
-    bool inType = true;
-
-    if (!strcmp(name, "Include")) {
-        mInitCheck = includeXMLFile(attrs);
-        if (mInitCheck == OK) {
-            mPastSections.push(mCurrentSection);
-            mCurrentSection = SECTION_INCLUDE;
-        }
-        ++mDepth;
-        return;
-    }
-
-    switch (mCurrentSection) {
-        case SECTION_TOPLEVEL:
-        {
-            if (!strcmp(name, "Decoders")) {
-                mCurrentSection = SECTION_DECODERS;
-            } else if (!strcmp(name, "Encoders")) {
-                mCurrentSection = SECTION_ENCODERS;
-            } else if (!strcmp(name, "Settings")) {
-                mCurrentSection = SECTION_SETTINGS;
-            }
-            break;
-        }
-
-        case SECTION_SETTINGS:
-        {
-            if (!strcmp(name, "Setting")) {
-                mInitCheck = addSettingFromAttributes(attrs);
-            }
-            break;
-        }
-
-        case SECTION_DECODERS:
-        {
-            if (!strcmp(name, "MediaCodec")) {
-                mInitCheck =
-                    addMediaCodecFromAttributes(false /* encoder */, attrs);
-
-                mCurrentSection = SECTION_DECODER;
-            }
-            break;
-        }
-
-        case SECTION_ENCODERS:
-        {
-            if (!strcmp(name, "MediaCodec")) {
-                mInitCheck =
-                    addMediaCodecFromAttributes(true /* encoder */, attrs);
-
-                mCurrentSection = SECTION_ENCODER;
-            }
-            break;
-        }
-
-        case SECTION_DECODER:
-        case SECTION_ENCODER:
-        {
-            if (!strcmp(name, "Quirk")) {
-                mInitCheck = addQuirk(attrs);
-            } else if (!strcmp(name, "Type")) {
-                mInitCheck = addTypeFromAttributes(attrs);
-                mCurrentSection =
-                    (mCurrentSection == SECTION_DECODER
-                            ? SECTION_DECODER_TYPE : SECTION_ENCODER_TYPE);
-            }
-        }
-        inType = false;
-        // fall through
-
-        case SECTION_DECODER_TYPE:
-        case SECTION_ENCODER_TYPE:
-        {
-            // ignore limits and features specified outside of type
-            bool outside = !inType && !mCurrentInfo->mHasSoleMime;
-            if (outside && (!strcmp(name, "Limit") || !strcmp(name, "Feature"))) {
-                ALOGW("ignoring %s specified outside of a Type", name);
-            } else if (!strcmp(name, "Limit")) {
-                mInitCheck = addLimit(attrs);
-            } else if (!strcmp(name, "Feature")) {
-                mInitCheck = addFeature(attrs);
-            }
-            break;
-        }
-
-        default:
-            break;
-    }
-
-    ++mDepth;
-}
-
-void MediaCodecList::endElementHandler(const char *name) {
-    if (mInitCheck != OK) {
-        return;
-    }
-
-    switch (mCurrentSection) {
-        case SECTION_SETTINGS:
-        {
-            if (!strcmp(name, "Settings")) {
-                mCurrentSection = SECTION_TOPLEVEL;
-            }
-            break;
-        }
-
-        case SECTION_DECODERS:
-        {
-            if (!strcmp(name, "Decoders")) {
-                mCurrentSection = SECTION_TOPLEVEL;
-            }
-            break;
-        }
-
-        case SECTION_ENCODERS:
-        {
-            if (!strcmp(name, "Encoders")) {
-                mCurrentSection = SECTION_TOPLEVEL;
-            }
-            break;
-        }
-
-        case SECTION_DECODER_TYPE:
-        case SECTION_ENCODER_TYPE:
-        {
-            if (!strcmp(name, "Type")) {
-                mCurrentSection =
-                    (mCurrentSection == SECTION_DECODER_TYPE
-                            ? SECTION_DECODER : SECTION_ENCODER);
-
-                mCurrentInfo->complete();
-            }
-            break;
-        }
-
-        case SECTION_DECODER:
-        {
-            if (!strcmp(name, "MediaCodec")) {
-                mCurrentSection = SECTION_DECODERS;
-                mCurrentInfo->complete();
-                mCurrentInfo = NULL;
-            }
-            break;
-        }
-
-        case SECTION_ENCODER:
-        {
-            if (!strcmp(name, "MediaCodec")) {
-                mCurrentSection = SECTION_ENCODERS;
-                mCurrentInfo->complete();;
-                mCurrentInfo = NULL;
-            }
-            break;
-        }
-
-        case SECTION_INCLUDE:
-        {
-            if (!strcmp(name, "Include") && mPastSections.size() > 0) {
-                mCurrentSection = mPastSections.top();
-                mPastSections.pop();
-            }
-            break;
-        }
-
-        default:
-            break;
-    }
-
-    --mDepth;
-}
-
-status_t MediaCodecList::addSettingFromAttributes(const char **attrs) {
-    const char *name = NULL;
-    const char *value = NULL;
-    const char *update = NULL;
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "name")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            name = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "value")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            value = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "update")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            update = attrs[i + 1];
-            ++i;
-        } else {
-            return -EINVAL;
-        }
-
-        ++i;
-    }
-
-    if (name == NULL || value == NULL) {
-        return -EINVAL;
-    }
-
-    mUpdate = (update != NULL) && parseBoolean(update);
-    if (mUpdate != mGlobalSettings->contains(name)) {
-        return -EINVAL;
-    }
-
-    mGlobalSettings->setString(name, value);
-    return OK;
-}
-
-void MediaCodecList::setCurrentCodecInfo(bool encoder, const char *name, const char *type) {
-    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
-        if (AString(name) == mCodecInfos[i]->getCodecName()) {
-            if (mCodecInfos[i]->getCapabilitiesFor(type) == NULL) {
-                ALOGW("Overrides with an unexpected mime %s", type);
-                // Create a new MediaCodecInfo (but don't add it to mCodecInfos) to hold the
-                // overrides we don't want.
-                mCurrentInfo = new MediaCodecInfo(name, encoder, type);
-            } else {
-                mCurrentInfo = mCodecInfos.editItemAt(i);
-                mCurrentInfo->updateMime(type);  // to set the current cap
-            }
-            return;
-        }
-    }
-    mCurrentInfo = new MediaCodecInfo(name, encoder, type);
-    // The next step involves trying to load the codec, which may
-    // fail.  Only list the codec if this succeeds.
-    // However, keep mCurrentInfo object around until parsing
-    // of full codec info is completed.
-    if (initializeCapabilities(type) == OK) {
-        mCodecInfos.push_back(mCurrentInfo);
-    }
-}
-
-status_t MediaCodecList::addMediaCodecFromAttributes(
-        bool encoder, const char **attrs) {
-    const char *name = NULL;
-    const char *type = NULL;
-    const char *update = NULL;
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "name")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            name = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "type")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            type = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "update")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            update = attrs[i + 1];
-            ++i;
-        } else {
-            return -EINVAL;
-        }
-
-        ++i;
-    }
-
-    if (name == NULL) {
-        return -EINVAL;
-    }
-
-    mUpdate = (update != NULL) && parseBoolean(update);
-    ssize_t index = -1;
-    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
-        if (AString(name) == mCodecInfos[i]->getCodecName()) {
-            index = i;
-        }
-    }
-    if (mUpdate != (index >= 0)) {
-        return -EINVAL;
-    }
-
-    if (index >= 0) {
-        // existing codec
-        mCurrentInfo = mCodecInfos.editItemAt(index);
-        if (type != NULL) {
-            // existing type
-            if (mCodecInfos[index]->getCapabilitiesFor(type) == NULL) {
-                return -EINVAL;
-            }
-            mCurrentInfo->updateMime(type);
-        }
-    } else {
-        // new codec
-        mCurrentInfo = new MediaCodecInfo(name, encoder, type);
-        // The next step involves trying to load the codec, which may
-        // fail.  Only list the codec if this succeeds.
-        // However, keep mCurrentInfo object around until parsing
-        // of full codec info is completed.
-        if (initializeCapabilities(type) == OK) {
-            mCodecInfos.push_back(mCurrentInfo);
-        }
-    }
-
-    return OK;
-}
-
-status_t MediaCodecList::initializeCapabilities(const char *type) {
-    if (type == NULL) {
-        return OK;
-    }
-
-    ALOGV("initializeCapabilities %s:%s",
-            mCurrentInfo->mName.c_str(), type);
-
-    sp<MediaCodecInfo::Capabilities> caps;
-    status_t err = MediaCodec::QueryCapabilities(
-            mCurrentInfo->mName,
-            type,
-            mCurrentInfo->mIsEncoder,
-            &caps);
-    if (err != OK) {
-        return err;
-    } else if (caps == NULL) {
-        ALOGE("MediaCodec::QueryCapabilities returned OK but no capabilities for '%s':'%s':'%s'",
-                mCurrentInfo->mName.c_str(), type,
-                mCurrentInfo->mIsEncoder ? "encoder" : "decoder");
-        return UNKNOWN_ERROR;
-    }
-
-    return mCurrentInfo->initializeCapabilities(caps);
-}
-
-status_t MediaCodecList::addQuirk(const char **attrs) {
-    const char *name = NULL;
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "name")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            name = attrs[i + 1];
-            ++i;
-        } else {
-            return -EINVAL;
-        }
-
-        ++i;
-    }
-
-    if (name == NULL) {
-        return -EINVAL;
-    }
-
-    mCurrentInfo->addQuirk(name);
-    return OK;
-}
-
-status_t MediaCodecList::addTypeFromAttributes(const char **attrs) {
-    const char *name = NULL;
-    const char *update = NULL;
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "name")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            name = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "update")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            update = attrs[i + 1];
-            ++i;
-        } else {
-            return -EINVAL;
-        }
-
-        ++i;
-    }
-
-    if (name == NULL) {
-        return -EINVAL;
-    }
-
-    bool isExistingType = (mCurrentInfo->getCapabilitiesFor(name) != NULL);
-    if (mUpdate != isExistingType) {
-        return -EINVAL;
-    }
-
-    status_t ret;
-    if (mUpdate) {
-        ret = mCurrentInfo->updateMime(name);
-    } else {
-        ret = mCurrentInfo->addMime(name);
-    }
-
-    if (ret != OK) {
-        return ret;
-    }
-
-    // The next step involves trying to load the codec, which may
-    // fail.  Handle this gracefully (by not reporting such mime).
-    if (!mUpdate && initializeCapabilities(name) != OK) {
-        mCurrentInfo->removeMime(name);
-    }
-    return OK;
+std::unique_ptr<MediaCodecInfoWriter>
+        MediaCodecListWriter::addMediaCodecInfo() {
+    sp<MediaCodecInfo> info = new MediaCodecInfo();
+    mList->mCodecInfos.push_back(info);
+    return std::unique_ptr<MediaCodecInfoWriter>(
+            new MediaCodecInfoWriter(info.get()));
 }
 
 // legacy method for non-advanced codecs
@@ -882,15 +210,15 @@
         "feature-tunneled-playback",
     };
 
-    size_t numCodecs = mCodecInfos.size();
-    for (; startIndex < numCodecs; ++startIndex) {
-        const MediaCodecInfo &info = *mCodecInfos.itemAt(startIndex).get();
+    size_t numCodecInfos = mCodecInfos.size();
+    for (; startIndex < numCodecInfos; ++startIndex) {
+        const MediaCodecInfo &info = *mCodecInfos[startIndex];
 
         if (info.isEncoder() != encoder) {
             continue;
         }
         sp<MediaCodecInfo::Capabilities> capabilities = info.getCapabilitiesFor(type);
-        if (capabilities == NULL) {
+        if (capabilities == nullptr) {
             continue;
         }
         const sp<AMessage> &details = capabilities->getDetails();
@@ -913,223 +241,9 @@
     return -ENOENT;
 }
 
-static status_t limitFoundMissingAttr(const AString &name, const char *attr, bool found = true) {
-    ALOGE("limit '%s' with %s'%s' attribute", name.c_str(),
-            (found ? "" : "no "), attr);
-    return -EINVAL;
-}
-
-static status_t limitError(const AString &name, const char *msg) {
-    ALOGE("limit '%s' %s", name.c_str(), msg);
-    return -EINVAL;
-}
-
-static status_t limitInvalidAttr(const AString &name, const char *attr, const AString &value) {
-    ALOGE("limit '%s' with invalid '%s' attribute (%s)", name.c_str(),
-            attr, value.c_str());
-    return -EINVAL;
-}
-
-status_t MediaCodecList::addLimit(const char **attrs) {
-    sp<AMessage> msg = new AMessage();
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (attrs[i + 1] == NULL) {
-            return -EINVAL;
-        }
-
-        // attributes with values
-        if (!strcmp(attrs[i], "name")
-                || !strcmp(attrs[i], "default")
-                || !strcmp(attrs[i], "in")
-                || !strcmp(attrs[i], "max")
-                || !strcmp(attrs[i], "min")
-                || !strcmp(attrs[i], "range")
-                || !strcmp(attrs[i], "ranges")
-                || !strcmp(attrs[i], "scale")
-                || !strcmp(attrs[i], "value")) {
-            msg->setString(attrs[i], attrs[i + 1]);
-            ++i;
-        } else {
-            return -EINVAL;
-        }
-        ++i;
-    }
-
-    AString name;
-    if (!msg->findString("name", &name)) {
-        ALOGE("limit with no 'name' attribute");
-        return -EINVAL;
-    }
-
-    // size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio,
-    // measured-frame-rate, measured-blocks-per-second: range
-    // quality: range + default + [scale]
-    // complexity: range + default
-    bool found;
-
-    if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
-            || name == "blocks-per-second" || name == "complexity"
-            || name == "frame-rate" || name == "quality" || name == "size"
-            || name == "measured-blocks-per-second" || name.startsWith("measured-frame-rate-")) {
-        AString min, max;
-        if (msg->findString("min", &min) && msg->findString("max", &max)) {
-            min.append("-");
-            min.append(max);
-            if (msg->contains("range") || msg->contains("value")) {
-                return limitError(name, "has 'min' and 'max' as well as 'range' or "
-                        "'value' attributes");
-            }
-            msg->setString("range", min);
-        } else if (msg->contains("min") || msg->contains("max")) {
-            return limitError(name, "has only 'min' or 'max' attribute");
-        } else if (msg->findString("value", &max)) {
-            min = max;
-            min.append("-");
-            min.append(max);
-            if (msg->contains("range")) {
-                return limitError(name, "has both 'range' and 'value' attributes");
-            }
-            msg->setString("range", min);
-        }
-
-        AString range, scale = "linear", def, in_;
-        if (!msg->findString("range", &range)) {
-            return limitError(name, "with no 'range', 'value' or 'min'/'max' attributes");
-        }
-
-        if ((name == "quality" || name == "complexity") ^
-                (found = msg->findString("default", &def))) {
-            return limitFoundMissingAttr(name, "default", found);
-        }
-        if (name != "quality" && msg->findString("scale", &scale)) {
-            return limitFoundMissingAttr(name, "scale");
-        }
-        if ((name == "aspect-ratio") ^ (found = msg->findString("in", &in_))) {
-            return limitFoundMissingAttr(name, "in", found);
-        }
-
-        if (name == "aspect-ratio") {
-            if (!(in_ == "pixels") && !(in_ == "blocks")) {
-                return limitInvalidAttr(name, "in", in_);
-            }
-            in_.erase(5, 1); // (pixel|block)-aspect-ratio
-            in_.append("-");
-            in_.append(name);
-            name = in_;
-        }
-        if (name == "quality") {
-            mCurrentInfo->addDetail("quality-scale", scale);
-        }
-        if (name == "quality" || name == "complexity") {
-            AString tag = name;
-            tag.append("-default");
-            mCurrentInfo->addDetail(tag, def);
-        }
-        AString tag = name;
-        tag.append("-range");
-        mCurrentInfo->addDetail(tag, range);
-    } else {
-        AString max, value, ranges;
-        if (msg->contains("default")) {
-            return limitFoundMissingAttr(name, "default");
-        } else if (msg->contains("in")) {
-            return limitFoundMissingAttr(name, "in");
-        } else if ((name == "channel-count" || name == "concurrent-instances") ^
-                (found = msg->findString("max", &max))) {
-            return limitFoundMissingAttr(name, "max", found);
-        } else if (msg->contains("min")) {
-            return limitFoundMissingAttr(name, "min");
-        } else if (msg->contains("range")) {
-            return limitFoundMissingAttr(name, "range");
-        } else if ((name == "sample-rate") ^
-                (found = msg->findString("ranges", &ranges))) {
-            return limitFoundMissingAttr(name, "ranges", found);
-        } else if (msg->contains("scale")) {
-            return limitFoundMissingAttr(name, "scale");
-        } else if ((name == "alignment" || name == "block-size") ^
-                (found = msg->findString("value", &value))) {
-            return limitFoundMissingAttr(name, "value", found);
-        }
-
-        if (max.size()) {
-            AString tag = "max-";
-            tag.append(name);
-            mCurrentInfo->addDetail(tag, max);
-        } else if (value.size()) {
-            mCurrentInfo->addDetail(name, value);
-        } else if (ranges.size()) {
-            AString tag = name;
-            tag.append("-ranges");
-            mCurrentInfo->addDetail(tag, ranges);
-        } else {
-            ALOGW("Ignoring unrecognized limit '%s'", name.c_str());
-        }
-    }
-    return OK;
-}
-
-status_t MediaCodecList::addFeature(const char **attrs) {
-    size_t i = 0;
-    const char *name = NULL;
-    int32_t optional = -1;
-    int32_t required = -1;
-    const char *value = NULL;
-
-    while (attrs[i] != NULL) {
-        if (attrs[i + 1] == NULL) {
-            return -EINVAL;
-        }
-
-        // attributes with values
-        if (!strcmp(attrs[i], "name")) {
-            name = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "optional") || !strcmp(attrs[i], "required")) {
-            int value = (int)parseBoolean(attrs[i + 1]);
-            if (!strcmp(attrs[i], "optional")) {
-                optional = value;
-            } else {
-                required = value;
-            }
-            ++i;
-        } else if (!strcmp(attrs[i], "value")) {
-            value = attrs[i + 1];
-            ++i;
-        } else {
-            return -EINVAL;
-        }
-        ++i;
-    }
-    if (name == NULL) {
-        ALOGE("feature with no 'name' attribute");
-        return -EINVAL;
-    }
-
-    if (optional == required && optional != -1) {
-        ALOGE("feature '%s' is both/neither optional and required", name);
-        return -EINVAL;
-    }
-
-    if ((optional != -1 || required != -1) && (value != NULL)) {
-        ALOGE("feature '%s' has both a value and optional/required attribute", name);
-        return -EINVAL;
-    }
-
-    if (value != NULL) {
-        mCurrentInfo->addFeature(name, value);
-    } else {
-        mCurrentInfo->addFeature(name, (required == 1) || (optional == 0));
-    }
-    return OK;
-}
-
 ssize_t MediaCodecList::findCodecByName(const char *name) const {
     for (size_t i = 0; i < mCodecInfos.size(); ++i) {
-        const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get();
-
-        if (info.mName == name) {
+        if (strcmp(mCodecInfos[i]->getCodecName(), name) == 0) {
             return i;
         }
     }
@@ -1167,11 +281,15 @@
 
 //static
 void MediaCodecList::findMatchingCodecs(
-        const char *mime, bool encoder, uint32_t flags, Vector<AString> *matches) {
+        const char *mime, bool encoder, uint32_t flags,
+        Vector<AString> *matches, Vector<AString> *owners) {
     matches->clear();
+    if (owners != nullptr) {
+        owners->clear();
+    }
 
     const sp<IMediaCodecList> list = getInstance();
-    if (list == NULL) {
+    if (list == nullptr) {
         return;
     }
 
@@ -1187,45 +305,27 @@
         index = matchIndex + 1;
 
         const sp<MediaCodecInfo> info = list->getCodecInfo(matchIndex);
-        CHECK(info != NULL);
+        CHECK(info != nullptr);
         AString componentName = info->getCodecName();
 
         if ((flags & kHardwareCodecsOnly) && isSoftwareCodec(componentName)) {
             ALOGV("skipping SW codec '%s'", componentName.c_str());
         } else {
             matches->push(componentName);
+            if (owners != nullptr) {
+                owners->push(AString(info->getOwnerName()));
+            }
             ALOGV("matching '%s'", componentName.c_str());
         }
     }
 
-    if (flags & kPreferSoftwareCodecs || property_get_bool("debug.stagefright.swcodec", false)) {
+    if (flags & kPreferSoftwareCodecs ||
+            property_get_bool("debug.stagefright.swcodec", false)) {
         matches->sort(compareSoftwareCodecsFirst);
     }
 }
 
-// static
-uint32_t MediaCodecList::getQuirksFor(const char *componentName) {
-    const sp<IMediaCodecList> list = getInstance();
-    if (list == NULL) {
-        return 0;
-    }
-
-    ssize_t ix = list->findCodecByName(componentName);
-    if (ix < 0) {
-        return 0;
-    }
-
-    const sp<MediaCodecInfo> info = list->getCodecInfo(ix);
-
-    uint32_t quirks = 0;
-    if (info->hasQuirk("requires-allocate-on-input-ports")) {
-        quirks |= ACodec::kRequiresAllocateBufferOnInputPorts;
-    }
-    if (info->hasQuirk("requires-allocate-on-output-ports")) {
-        quirks |= ACodec::kRequiresAllocateBufferOnOutputPorts;
-    }
-
-    return quirks;
+MediaCodecListBuilderBase::~MediaCodecListBuilderBase() {
 }
 
 }  // namespace android
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index 095fc6a..6920e51 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -33,8 +33,6 @@
 
 namespace android {
 
-const char *kProfilingResults = "/data/misc/media/media_codecs_profiling_results.xml";
-
 AString getProfilingVersionString() {
     char val[PROPERTY_VALUE_MAX];
     if (property_get("ro.build.display.id", val, NULL) && (strlen(val) > 0)) {
@@ -205,24 +203,24 @@
     return true;
 }
 
-void profileCodecs(const Vector<sp<MediaCodecInfo>> &infos) {
+void profileCodecs(const std::vector<sp<MediaCodecInfo>> &infos,
+        const char* profilingResults) {
     CodecSettings global_results;
     KeyedVector<AString, CodecSettings> encoder_results;
     KeyedVector<AString, CodecSettings> decoder_results;
     profileCodecs(infos, &global_results, &encoder_results, &decoder_results);
-    exportResultsToXML(kProfilingResults, global_results, encoder_results, decoder_results);
+    exportResultsToXML(profilingResults, global_results, encoder_results, decoder_results);
 }
 
 void profileCodecs(
-        const Vector<sp<MediaCodecInfo>> &infos,
+        const std::vector<sp<MediaCodecInfo>> &infos,
         CodecSettings *global_results,
         KeyedVector<AString, CodecSettings> *encoder_results,
         KeyedVector<AString, CodecSettings> *decoder_results,
         bool forceToMeasure) {
     KeyedVector<AString, sp<MediaCodecInfo::Capabilities>> codecsNeedMeasure;
     AString supportMultipleSecureCodecs = "true";
-    for (size_t i = 0; i < infos.size(); ++i) {
-        const sp<MediaCodecInfo> info = infos[i];
+    for (const auto& info : infos) {
         AString name = info->getCodecName();
         if (name.startsWith("OMX.google.") ||
                 // TODO: reenable below codecs once fixed
diff --git a/media/libstagefright/MediaCodecListOverrides.h b/media/libstagefright/MediaCodecListOverrides.h
index d4bb225..4f8c2f5 100644
--- a/media/libstagefright/MediaCodecListOverrides.h
+++ b/media/libstagefright/MediaCodecListOverrides.h
@@ -23,12 +23,10 @@
 
 #include <utils/StrongPointer.h>
 #include <utils/KeyedVector.h>
+#include <vector>
 
 namespace android {
 
-extern const char *kProfilingVersionString;
-extern const char *kProfilingResults;
-
 struct MediaCodecInfo;
 
 AString getProfilingVersionString();
@@ -36,11 +34,12 @@
 bool splitString(const AString &s, const AString &delimiter, AString *s1, AString *s2);
 
 // profile codecs and save the result to xml file named kProfilingResults.
-void profileCodecs(const Vector<sp<MediaCodecInfo>> &infos);
+void profileCodecs(const std::vector<sp<MediaCodecInfo>> &infos,
+        const char* profilingResults);
 
 // profile codecs and save the result to global_results, encoder_results and decoder_results.
 void profileCodecs(
-        const Vector<sp<MediaCodecInfo>> &infos,
+        const std::vector<sp<MediaCodecInfo>> &infos,
         CodecSettings *global_results,
         KeyedVector<AString, CodecSettings> *encoder_results,
         KeyedVector<AString, CodecSettings> *decoder_results,
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 51f1ba3..640cb82 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
 #define LOG_TAG "NuMediaExtractor"
 #include <utils/Log.h>
 
@@ -35,7 +35,6 @@
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
-#include <android/media/ICas.h>
 
 namespace android {
 
@@ -83,8 +82,8 @@
         return ERROR_UNSUPPORTED;
     }
 
-    if (mCas != NULL) {
-        mImpl->setMediaCas(mCas);
+    if (!mCasToken.empty()) {
+        mImpl->setMediaCas(mCasToken);
     }
 
     status_t err = updateDurationAndBitrate();
@@ -119,8 +118,8 @@
         return ERROR_UNSUPPORTED;
     }
 
-    if (mCas != NULL) {
-        mImpl->setMediaCas(mCas);
+    if (!mCasToken.empty()) {
+        mImpl->setMediaCas(mCasToken);
     }
 
     err = updateDurationAndBitrate();
@@ -149,8 +148,8 @@
         return ERROR_UNSUPPORTED;
     }
 
-    if (mCas != NULL) {
-        mImpl->setMediaCas(mCas);
+    if (!mCasToken.empty()) {
+        mImpl->setMediaCas(mCasToken);
     }
 
     err = updateDurationAndBitrate();
@@ -161,24 +160,36 @@
     return err;
 }
 
-status_t NuMediaExtractor::setMediaCas(const sp<ICas> &cas) {
-    ALOGV("setMediaCas: cas=%p", cas.get());
+static String8 arrayToString(const std::vector<uint8_t> &array) {
+    String8 result;
+    for (size_t i = 0; i < array.size(); i++) {
+        result.appendFormat("%02x ", array[i]);
+    }
+    if (result.isEmpty()) {
+        result.append("(null)");
+    }
+    return result;
+}
+
+status_t NuMediaExtractor::setMediaCas(const HInterfaceToken &casToken) {
+    ALOGV("setMediaCas: casToken={%s}", arrayToString(casToken).c_str());
 
     Mutex::Autolock autoLock(mLock);
 
-    if (cas == NULL) {
+    if (casToken.empty()) {
         return BAD_VALUE;
     }
 
+    mCasToken = casToken;
+
     if (mImpl != NULL) {
-        mImpl->setMediaCas(cas);
+        mImpl->setMediaCas(casToken);
         status_t err = updateDurationAndBitrate();
         if (err != OK) {
             return err;
         }
     }
 
-    mCas = cas;
     return OK;
 }
 
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 5f9aa01..5f50e46 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -38,7 +38,7 @@
 }
 
 status_t OMXClient::connect() {
-    return connect(nullptr);
+    return connect("default", nullptr);
 }
 
 status_t OMXClient::connect(bool* trebleFlag) {
@@ -54,6 +54,19 @@
     return connectLegacy();
 }
 
+status_t OMXClient::connect(const char* name, bool* trebleFlag) {
+    if (property_get_bool("persist.media.treble_omx", true)) {
+        if (trebleFlag != nullptr) {
+            *trebleFlag = true;
+        }
+        return connectTreble(name);
+    }
+    if (trebleFlag != nullptr) {
+        *trebleFlag = false;
+    }
+    return connectLegacy();
+}
+
 status_t OMXClient::connectLegacy() {
     sp<IServiceManager> sm = defaultServiceManager();
     sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
@@ -73,9 +86,12 @@
     return OK;
 }
 
-status_t OMXClient::connectTreble() {
+status_t OMXClient::connectTreble(const char* name) {
     using namespace ::android::hardware::media::omx::V1_0;
-    sp<IOmx> tOmx = IOmx::getService("default");
+    if (name == nullptr) {
+        name = "default";
+    }
+    sp<IOmx> tOmx = IOmx::getService(name);
     if (tOmx.get() == nullptr) {
         ALOGE("Cannot obtain Treble IOmx.");
         return NO_INIT;
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
new file mode 100644
index 0000000..8717a79
--- /dev/null
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OmxInfoBuilder"
+
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
+#include <utils/Log.h>
+#include <cutils/properties.h>
+
+#include <binder/IServiceManager.h>
+#include <media/IMediaCodecService.h>
+#include <media/stagefright/OmxInfoBuilder.h>
+#include <media/stagefright/ACodec.h>
+
+#include <android/hardware/media/omx/1.0/IOmxStore.h>
+#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
+#include <media/stagefright/omx/OMXUtils.h>
+
+#include <media/IOMXStore.h>
+#include <media/IOMX.h>
+#include <media/MediaDefs.h>
+#include <media/omx/1.0/WOmx.h>
+
+#include <media/openmax/OMX_Index.h>
+#include <media/openmax/OMX_IndexExt.h>
+#include <media/openmax/OMX_Audio.h>
+#include <media/openmax/OMX_AudioExt.h>
+#include <media/openmax/OMX_Video.h>
+#include <media/openmax/OMX_VideoExt.h>
+
+namespace android {
+
+namespace /* unnamed */ {
+
+status_t queryCapabilities(
+        const IOMXStore::NodeInfo& node, const char* mime, bool isEncoder,
+        MediaCodecInfo::CapabilitiesWriter* caps) {
+    sp<ACodec> codec = new ACodec();
+    status_t err = codec->queryCapabilities(
+            node.owner.c_str(), node.name.c_str(), mime, isEncoder, caps);
+    if (err != OK) {
+        return err;
+    }
+    for (const auto& attribute : node.attributes) {
+        // All features have an int32 value except
+        // "feature-bitrate-modes", which has a string value.
+        if ((attribute.key.compare(0, 8, "feature-") == 0) &&
+                (attribute.key.compare(8, 15, "bitrate-modes")
+                 != 0)) {
+            // If this attribute.key is a feature that is not a bitrate
+            // control, add an int32 value.
+            caps->addDetail(
+                    attribute.key.c_str(),
+                    attribute.value == "1" ? 1 : 0);
+        } else {
+            // Non-feature attributes
+            caps->addDetail(
+                    attribute.key.c_str(), attribute.value.c_str());
+        }
+    }
+    return OK;
+}
+
+}  // unnamed namespace
+
+OmxInfoBuilder::OmxInfoBuilder() {
+}
+
+status_t OmxInfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
+    bool treble;
+    sp<IOMX> omx;
+    std::vector<IOMXStore::RoleInfo> roles;
+
+    treble = property_get_bool("persist.media.treble_omx", true);
+    if (treble) {
+        using namespace ::android::hardware::media::omx::V1_0;
+        using ::android::hardware::hidl_vec;
+        using ::android::hardware::hidl_string;
+
+        // Obtain IOmxStore
+        sp<IOmxStore> omxStore = IOmxStore::getService();
+        if (omxStore == nullptr) {
+            ALOGE("Cannot connect to an IOmxStore instance.");
+            return NO_INIT;
+        }
+
+        // List service attributes (global settings)
+        Status status;
+        hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
+        auto transStatus = omxStore->listServiceAttributes(
+                [&status, &serviceAttributes]
+                (Status inStatus, const hidl_vec<IOmxStore::ServiceAttribute>&
+                        inAttributes) {
+                    status = inStatus;
+                    serviceAttributes = inAttributes;
+                });
+        if (!transStatus.isOk()) {
+            ALOGE("Fail to obtain global settings from IOmxStore.");
+            return NO_INIT;
+        }
+        if (status != Status::OK) {
+            ALOGE("IOmxStore reports parsing error.");
+            return NO_INIT;
+        }
+        for (const auto& p : serviceAttributes) {
+            writer->addGlobalSetting(
+                    p.key.c_str(), p.value.c_str());
+        }
+
+        // List roles and convert to IOMXStore's format
+        transStatus = omxStore->listRoles(
+                [&roles]
+                (const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
+                    roles.reserve(inRoleList.size());
+                    for (const auto& inRole : inRoleList) {
+                        IOMXStore::RoleInfo role;
+                        role.role = inRole.role;
+                        role.type = inRole.type;
+                        role.isEncoder = inRole.isEncoder;
+                        role.preferPlatformNodes = inRole.preferPlatformNodes;
+                        std::vector<IOMXStore::NodeInfo>& nodes =
+                                role.nodes;
+                        nodes.reserve(inRole.nodes.size());
+                        for (const auto& inNode : inRole.nodes) {
+                            IOMXStore::NodeInfo node;
+                            node.name = inNode.name;
+                            node.owner = inNode.owner;
+                            std::vector<IOMXStore::Attribute>& attributes =
+                                    node.attributes;
+                            attributes.reserve(inNode.attributes.size());
+                            for (const auto& inAttr : inNode.attributes) {
+                                IOMXStore::Attribute attr;
+                                attr.key = inAttr.key;
+                                attr.value = inAttr.value;
+                                attributes.push_back(std::move(attr));
+                            }
+                            nodes.push_back(std::move(node));
+                        }
+                        roles.push_back(std::move(role));
+                    }
+                });
+        if (!transStatus.isOk()) {
+            ALOGE("Fail to obtain codec roles from IOmxStore.");
+            return NO_INIT;
+        }
+    } else {
+        // Obtain IOMXStore
+        sp<IServiceManager> sm = defaultServiceManager();
+        if (sm == nullptr) {
+            ALOGE("Cannot obtain the default service manager.");
+            return NO_INIT;
+        }
+        sp<IBinder> codecBinder = sm->getService(String16("media.codec"));
+        if (codecBinder == nullptr) {
+            ALOGE("Cannot obtain the media codec service.");
+            return NO_INIT;
+        }
+        sp<IMediaCodecService> codecService =
+                interface_cast<IMediaCodecService>(codecBinder);
+        if (codecService == nullptr) {
+            ALOGE("Wrong type of media codec service obtained.");
+            return NO_INIT;
+        }
+        omx = codecService->getOMX();
+        if (omx == nullptr) {
+            ALOGE("Cannot connect to an IOMX instance.");
+        }
+        sp<IOMXStore> omxStore = codecService->getOMXStore();
+        if (omxStore == nullptr) {
+            ALOGE("Cannot connect to an IOMXStore instance.");
+            return NO_INIT;
+        }
+
+        // List service attributes (global settings)
+        std::vector<IOMXStore::Attribute> serviceAttributes;
+        status_t status = omxStore->listServiceAttributes(&serviceAttributes);
+        if (status != OK) {
+            ALOGE("Fail to obtain global settings from IOMXStore.");
+            return NO_INIT;
+        }
+        for (const auto& p : serviceAttributes) {
+            writer->addGlobalSetting(
+                    p.key.c_str(), p.value.c_str());
+        }
+
+        // List roles
+        status = omxStore->listRoles(&roles);
+        if (status != OK) {
+            ALOGE("Fail to obtain codec roles from IOMXStore.");
+            return NO_INIT;
+        }
+    }
+
+    // Convert roles to lists of codecs
+
+    // codec name -> index into swCodecs
+    std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
+            swCodecName2Info;
+    // codec name -> index into hwCodecs
+    std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
+            hwCodecName2Info;
+    // owner name -> MediaCodecInfo
+    // This map will be used to obtain the correct IOmx service(s) needed for
+    // creating IOmxNode instances and querying capabilities.
+    std::map<std::string, std::vector<sp<MediaCodecInfo> > >
+            owner2CodecInfo;
+
+    for (const auto& role : roles) {
+        const auto& typeName = role.type;
+        bool isEncoder = role.isEncoder;
+        bool preferPlatformNodes = role.preferPlatformNodes;
+        // If preferPlatformNodes is true, hardware nodes must be added after
+        // platform (software) nodes. hwCodecs is used to hold hardware nodes
+        // that need to be added after software nodes for the same role.
+        std::vector<const IOMXStore::NodeInfo*> hwCodecs;
+        for (const auto& node : role.nodes) {
+            const auto& nodeName = node.name;
+            bool isSoftware = nodeName.compare(0, 10, "OMX.google") == 0;
+            MediaCodecInfoWriter* info;
+            if (isSoftware) {
+                auto c2i = swCodecName2Info.find(nodeName);
+                if (c2i == swCodecName2Info.end()) {
+                    // Create a new MediaCodecInfo for a new node.
+                    c2i = swCodecName2Info.insert(std::make_pair(
+                            nodeName, writer->addMediaCodecInfo())).first;
+                    info = c2i->second.get();
+                    info->setName(nodeName.c_str());
+                    info->setOwner(node.owner.c_str());
+                    info->setEncoder(isEncoder);
+                } else {
+                    // The node has been seen before. Simply retrieve the
+                    // existing MediaCodecInfoWriter.
+                    info = c2i->second.get();
+                }
+            } else {
+                auto c2i = hwCodecName2Info.find(nodeName);
+                if (c2i == hwCodecName2Info.end()) {
+                    // Create a new MediaCodecInfo for a new node.
+                    if (!preferPlatformNodes) {
+                        c2i = hwCodecName2Info.insert(std::make_pair(
+                                nodeName, writer->addMediaCodecInfo())).first;
+                        info = c2i->second.get();
+                        info->setName(nodeName.c_str());
+                        info->setOwner(node.owner.c_str());
+                        info->setEncoder(isEncoder);
+                    } else {
+                        // If preferPlatformNodes is true, this node must be
+                        // added after all software nodes.
+                        hwCodecs.push_back(&node);
+                        continue;
+                    }
+                } else {
+                    // The node has been seen before. Simply retrieve the
+                    // existing MediaCodecInfoWriter.
+                    info = c2i->second.get();
+                }
+            }
+            std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
+                    info->addMime(typeName.c_str());
+            if (queryCapabilities(
+                    node, typeName.c_str(), isEncoder, caps.get()) != OK) {
+                ALOGW("Fail to add mime %s to codec %s",
+                        typeName.c_str(), nodeName.c_str());
+                info->removeMime(typeName.c_str());
+            }
+        }
+
+        // If preferPlatformNodes is true, hardware nodes will not have been
+        // added in the loop above, but rather saved in hwCodecs. They are
+        // going to be added here.
+        if (preferPlatformNodes) {
+            for (const auto& node : hwCodecs) {
+                MediaCodecInfoWriter* info;
+                const auto& nodeName = node->name;
+                auto c2i = hwCodecName2Info.find(nodeName);
+                if (c2i == hwCodecName2Info.end()) {
+                    // Create a new MediaCodecInfo for a new node.
+                    c2i = hwCodecName2Info.insert(std::make_pair(
+                            nodeName, writer->addMediaCodecInfo())).first;
+                    info = c2i->second.get();
+                    info->setName(nodeName.c_str());
+                    info->setOwner(node->owner.c_str());
+                    info->setEncoder(isEncoder);
+                } else {
+                    // The node has been seen before. Simply retrieve the
+                    // existing MediaCodecInfoWriter.
+                    info = c2i->second.get();
+                }
+                std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
+                        info->addMime(typeName.c_str());
+                if (queryCapabilities(
+                        *node, typeName.c_str(), isEncoder, caps.get()) != OK) {
+                    ALOGW("Fail to add mime %s to codec %s "
+                          "after software codecs",
+                          typeName.c_str(), nodeName.c_str());
+                    info->removeMime(typeName.c_str());
+                }
+            }
+        }
+    }
+    return OK;
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index f0c27ac..4ff2bfe 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -85,7 +85,8 @@
     status_t status;
     if (fd < 0) {
         // couldn't open it locally, maybe the media server can?
-        status = mRetriever->setDataSource(NULL /* httpService */, path);
+        sp<IMediaHTTPService> nullService;
+        status = mRetriever->setDataSource(nullService, path);
     } else {
         status = mRetriever->setDataSource(fd, 0, 0x7ffffffffffffffL);
         close(fd);
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 03dc9df..103da95 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -60,6 +60,12 @@
 StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
     ALOGV("~StagefrightMetadataRetriever()");
     clearMetadata();
+    // Explicitly release extractor before continuing with the destructor,
+    // some extractors might need to callback to close off the DataSource
+    // and we need to make sure it's still there.
+    if (mExtractor != NULL) {
+        mExtractor->release();
+    }
     if (mSource != NULL) {
         mSource->close();
     }
@@ -121,12 +127,12 @@
 }
 
 status_t StagefrightMetadataRetriever::setDataSource(
-        const sp<DataSource>& source) {
+        const sp<DataSource>& source, const char *mime) {
     ALOGV("setDataSource(DataSource)");
 
     clearMetadata();
     mSource = source;
-    mExtractor = MediaExtractor::Create(mSource);
+    mExtractor = MediaExtractor::Create(mSource, mime);
 
     if (mExtractor == NULL) {
         ALOGE("Failed to instantiate a MediaExtractor.");
@@ -137,17 +143,173 @@
     return OK;
 }
 
+static VideoFrame *allocVideoFrame(
+        const sp<MetaData> &trackMeta, int32_t width, int32_t height, int32_t bpp, bool metaOnly) {
+    int32_t rotationAngle;
+    if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
+        rotationAngle = 0;  // By default, no rotation
+    }
+
+    uint32_t type;
+    const void *iccData;
+    size_t iccSize;
+    if (!trackMeta->findData(kKeyIccProfile, &type, &iccData, &iccSize)){
+        iccData = NULL;
+        iccSize = 0;
+    }
+
+    int32_t sarWidth, sarHeight;
+    int32_t displayWidth, displayHeight;
+    if (trackMeta->findInt32(kKeySARWidth, &sarWidth)
+            && trackMeta->findInt32(kKeySARHeight, &sarHeight)
+            && sarHeight != 0) {
+        displayWidth = (width * sarWidth) / sarHeight;
+        displayHeight = height;
+    } else if (trackMeta->findInt32(kKeyDisplayWidth, &displayWidth)
+                && trackMeta->findInt32(kKeyDisplayHeight, &displayHeight)
+                && displayWidth > 0 && displayHeight > 0
+                && width > 0 && height > 0) {
+        ALOGV("found display size %dx%d", displayWidth, displayHeight);
+    } else {
+        displayWidth = width;
+        displayHeight = height;
+    }
+
+    return new VideoFrame(width, height, displayWidth, displayHeight,
+            rotationAngle, bpp, !metaOnly, iccData, iccSize);
+}
+
+static bool getDstColorFormat(android_pixel_format_t colorFormat,
+        OMX_COLOR_FORMATTYPE *omxColorFormat, int32_t *bpp) {
+    switch (colorFormat) {
+        case HAL_PIXEL_FORMAT_RGB_565:
+        {
+            *omxColorFormat = OMX_COLOR_Format16bitRGB565;
+            *bpp = 2;
+            return true;
+        }
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        {
+            *omxColorFormat = OMX_COLOR_Format32BitRGBA8888;
+            *bpp = 4;
+            return true;
+        }
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        {
+            *omxColorFormat = OMX_COLOR_Format32bitBGRA8888;
+            *bpp = 4;
+            return true;
+        }
+        default:
+        {
+            ALOGE("Unsupported color format: %d", colorFormat);
+            break;
+        }
+    }
+    return false;
+}
+
 static VideoFrame *extractVideoFrame(
         const AString &componentName,
         const sp<MetaData> &trackMeta,
         const sp<IMediaSource> &source,
         int64_t frameTimeUs,
-        int seekMode) {
-
+        int seekMode,
+        int colorFormat,
+        bool metaOnly) {
     sp<MetaData> format = source->getFormat();
 
+    MediaSource::ReadOptions::SeekMode mode =
+            static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
+    if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC ||
+        seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) {
+        ALOGE("Unknown seek mode: %d", seekMode);
+        return NULL;
+    }
+
+    int32_t dstBpp;
+    OMX_COLOR_FORMATTYPE dstFormat;
+    if (!getDstColorFormat(
+            (android_pixel_format_t)colorFormat, &dstFormat, &dstBpp)) {
+        return NULL;
+    }
+
+    if (metaOnly) {
+        int32_t width, height;
+        CHECK(trackMeta->findInt32(kKeyWidth, &width));
+        CHECK(trackMeta->findInt32(kKeyHeight, &height));
+        return allocVideoFrame(trackMeta, width, height, dstBpp, true);
+    }
+
+    MediaSource::ReadOptions options;
+    sp<MetaData> overrideMeta;
+    if (frameTimeUs < 0) {
+        uint32_t type;
+        const void *data;
+        size_t size;
+        int64_t thumbNailTime;
+        int32_t thumbnailWidth, thumbnailHeight;
+
+        // if we have a stand-alone thumbnail, set up the override meta,
+        // and set seekTo time to -1.
+        if (trackMeta->findInt32(kKeyThumbnailWidth, &thumbnailWidth)
+         && trackMeta->findInt32(kKeyThumbnailHeight, &thumbnailHeight)
+         && trackMeta->findData(kKeyThumbnailHVCC, &type, &data, &size)){
+            overrideMeta = new MetaData(*trackMeta);
+            overrideMeta->remove(kKeyDisplayWidth);
+            overrideMeta->remove(kKeyDisplayHeight);
+            overrideMeta->setInt32(kKeyWidth, thumbnailWidth);
+            overrideMeta->setInt32(kKeyHeight, thumbnailHeight);
+            overrideMeta->setData(kKeyHVCC, type, data, size);
+            thumbNailTime = -1ll;
+            ALOGV("thumbnail: %dx%d", thumbnailWidth, thumbnailHeight);
+        } else if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
+                || thumbNailTime < 0) {
+            thumbNailTime = 0;
+        }
+
+        options.setSeekTo(thumbNailTime, mode);
+    } else {
+        options.setSeekTo(frameTimeUs, mode);
+    }
+
+    int32_t gridRows = 1, gridCols = 1;
+    if (overrideMeta == NULL) {
+        // check if we're dealing with a tiled heif
+        int32_t gridWidth, gridHeight;
+        if (trackMeta->findInt32(kKeyGridWidth, &gridWidth) && gridWidth > 0
+         && trackMeta->findInt32(kKeyGridHeight, &gridHeight) && gridHeight > 0) {
+            int32_t width, height, displayWidth, displayHeight;
+            CHECK(trackMeta->findInt32(kKeyWidth, &width));
+            CHECK(trackMeta->findInt32(kKeyHeight, &height));
+            CHECK(trackMeta->findInt32(kKeyDisplayWidth, &displayWidth));
+            CHECK(trackMeta->findInt32(kKeyDisplayHeight, &displayHeight));
+
+            if (width >= displayWidth && height >= displayHeight
+                    && (width % gridWidth == 0) && (height % gridHeight == 0)) {
+                ALOGV("grid config: %dx%d, display %dx%d, grid %dx%d",
+                        width, height, displayWidth, displayHeight, gridWidth, gridHeight);
+
+                overrideMeta = new MetaData(*trackMeta);
+                overrideMeta->remove(kKeyDisplayWidth);
+                overrideMeta->remove(kKeyDisplayHeight);
+                overrideMeta->setInt32(kKeyWidth, gridWidth);
+                overrideMeta->setInt32(kKeyHeight, gridHeight);
+                gridCols = width / gridWidth;
+                gridRows = height / gridHeight;
+            } else {
+                ALOGE("Bad grid config: %dx%d, display %dx%d, grid %dx%d",
+                        width, height, displayWidth, displayHeight, gridWidth, gridHeight);
+            }
+        }
+        if (overrideMeta == NULL) {
+            overrideMeta = trackMeta;
+        }
+    }
+    int32_t numTiles = gridRows * gridCols;
+
     sp<AMessage> videoFormat;
-    if (convertMetaDataToMessage(trackMeta, &videoFormat) != OK) {
+    if (convertMetaDataToMessage(overrideMeta, &videoFormat) != OK) {
         ALOGE("b/23680780");
         ALOGW("Failed to convert meta data to message");
         return NULL;
@@ -160,7 +322,8 @@
     // input and output ports, if seeking to a sync frame. NOTE: This request may
     // fail if component requires more than that for decoding.
     bool isSeekingClosest = (seekMode == MediaSource::ReadOptions::SEEK_CLOSEST);
-    if (!isSeekingClosest) {
+    bool decodeSingleFrame = !isSeekingClosest && (numTiles == 1);
+    if (decodeSingleFrame) {
         videoFormat->setInt32("android._num-input-buffers", 1);
         videoFormat->setInt32("android._num-output-buffers", 1);
     }
@@ -190,30 +353,6 @@
         return NULL;
     }
 
-    MediaSource::ReadOptions options;
-    if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC ||
-        seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) {
-
-        ALOGE("Unknown seek mode: %d", seekMode);
-        decoder->release();
-        return NULL;
-    }
-
-    MediaSource::ReadOptions::SeekMode mode =
-            static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
-
-    int64_t thumbNailTime;
-    if (frameTimeUs < 0) {
-        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
-                || thumbNailTime < 0) {
-            thumbNailTime = 0;
-        }
-        options.setSeekTo(thumbNailTime, mode);
-    } else {
-        thumbNailTime = -1;
-        options.setSeekTo(frameTimeUs, mode);
-    }
-
     err = source->start();
     if (err != OK) {
         ALOGW("source failed to start: %d (%s)", err, asString(err));
@@ -258,6 +397,9 @@
     bool firstSample = true;
     int64_t targetTimeUs = -1ll;
 
+    VideoFrame *frame = NULL;
+    int32_t tilesDecoded = 0;
+
     do {
         size_t inputIndex = -1;
         int64_t ptsUs = 0ll;
@@ -282,6 +424,9 @@
             if (err != OK) {
                 ALOGW("Input Error or EOS");
                 haveMoreInputs = false;
+                if (err == ERROR_END_OF_STREAM) {
+                    err = OK;
+                }
                 break;
             }
             if (firstSample && isSeekingClosest) {
@@ -293,6 +438,7 @@
             if (mediaBuffer->range_length() > codecBuffer->capacity()) {
                 ALOGE("buffer size (%zu) too large for codec input size (%zu)",
                         mediaBuffer->range_length(), codecBuffer->capacity());
+                haveMoreInputs = false;
                 err = BAD_VALUE;
             } else {
                 codecBuffer->setRange(0, mediaBuffer->range_length());
@@ -301,19 +447,20 @@
                 memcpy(codecBuffer->data(),
                         (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(),
                         mediaBuffer->range_length());
-                if (isAvcOrHevc && IsIDR(codecBuffer) && !isSeekingClosest) {
-                    // Only need to decode one IDR frame, unless we're seeking with CLOSEST
-                    // option, in which case we need to actually decode to targetTimeUs.
-                    haveMoreInputs = false;
-                    flags |= MediaCodec::BUFFER_FLAG_EOS;
-                }
             }
 
             mediaBuffer->release();
             break;
         }
 
-        if (err == OK && inputIndex < inputBuffers.size()) {
+        if (haveMoreInputs && inputIndex < inputBuffers.size()) {
+            if (isAvcOrHevc && IsIDR(codecBuffer) && decodeSingleFrame) {
+                // Only need to decode one IDR frame, unless we're seeking with CLOSEST
+                // option, in which case we need to actually decode to targetTimeUs.
+                haveMoreInputs = false;
+                flags |= MediaCodec::BUFFER_FLAG_EOS;
+            }
+
             ALOGV("QueueInput: size=%zu ts=%" PRId64 " us flags=%x",
                     codecBuffer->size(), ptsUs, flags);
             err = decoder->queueInputBuffer(
@@ -352,11 +499,70 @@
                 } else if (err == OK) {
                     // If we're seeking with CLOSEST option and obtained a valid targetTimeUs
                     // from the extractor, decode to the specified frame. Otherwise we're done.
-                    done = (targetTimeUs < 0ll) || (timeUs >= targetTimeUs);
                     ALOGV("Received an output buffer, timeUs=%lld", (long long)timeUs);
-                    if (!done) {
-                        err = decoder->releaseOutputBuffer(index);
+                    sp<MediaCodecBuffer> videoFrameBuffer = outputBuffers.itemAt(index);
+
+                    int32_t width, height;
+                    CHECK(outputFormat != NULL);
+                    CHECK(outputFormat->findInt32("width", &width));
+                    CHECK(outputFormat->findInt32("height", &height));
+
+                    int32_t crop_left, crop_top, crop_right, crop_bottom;
+                    if (!outputFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
+                        crop_left = crop_top = 0;
+                        crop_right = width - 1;
+                        crop_bottom = height - 1;
                     }
+
+                    if (frame == NULL) {
+                        frame = allocVideoFrame(
+                                trackMeta,
+                                (crop_right - crop_left + 1) * gridCols,
+                                (crop_bottom - crop_top + 1) * gridRows,
+                                dstBpp,
+                                false /*metaOnly*/);
+                    }
+
+                    int32_t srcFormat;
+                    CHECK(outputFormat->findInt32("color-format", &srcFormat));
+
+                    ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat);
+
+                    int32_t dstLeft, dstTop, dstRight, dstBottom;
+                    if (numTiles == 1) {
+                        dstLeft = crop_left;
+                        dstTop = crop_top;
+                        dstRight = crop_right;
+                        dstBottom = crop_bottom;
+                    } else {
+                        dstLeft = tilesDecoded % gridCols * width;
+                        dstTop = tilesDecoded / gridCols * height;
+                        dstRight = dstLeft + width - 1;
+                        dstBottom = dstTop + height - 1;
+                    }
+
+                    if (converter.isValid()) {
+                        err = converter.convert(
+                                (const uint8_t *)videoFrameBuffer->data(),
+                                width, height,
+                                crop_left, crop_top, crop_right, crop_bottom,
+                                frame->mData,
+                                frame->mWidth,
+                                frame->mHeight,
+                                dstLeft, dstTop, dstRight, dstBottom);
+                    } else {
+                        ALOGE("Unable to convert from format 0x%08x to 0x%08x",
+                                srcFormat, dstFormat);
+
+                        err = ERROR_UNSUPPORTED;
+                    }
+
+                    done = (targetTimeUs < 0ll) || (timeUs >= targetTimeUs);
+                    if (numTiles > 1) {
+                        tilesDecoded++;
+                        done &= (tilesDecoded >= numTiles);
+                    }
+                    err = decoder->releaseOutputBuffer(index);
                 } else {
                     ALOGW("Received error %d (%s) instead of output", err, asString(err));
                     done = true;
@@ -366,102 +572,11 @@
         }
     } while (err == OK && !done);
 
-    if (err != OK || size <= 0 || outputFormat == NULL) {
-        ALOGE("Failed to decode thumbnail frame");
-        source->stop();
-        decoder->release();
-        return NULL;
-    }
-
-    ALOGV("successfully decoded video frame.");
-    sp<MediaCodecBuffer> videoFrameBuffer = outputBuffers.itemAt(index);
-
-    if (thumbNailTime >= 0) {
-        if (timeUs != thumbNailTime) {
-            AString mime;
-            CHECK(outputFormat->findString("mime", &mime));
-
-            ALOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
-                    (long long)thumbNailTime, (long long)timeUs, mime.c_str());
-        }
-    }
-
-    int32_t width, height;
-    CHECK(outputFormat->findInt32("width", &width));
-    CHECK(outputFormat->findInt32("height", &height));
-
-    int32_t crop_left, crop_top, crop_right, crop_bottom;
-    if (!outputFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
-        crop_left = crop_top = 0;
-        crop_right = width - 1;
-        crop_bottom = height - 1;
-    }
-
-    int32_t rotationAngle;
-    if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
-        rotationAngle = 0;  // By default, no rotation
-    }
-
-    VideoFrame *frame = new VideoFrame;
-    frame->mWidth = crop_right - crop_left + 1;
-    frame->mHeight = crop_bottom - crop_top + 1;
-    frame->mDisplayWidth = frame->mWidth;
-    frame->mDisplayHeight = frame->mHeight;
-    frame->mSize = frame->mWidth * frame->mHeight * 2;
-    frame->mData = new uint8_t[frame->mSize];
-    frame->mRotationAngle = rotationAngle;
-
-    int32_t sarWidth, sarHeight;
-    if (trackMeta->findInt32(kKeySARWidth, &sarWidth)
-            && trackMeta->findInt32(kKeySARHeight, &sarHeight)
-            && sarHeight != 0) {
-        frame->mDisplayWidth = (frame->mDisplayWidth * sarWidth) / sarHeight;
-    } else {
-        int32_t width, height;
-        if (trackMeta->findInt32(kKeyDisplayWidth, &width)
-                && trackMeta->findInt32(kKeyDisplayHeight, &height)
-                && frame->mDisplayWidth > 0 && frame->mDisplayHeight > 0
-                && width > 0 && height > 0) {
-            if (frame->mDisplayHeight * (int64_t)width / height > (int64_t)frame->mDisplayWidth) {
-                frame->mDisplayHeight =
-                        (int32_t)(height * (int64_t)frame->mDisplayWidth / width);
-            } else {
-                frame->mDisplayWidth =
-                        (int32_t)(frame->mDisplayHeight * (int64_t)width / height);
-            }
-            ALOGV("thumbNail width and height are overridden to %d x %d",
-                    frame->mDisplayWidth, frame->mDisplayHeight);
-        }
-    }
-
-    int32_t srcFormat;
-    CHECK(outputFormat->findInt32("color-format", &srcFormat));
-
-    ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
-
-    if (converter.isValid()) {
-        err = converter.convert(
-                (const uint8_t *)videoFrameBuffer->data(),
-                width, height,
-                crop_left, crop_top, crop_right, crop_bottom,
-                frame->mData,
-                frame->mWidth,
-                frame->mHeight,
-                0, 0, frame->mWidth - 1, frame->mHeight - 1);
-    } else {
-        ALOGE("Unable to convert from format 0x%08x to RGB565", srcFormat);
-
-        err = ERROR_UNSUPPORTED;
-    }
-
-    videoFrameBuffer.clear();
     source->stop();
-    decoder->releaseOutputBuffer(index);
     decoder->release();
 
     if (err != OK) {
-        ALOGE("Colorconverter failed to convert frame.");
-
+        ALOGE("failed to get video frame (err %d)", err);
         delete frame;
         frame = NULL;
     }
@@ -470,9 +585,10 @@
 }
 
 VideoFrame *StagefrightMetadataRetriever::getFrameAtTime(
-        int64_t timeUs, int option) {
+        int64_t timeUs, int option, int colorFormat, bool metaOnly) {
 
-    ALOGV("getFrameAtTime: %" PRId64 " us option: %d", timeUs, option);
+    ALOGV("getFrameAtTime: %" PRId64 " us option: %d colorFormat: %d, metaOnly: %d",
+            timeUs, option, colorFormat, metaOnly);
 
     if (mExtractor.get() == NULL) {
         ALOGV("no extractor.");
@@ -540,8 +656,8 @@
 
     for (size_t i = 0; i < matchingCodecs.size(); ++i) {
         const AString &componentName = matchingCodecs[i];
-        VideoFrame *frame =
-            extractVideoFrame(componentName, trackMeta, source, timeUs, option);
+        VideoFrame *frame = extractVideoFrame(
+                componentName, trackMeta, source, timeUs, option, colorFormat, metaOnly);
 
         if (frame != NULL) {
             return frame;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 0aea8e1..3ef8f2a 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -237,6 +237,11 @@
     OMX_VIDEO_AVCPROFILETYPE codecProfile;
     OMX_VIDEO_AVCLEVELTYPE codecLevel;
     if (profiles.map(profile, &codecProfile)) {
+        if (profile == 66 && (constraints & 0x40)) {
+            codecProfile = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedBaseline;
+        } else if (profile == 100 && (constraints & 0x0C) == 0x0C) {
+            codecProfile = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedHigh;
+        }
         format->setInt32("profile", codecProfile);
         if (levels.map(level, &codecLevel)) {
             // for 9 && 11 decide level based on profile and constraint_set3 flag
@@ -1874,5 +1879,13 @@
     return result;
 }
 
+void MakeFourCCString(uint32_t x, char *s) {
+    s[0] = x >> 24;
+    s[1] = (x >> 16) & 0xff;
+    s[2] = (x >> 8) & 0xff;
+    s[3] = x & 0xff;
+    s[4] = '\0';
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/codecs/aacdec/Android.bp b/media/libstagefright/codecs/aacdec/Android.bp
index 6e04c1e..21c00a1 100644
--- a/media/libstagefright/codecs/aacdec/Android.bp
+++ b/media/libstagefright/codecs/aacdec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_aacdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "SoftAAC2.cpp",
@@ -33,4 +37,5 @@
         "libcutils",
         "liblog",
     ],
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 9fbdb72..e0c0c32 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -218,6 +218,30 @@
 OMX_ERRORTYPE SoftAAC2::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch ((OMX_U32) index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding =
+                (formatParams->nPortIndex == 0)
+                    ? OMX_AUDIO_CodingAAC : OMX_AUDIO_CodingPCM;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioAac:
         {
             OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
@@ -342,6 +366,29 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if ((formatParams->nPortIndex == 0
+                        && formatParams->eEncoding != OMX_AUDIO_CodingAAC)
+                || (formatParams->nPortIndex == 1
+                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioAac:
         {
             const OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h
index a1cf285..73a3965 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.h
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h
@@ -17,7 +17,7 @@
 #ifndef SOFT_AAC_2_H_
 #define SOFT_AAC_2_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 #include "aacdecoder_lib.h"
 #include "DrcPresModeWrap.h"
diff --git a/media/libstagefright/codecs/aacenc/Android.bp b/media/libstagefright/codecs/aacenc/Android.bp
index 432047b..d734b9c 100644
--- a/media/libstagefright/codecs/aacenc/Android.bp
+++ b/media/libstagefright/codecs/aacenc/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_aacenc",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftAACEncoder2.cpp"],
 
@@ -29,4 +33,5 @@
         "libutils",
         "liblog",
     ],
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder.h b/media/libstagefright/codecs/aacenc/SoftAACEncoder.h
index 981cbbb..e64c1b7 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder.h
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder.h
@@ -18,7 +18,7 @@
 
 #define SOFT_AAC_ENCODER_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 struct VO_AUDIO_CODECAPI;
 struct VO_MEM_OPERATOR;
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h
index 123fd25..681dcf2 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h
@@ -18,7 +18,7 @@
 
 #define SOFT_AAC_ENCODER_2_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 #include "aacenc_lib.h"
 
diff --git a/media/libstagefright/codecs/amrnb/common/Android.bp b/media/libstagefright/codecs/amrnb/common/Android.bp
index c5ac558..5177593 100644
--- a/media/libstagefright/codecs/amrnb/common/Android.bp
+++ b/media/libstagefright/codecs/amrnb/common/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_amrnb_common",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "src/add.cpp",
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.bp b/media/libstagefright/codecs/amrnb/dec/Android.bp
index 9f3fe08..b493e21 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.bp
+++ b/media/libstagefright/codecs/amrnb/dec/Android.bp
@@ -1,5 +1,6 @@
 cc_library_static {
     name: "libstagefright_amrnbdec",
+    vendor_available: true,
 
     srcs: [
         "src/a_refl.cpp",
@@ -55,13 +56,20 @@
     //    ],
     //},
 
-    shared_libs: ["libstagefright_amrnb_common"],
+    shared_libs: [
+        "libstagefright_amrnb_common",
+        "liblog",
+    ],
 }
 
 //###############################################################################
 
 cc_library_shared {
     name: "libstagefright_soft_amrdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftAMR.cpp"],
 
@@ -96,6 +104,7 @@
         "liblog",
         "libstagefright_amrnb_common",
     ],
+    compile_multilib: "32",
 }
 
 //###############################################################################
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index 7553153..b7e84ec 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -143,6 +143,30 @@
 OMX_ERRORTYPE SoftAMR::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding =
+                (formatParams->nPortIndex == 0)
+                    ? OMX_AUDIO_CodingAMR : OMX_AUDIO_CodingPCM;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioAmr:
         {
             OMX_AUDIO_PARAM_AMRTYPE *amrParams =
@@ -236,6 +260,29 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if ((formatParams->nPortIndex == 0
+                        && formatParams->eEncoding != OMX_AUDIO_CodingAMR)
+                || (formatParams->nPortIndex == 1
+                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioAmr:
         {
             const OMX_AUDIO_PARAM_AMRTYPE *aacParams =
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.h b/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
index 758d6ac..869b81d 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
@@ -18,7 +18,7 @@
 
 #define SOFT_AMR_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 namespace android {
 
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.bp b/media/libstagefright/codecs/amrnb/enc/Android.bp
index a0cf260..1e8fd31 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.bp
+++ b/media/libstagefright/codecs/amrnb/enc/Android.bp
@@ -1,5 +1,6 @@
 cc_library_static {
     name: "libstagefright_amrnbenc",
+    vendor_available: true,
 
     srcs: [
         "src/amrencode.cpp",
@@ -83,6 +84,10 @@
 
 cc_library_shared {
     name: "libstagefright_soft_amrnbenc",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftAMRNBEncoder.cpp"],
 
@@ -110,6 +115,7 @@
         "liblog",
         "libstagefright_amrnb_common",
     ],
+    compile_multilib: "32",
 }
 
 //###############################################################################
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.h b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.h
index 50178c4..c73e4dd 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.h
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.h
@@ -18,7 +18,7 @@
 
 #define SOFT_AMRNB_ENCODER_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 namespace android {
 
diff --git a/media/libstagefright/codecs/amrwb/Android.bp b/media/libstagefright/codecs/amrwb/Android.bp
index f2ab0da..14a73d6 100644
--- a/media/libstagefright/codecs/amrwb/Android.bp
+++ b/media/libstagefright/codecs/amrwb/Android.bp
@@ -1,5 +1,6 @@
 cc_library_static {
     name: "libstagefright_amrwbdec",
+    vendor_available: true,
 
     srcs: [
         "src/agc2_amr_wb.cpp",
diff --git a/media/libstagefright/codecs/amrwbenc/Android.bp b/media/libstagefright/codecs/amrwbenc/Android.bp
index eb27388..b6f637f 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.bp
+++ b/media/libstagefright/codecs/amrwbenc/Android.bp
@@ -1,5 +1,6 @@
 cc_library_static {
     name: "libstagefright_amrwbenc",
+    vendor_available: true,
 
     srcs: [
         "src/autocorr.c",
@@ -144,6 +145,10 @@
 
 cc_library_shared {
     name: "libstagefright_soft_amrwbenc",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftAMRWBEncoder.cpp"],
 
@@ -173,6 +178,7 @@
         "liblog",
         "libstagefright_enc_common",
     ],
+    compile_multilib: "32",
 }
 
 //###############################################################################
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.h b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.h
index d0c1dab..8950a8c 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.h
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.h
@@ -18,7 +18,7 @@
 
 #define SOFT_AMRWB_ENCODER_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 #include "voAMRWB.h"
 
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index b6724be..34db19b 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_avcdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     static_libs: ["libavcdec"],
     srcs: ["SoftAVCDec.cpp"],
@@ -18,7 +22,7 @@
     ],
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
@@ -36,4 +40,5 @@
     },
 
     ldflags: ["-Wl,-Bsymbolic"],
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 248ab6d..c342b6c 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -48,10 +48,14 @@
         (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
 
 static const CodecProfileLevel kProfileLevels[] = {
+    { OMX_VIDEO_AVCProfileConstrainedBaseline, OMX_VIDEO_AVCLevel52 },
+
     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel52 },
 
     { OMX_VIDEO_AVCProfileMain,     OMX_VIDEO_AVCLevel52 },
 
+    { OMX_VIDEO_AVCProfileConstrainedHigh,     OMX_VIDEO_AVCLevel52 },
+
     { OMX_VIDEO_AVCProfileHigh,     OMX_VIDEO_AVCLevel52 },
 };
 
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.h b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
index 18b7556..679ed3e 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.h
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
@@ -18,7 +18,7 @@
 
 #define SOFT_H264_DEC_H_
 
-#include "SoftVideoDecoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoDecoderOMXComponent.h>
 #include <sys/time.h>
 
 namespace android {
diff --git a/media/libstagefright/codecs/avcenc/Android.bp b/media/libstagefright/codecs/avcenc/Android.bp
index f0542a3..5203126 100644
--- a/media/libstagefright/codecs/avcenc/Android.bp
+++ b/media/libstagefright/codecs/avcenc/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_avcenc",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     static_libs: ["libavcenc"],
     srcs: ["SoftAVCEnc.cpp"],
@@ -13,7 +17,7 @@
     ],
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libutils",
         "liblog",
@@ -35,4 +39,5 @@
         "-Wno-unused-variable",
     ],
     ldflags: ["-Wl,-Bsymbolic"],
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index b1af17b..358c743 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -27,7 +27,6 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
 #include <OMX_IndexExt.h>
 #include <OMX_VideoExt.h>
 
@@ -75,33 +74,11 @@
 };
 
 static const CodecProfileLevel kProfileLevels[] = {
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1  },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2  },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3  },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4  },
-    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1  },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1b },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel11 },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel12 },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel13 },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel2  },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel21 },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel22 },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel3  },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel31 },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel32 },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel4  },
-    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel41 },
+    { OMX_VIDEO_AVCProfileConstrainedBaseline, OMX_VIDEO_AVCLevel41 },
 
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
+
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel41 },
 };
 
 static size_t GetCPUCoreCount() {
@@ -629,8 +606,10 @@
         level = 30;
     } else if (displaySizeY > (352 * 288)) {
         level = 21;
-    } else {
+    } else if (displaySizeY > (176 * 144)) {
         level = 20;
+    } else {
+        level = 10;
     }
     mAVCEncLevel = MAX(level, mAVCEncLevel);
 
@@ -963,7 +942,8 @@
                 return OMX_ErrorUndefined;
             }
 
-            avcParams->eProfile = OMX_VIDEO_AVCProfileBaseline;
+            // TODO: maintain profile
+            avcParams->eProfile = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedBaseline;
             avcParams->eLevel = omxLevel;
             avcParams->nRefFrames = 1;
             avcParams->bUseHadamard = OMX_TRUE;
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.h b/media/libstagefright/codecs/avcenc/SoftAVCEnc.h
index 818e4a1..a43cdf1 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.h
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.h
@@ -21,7 +21,7 @@
 #include <media/stagefright/foundation/ABase.h>
 #include <utils/Vector.h>
 
-#include "SoftVideoEncoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoEncoderOMXComponent.h>
 
 namespace android {
 
diff --git a/media/libstagefright/codecs/common/Android.bp b/media/libstagefright/codecs/common/Android.bp
index 021e6af..3726922 100644
--- a/media/libstagefright/codecs/common/Android.bp
+++ b/media/libstagefright/codecs/common/Android.bp
@@ -1,5 +1,9 @@
 cc_library {
     name: "libstagefright_enc_common",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["cmnMemory.c"],
 
diff --git a/media/libstagefright/codecs/flac/dec/Android.bp b/media/libstagefright/codecs/flac/dec/Android.bp
index 6ac264d..595cfdb 100644
--- a/media/libstagefright/codecs/flac/dec/Android.bp
+++ b/media/libstagefright/codecs/flac/dec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_flacdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "SoftFlacDecoder.cpp",
@@ -33,4 +37,5 @@
         "libstagefright_foundation",
         "libutils",
     ],
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
index cff4a33..4ab1ab2 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
@@ -126,6 +126,29 @@
         OMX_INDEXTYPE index, OMX_PTR params) {
     ALOGV("internalGetParameter: index(%x)", index);
     switch ((OMX_U32)index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding =
+                (formatParams->nPortIndex == 0)
+                    ? OMX_AUDIO_CodingFLAC : OMX_AUDIO_CodingPCM;
+
+            return OMX_ErrorNone;
+        }
         case OMX_IndexParamAudioFlac:
         {
             OMX_AUDIO_PARAM_FLACTYPE *flacParams =
@@ -219,6 +242,29 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if ((formatParams->nPortIndex == 0
+                        && formatParams->eEncoding != OMX_AUDIO_CodingFLAC)
+                || (formatParams->nPortIndex == 1
+                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
@@ -256,10 +302,27 @@
     while (!inQueue.empty() && !outQueue.empty()) {
         BufferInfo *inInfo = *inQueue.begin();
         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+        BufferInfo *outInfo = *outQueue.begin();
+        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
         uint8_t* inBuffer = inHeader->pBuffer + inHeader->nOffset;
         uint32_t inBufferLength = inHeader->nFilledLen;
         bool endOfInput = (inHeader->nFlags & OMX_BUFFERFLAG_EOS) != 0;
 
+        if (inHeader->nFilledLen == 0) {
+            if (endOfInput) {
+                outHeader->nFilledLen = 0;
+                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+                outInfo->mOwnedByUs = false;
+                outQueue.erase(outQueue.begin());
+                notifyFillBufferDone(outHeader);
+            } else {
+                ALOGE("onQueueFilled: emptyInputBuffer received");
+            }
+            inInfo->mOwnedByUs = false;
+            inQueue.erase(inQueue.begin());
+            notifyEmptyBufferDone(inHeader);
+            return;
+        }
         if (mInputBufferCount == 0 && !(inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
             ALOGE("onQueueFilled: first buffer should have OMX_BUFFERFLAG_CODECCONFIG set");
             inHeader->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
@@ -297,8 +360,6 @@
             return;
         }
 
-        BufferInfo *outInfo = *outQueue.begin();
-        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
         short *outBuffer =
                 reinterpret_cast<short *>(outHeader->pBuffer + outHeader->nOffset);
         size_t outBufferSize = outHeader->nAllocLen - outHeader->nOffset;
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
index c09081d..4a21c34 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
@@ -18,7 +18,7 @@
 #define SOFT_FLAC_DECODER_H
 
 #include "FLACDecoder.h"
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 namespace android {
 
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index d1413f6..066917b 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -22,7 +22,7 @@
     },
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
@@ -32,5 +32,10 @@
     static_libs: ["libFLAC"],
 
     name: "libstagefright_soft_flacenc",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index caceda9..56d2d69 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -154,6 +154,30 @@
     ALOGV("SoftFlacEncoder::internalGetParameter(index=0x%x)", index);
 
     switch (index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding =
+                (formatParams->nPortIndex == 0)
+                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingFLAC;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
@@ -163,7 +187,7 @@
                 return OMX_ErrorBadParameter;
             }
 
-            if (pcmParams->nPortIndex > 1) {
+            if (pcmParams->nPortIndex != 0) {
                 return OMX_ErrorUndefined;
             }
 
@@ -189,6 +213,10 @@
                 return OMX_ErrorBadParameter;
             }
 
+            if (flacParams->nPortIndex != 1) {
+                return OMX_ErrorUndefined;
+            }
+
             flacParams->nCompressionLevel = mCompressionLevel;
             flacParams->nChannels = mNumChannels;
             flacParams->nSampleRate = mSampleRate;
@@ -203,6 +231,29 @@
 OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter(
         OMX_INDEXTYPE index, const OMX_PTR params) {
     switch (index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if ((formatParams->nPortIndex == 0
+                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
+                || (formatParams->nPortIndex == 1
+                        && formatParams->eEncoding != OMX_AUDIO_CodingFLAC)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             ALOGV("SoftFlacEncoder::internalSetParameter(OMX_IndexParamAudioPcm)");
@@ -212,7 +263,7 @@
                 return OMX_ErrorBadParameter;
             }
 
-            if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
+            if (pcmParams->nPortIndex != 0) {
                 ALOGE("SoftFlacEncoder::internalSetParameter() Error #1");
                 return OMX_ErrorUndefined;
             }
@@ -258,6 +309,10 @@
                 return OMX_ErrorBadParameter;
             }
 
+            if (flacParams->nPortIndex != 1) {
+                return OMX_ErrorUndefined;
+            }
+
             mCompressionLevel = flacParams->nCompressionLevel; // range clamping done inside encoder
             return OMX_ErrorNone;
         }
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
index 6027f76..f4f0655 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
@@ -18,7 +18,7 @@
 
 #define SOFT_FLAC_ENC_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 #include "FLAC/stream_encoder.h"
 
diff --git a/media/libstagefright/codecs/g711/dec/Android.bp b/media/libstagefright/codecs/g711/dec/Android.bp
index b78b689..fff72a8 100644
--- a/media/libstagefright/codecs/g711/dec/Android.bp
+++ b/media/libstagefright/codecs/g711/dec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_g711dec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftG711.cpp"],
 
@@ -9,7 +13,7 @@
     ],
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libutils",
         "liblog",
@@ -27,4 +31,5 @@
             cfi: true,
         },
     },
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index f7c0429..7a4cca9 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -105,6 +105,30 @@
 OMX_ERRORTYPE SoftG711::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding =
+                (formatParams->nPortIndex == 0)
+                    ? OMX_AUDIO_CodingG711 : OMX_AUDIO_CodingPCM;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
@@ -173,6 +197,29 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if ((formatParams->nPortIndex == 0
+                        && formatParams->eEncoding != OMX_AUDIO_CodingG711)
+                || (formatParams->nPortIndex == 1
+                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamStandardComponentRole:
         {
             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.h b/media/libstagefright/codecs/g711/dec/SoftG711.h
index 16b6340..3ece246 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.h
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.h
@@ -18,7 +18,7 @@
 
 #define SOFT_G711_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 namespace android {
 
diff --git a/media/libstagefright/codecs/gsm/dec/Android.bp b/media/libstagefright/codecs/gsm/dec/Android.bp
index 8e86ad6..753eeef 100644
--- a/media/libstagefright/codecs/gsm/dec/Android.bp
+++ b/media/libstagefright/codecs/gsm/dec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_gsmdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftGSM.cpp"],
 
@@ -23,11 +27,12 @@
     },
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libutils",
         "liblog",
     ],
 
     static_libs: ["libgsm"],
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
index 11999b4..d777229 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
@@ -105,6 +105,30 @@
 OMX_ERRORTYPE SoftGSM::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding =
+                (formatParams->nPortIndex == 0)
+                    ? OMX_AUDIO_CodingGSMFR : OMX_AUDIO_CodingPCM;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
@@ -164,6 +188,29 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if ((formatParams->nPortIndex == 0
+                        && formatParams->eEncoding != OMX_AUDIO_CodingGSMFR)
+                || (formatParams->nPortIndex == 1
+                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamStandardComponentRole:
         {
             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.h b/media/libstagefright/codecs/gsm/dec/SoftGSM.h
index 0303dea..ef86915 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.h
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.h
@@ -18,7 +18,7 @@
 
 #define SOFT_GSM_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 extern "C" {
 #include "gsm.h"
diff --git a/media/libstagefright/codecs/hevcdec/Android.bp b/media/libstagefright/codecs/hevcdec/Android.bp
index 3beb5d0..d9a5ee3 100644
--- a/media/libstagefright/codecs/hevcdec/Android.bp
+++ b/media/libstagefright/codecs/hevcdec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_hevcdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     static_libs: ["libhevcdec"],
     srcs: ["SoftHEVC.cpp"],
@@ -28,7 +32,7 @@
     },
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
@@ -39,4 +43,5 @@
     // requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC
     // Bug: 16853291
     ldflags: ["-Wl,-Bsymbolic"],
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.h b/media/libstagefright/codecs/hevcdec/SoftHEVC.h
index e7c2127..5800490 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.h
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.h
@@ -18,7 +18,7 @@
 
 #define SOFT_HEVC_H_
 
-#include "SoftVideoDecoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoDecoderOMXComponent.h>
 #include <sys/time.h>
 
 namespace android {
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.bp b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
index 04ea075..1216ae5 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
@@ -1,5 +1,7 @@
 cc_library_static {
     name: "libstagefright_m4vh263dec",
+    vendor_available: true,
+    shared_libs: ["liblog"],
 
     srcs: [
         "src/adaptive_smooth_no_mmx.cpp",
@@ -66,6 +68,10 @@
 
 cc_library_shared {
     name: "libstagefright_soft_mpeg4dec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftMPEG4.cpp"],
 
@@ -87,7 +93,7 @@
     static_libs: ["libstagefright_m4vh263dec"],
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
@@ -103,4 +109,5 @@
             cfi: true,
         },
     },
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index 411a251..39b67ab 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -31,20 +31,12 @@
 namespace android {
 
 static const CodecProfileLevel kM4VProfileLevels[] = {
-    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0 },
-    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0b },
-    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1 },
-    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level2 },
     { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level3 },
 };
 
 static const CodecProfileLevel kH263ProfileLevels[] = {
-    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10 },
-    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level20 },
     { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level30 },
     { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 },
-    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level10 },
-    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level20 },
     { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level30 },
     { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level45 },
 };
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
index 4114e7d..e399ac9 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
@@ -18,7 +18,7 @@
 
 #define SOFT_MPEG4_H_
 
-#include "SoftVideoDecoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoDecoderOMXComponent.h>
 
 struct tagvideoDecControls;
 
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp
index f7192b1c..7202f98 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp
@@ -560,7 +560,7 @@
 
     BitstreamShow13Bits(stream, &code);
 
-    if (code == 0)
+    if (code < 8)
     {
         return VLC_CODE_ERROR;
     }
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
index d63c946..a95b807 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
@@ -1,5 +1,6 @@
 cc_library_static {
     name: "libstagefright_m4vh263enc",
+    vendor_available: true,
 
     srcs: [
         "src/bitstream_io.cpp",
@@ -52,6 +53,10 @@
 
 cc_library_shared {
     name: "libstagefright_soft_mpeg4enc",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftMPEG4Encoder.cpp"],
 
@@ -75,7 +80,7 @@
     static_libs: ["libstagefright_m4vh263enc"],
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libutils",
         "liblog",
@@ -90,6 +95,7 @@
             cfi: true,
         },
     },
+    compile_multilib: "32",
 }
 
 //###############################################################################
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index 6d4cb69..7b90a01 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -29,7 +29,6 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
 
 #include "SoftMPEG4Encoder.h"
 
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
index ae8cb6f..00f2dd3 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
@@ -19,7 +19,7 @@
 
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/foundation/ABase.h>
-#include "SoftVideoEncoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoEncoderOMXComponent.h>
 #include "mp4enc_api.h"
 
 
diff --git a/media/libstagefright/codecs/mp3dec/Android.bp b/media/libstagefright/codecs/mp3dec/Android.bp
index 304fef8..c554a99 100644
--- a/media/libstagefright/codecs/mp3dec/Android.bp
+++ b/media/libstagefright/codecs/mp3dec/Android.bp
@@ -1,5 +1,6 @@
 cc_library_static {
     name: "libstagefright_mp3dec",
+    vendor_available: true,
 
     srcs: [
         "src/pvmp3_normalize.cpp",
@@ -77,6 +78,10 @@
 
 cc_library_shared {
     name: "libstagefright_soft_mp3dec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftMP3.cpp"],
 
@@ -102,7 +107,7 @@
     },
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
@@ -110,6 +115,7 @@
     ],
 
     static_libs: ["libstagefright_mp3dec"],
+    compile_multilib: "32",
 }
 
 //###############################################################################
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 3def1f0..2364684 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -134,6 +134,30 @@
 OMX_ERRORTYPE SoftMP3::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding =
+                (formatParams->nPortIndex == 0)
+                    ? OMX_AUDIO_CodingMP3 : OMX_AUDIO_CodingPCM;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
@@ -208,6 +232,29 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if ((formatParams->nPortIndex == 0
+                        && formatParams->eEncoding != OMX_AUDIO_CodingMP3)
+                || (formatParams->nPortIndex == 1
+                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.h b/media/libstagefright/codecs/mp3dec/SoftMP3.h
index 3bfa6c7..976fd00 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.h
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.h
@@ -18,7 +18,7 @@
 
 #define SOFT_MP3_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 struct tPVMP3DecoderExternal;
 
diff --git a/media/libstagefright/codecs/mpeg2dec/Android.bp b/media/libstagefright/codecs/mpeg2dec/Android.bp
index 051b89b..9590e9f 100644
--- a/media/libstagefright/codecs/mpeg2dec/Android.bp
+++ b/media/libstagefright/codecs/mpeg2dec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_mpeg2dec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     static_libs: ["libmpeg2dec"],
     srcs: ["SoftMPEG2.cpp"],
@@ -18,7 +22,7 @@
     ],
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
@@ -36,4 +40,5 @@
             cfi: true,
         },
     },
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
index 9a69226..9d5f342 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
@@ -789,7 +789,7 @@
 
             if (s_dec_op.u4_output_present) {
                 ssize_t timeStampIdx;
-                outHeader->nFilledLen = (mWidth * mHeight * 3) / 2;
+                outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
 
                 timeStampIdx = getMinTimestampIdx(mTimeStamps, mTimeStampsValid);
                 if (timeStampIdx < 0) {
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
index 6729a54..338fc30 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
@@ -18,7 +18,7 @@
 
 #define SOFT_MPEG2_H_
 
-#include "SoftVideoDecoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoDecoderOMXComponent.h>
 #include <sys/time.h>
 
 namespace android {
diff --git a/media/libstagefright/codecs/on2/dec/Android.bp b/media/libstagefright/codecs/on2/dec/Android.bp
index c4242c2..59c1f5d 100644
--- a/media/libstagefright/codecs/on2/dec/Android.bp
+++ b/media/libstagefright/codecs/on2/dec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_vpxdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftVPX.cpp"],
 
@@ -11,7 +15,7 @@
     static_libs: ["libvpx"],
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
@@ -30,4 +34,5 @@
             cfi: true,
         },
     },
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.h b/media/libstagefright/codecs/on2/dec/SoftVPX.h
index 84cf79c..d6bb902 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.h
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.h
@@ -18,7 +18,7 @@
 
 #define SOFT_VPX_H_
 
-#include "SoftVideoDecoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoDecoderOMXComponent.h>
 
 #include "vpx/vpx_decoder.h"
 #include "vpx/vpx_codec.h"
diff --git a/media/libstagefright/codecs/on2/enc/Android.bp b/media/libstagefright/codecs/on2/enc/Android.bp
index ba53090..5a52225 100644
--- a/media/libstagefright/codecs/on2/enc/Android.bp
+++ b/media/libstagefright/codecs/on2/enc/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_vpxenc",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "SoftVPXEncoder.cpp",
@@ -28,10 +32,11 @@
     static_libs: ["libvpx"],
 
     shared_libs: [
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
         "liblog",
     ],
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
index 86dfad7..dd86d36 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
@@ -18,7 +18,7 @@
 
 #define SOFT_VPX_ENCODER_H_
 
-#include "SoftVideoEncoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoEncoderOMXComponent.h>
 
 #include <OMX_VideoExt.h>
 #include <OMX_IndexExt.h>
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
index b8c1807..fad988b 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -18,7 +18,7 @@
 
 #define SOFT_AVC_H_
 
-#include "SoftVideoDecoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoDecoderOMXComponent.h>
 #include <utils/KeyedVector.h>
 
 #include "H264SwDecApi.h"
diff --git a/media/libstagefright/codecs/opus/dec/Android.bp b/media/libstagefright/codecs/opus/dec/Android.bp
index ecd73f6..88d6ec4 100644
--- a/media/libstagefright/codecs/opus/dec/Android.bp
+++ b/media/libstagefright/codecs/opus/dec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_opusdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftOpus.cpp"],
 
@@ -10,7 +14,7 @@
 
     shared_libs: [
         "libopus",
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
@@ -29,4 +33,5 @@
             cfi: true,
         },
     },
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index 2ac6ce0..813004b 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -62,6 +62,7 @@
       mSeekPreRoll(0),
       mAnchorTimeUs(0),
       mNumFramesOutput(0),
+      mHaveEOS(false),
       mOutputPortSettingsChange(NONE) {
     initPorts();
     CHECK_EQ(initDecoder(), (status_t)OK);
@@ -129,6 +130,31 @@
 OMX_ERRORTYPE SoftOpus::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch ((int)index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding =
+                (formatParams->nPortIndex == 0)
+                    ? (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS :
+                       OMX_AUDIO_CodingPCM;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioAndroidOpus:
         {
             OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
@@ -212,6 +238,30 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if ((formatParams->nPortIndex == 0
+                        && formatParams->eEncoding !=
+                           (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS)
+                || (formatParams->nPortIndex == 1
+                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioAndroidOpus:
         {
             const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
@@ -335,7 +385,31 @@
     return static_cast<double>(ns) * kRate / 1000000000;
 }
 
-void SoftOpus::onQueueFilled(OMX_U32 portIndex) {
+void SoftOpus::handleEOS() {
+    List<BufferInfo *> &inQueue = getPortQueue(0);
+    List<BufferInfo *> &outQueue = getPortQueue(1);
+    CHECK(!inQueue.empty() && !outQueue.empty());
+
+    BufferInfo *outInfo = *outQueue.begin();
+    OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+    outHeader->nFilledLen = 0;
+    outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+    mHaveEOS = true;
+
+    outQueue.erase(outQueue.begin());
+    outInfo->mOwnedByUs = false;
+    notifyFillBufferDone(outHeader);
+
+    BufferInfo *inInfo = *inQueue.begin();
+    OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+    inQueue.erase(inQueue.begin());
+    inInfo->mOwnedByUs = false;
+    notifyEmptyBufferDone(inHeader);
+
+    ++mInputBufferCount;
+}
+
+void SoftOpus::onQueueFilled(OMX_U32 /* portIndex */) {
     List<BufferInfo *> &inQueue = getPortQueue(0);
     List<BufferInfo *> &outQueue = getPortQueue(1);
 
@@ -343,104 +417,108 @@
         return;
     }
 
-    if (portIndex == 0 && mInputBufferCount < 3) {
-        BufferInfo *info = *inQueue.begin();
-        OMX_BUFFERHEADERTYPE *header = info->mHeader;
-
-        const uint8_t *data = header->pBuffer + header->nOffset;
-        size_t size = header->nFilledLen;
-
-        if (mInputBufferCount == 0) {
-            CHECK(mHeader == NULL);
-            mHeader = new OpusHeader();
-            memset(mHeader, 0, sizeof(*mHeader));
-            if (!ParseOpusHeader(data, size, mHeader)) {
-                ALOGV("Parsing Opus Header failed.");
-                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
-                return;
-            }
-
-            uint8_t channel_mapping[kMaxChannels] = {0};
-            if (mHeader->channels <= kMaxChannelsWithDefaultLayout) {
-                memcpy(&channel_mapping,
-                       kDefaultOpusChannelLayout,
-                       kMaxChannelsWithDefaultLayout);
-            } else {
-                memcpy(&channel_mapping,
-                       mHeader->stream_map,
-                       mHeader->channels);
-            }
-
-            int status = OPUS_INVALID_STATE;
-            mDecoder = opus_multistream_decoder_create(kRate,
-                                                       mHeader->channels,
-                                                       mHeader->num_streams,
-                                                       mHeader->num_coupled,
-                                                       channel_mapping,
-                                                       &status);
-            if (!mDecoder || status != OPUS_OK) {
-                ALOGV("opus_multistream_decoder_create failed status=%s",
-                      opus_strerror(status));
-                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
-                return;
-            }
-            status =
-                opus_multistream_decoder_ctl(mDecoder,
-                                             OPUS_SET_GAIN(mHeader->gain_db));
-            if (status != OPUS_OK) {
-                ALOGV("Failed to set OPUS header gain; status=%s",
-                      opus_strerror(status));
-                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
-                return;
-            }
-        } else if (mInputBufferCount == 1) {
-            mCodecDelay = ns_to_samples(
-                              *(reinterpret_cast<int64_t*>(header->pBuffer +
-                                                           header->nOffset)),
-                              kRate);
-            mSamplesToDiscard = mCodecDelay;
-        } else {
-            mSeekPreRoll = ns_to_samples(
-                               *(reinterpret_cast<int64_t*>(header->pBuffer +
-                                                            header->nOffset)),
-                               kRate);
-            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
-            mOutputPortSettingsChange = AWAITING_DISABLED;
-        }
-
-        inQueue.erase(inQueue.begin());
-        info->mOwnedByUs = false;
-        notifyEmptyBufferDone(header);
-        ++mInputBufferCount;
-        return;
-    }
-
-    while (!inQueue.empty() && !outQueue.empty()) {
+    while (!mHaveEOS && !inQueue.empty() && !outQueue.empty()) {
         BufferInfo *inInfo = *inQueue.begin();
         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
 
-        // Ignore CSD re-submissions.
-        if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+        if (mInputBufferCount < 3) {
+            const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
+            size_t size = inHeader->nFilledLen;
+
+            if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && size == 0) {
+                handleEOS();
+                return;
+            }
+
+            if (mInputBufferCount == 0) {
+                CHECK(mHeader == NULL);
+                mHeader = new OpusHeader();
+                memset(mHeader, 0, sizeof(*mHeader));
+                if (!ParseOpusHeader(data, size, mHeader)) {
+                    ALOGV("Parsing Opus Header failed.");
+                    notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+                    return;
+                }
+
+                uint8_t channel_mapping[kMaxChannels] = {0};
+                if (mHeader->channels <= kMaxChannelsWithDefaultLayout) {
+                    memcpy(&channel_mapping,
+                           kDefaultOpusChannelLayout,
+                           kMaxChannelsWithDefaultLayout);
+                } else {
+                    memcpy(&channel_mapping,
+                           mHeader->stream_map,
+                           mHeader->channels);
+                }
+
+                int status = OPUS_INVALID_STATE;
+                mDecoder = opus_multistream_decoder_create(kRate,
+                                                           mHeader->channels,
+                                                           mHeader->num_streams,
+                                                           mHeader->num_coupled,
+                                                           channel_mapping,
+                                                           &status);
+                if (!mDecoder || status != OPUS_OK) {
+                    ALOGV("opus_multistream_decoder_create failed status=%s",
+                          opus_strerror(status));
+                    notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+                    return;
+                }
+                status =
+                    opus_multistream_decoder_ctl(mDecoder,
+                                                 OPUS_SET_GAIN(mHeader->gain_db));
+                if (status != OPUS_OK) {
+                    ALOGV("Failed to set OPUS header gain; status=%s",
+                          opus_strerror(status));
+                    notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+                    return;
+                }
+            } else if (mInputBufferCount == 1) {
+                mCodecDelay = ns_to_samples(
+                                  *(reinterpret_cast<int64_t*>(inHeader->pBuffer +
+                                                               inHeader->nOffset)),
+                                  kRate);
+                mSamplesToDiscard = mCodecDelay;
+            } else {
+                mSeekPreRoll = ns_to_samples(
+                                   *(reinterpret_cast<int64_t*>(inHeader->pBuffer +
+                                                                inHeader->nOffset)),
+                                   kRate);
+                notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+                mOutputPortSettingsChange = AWAITING_DISABLED;
+            }
+
+            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+                handleEOS();
+                return;
+            }
+
             inQueue.erase(inQueue.begin());
             inInfo->mOwnedByUs = false;
             notifyEmptyBufferDone(inHeader);
-            return;
+            ++mInputBufferCount;
+
+            continue;
+        }
+
+        // Ignore CSD re-submissions.
+        if (mInputBufferCount >= 3 && (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
+            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+                handleEOS();
+                return;
+            }
+
+            inQueue.erase(inQueue.begin());
+            inInfo->mOwnedByUs = false;
+            notifyEmptyBufferDone(inHeader);
+            continue;
         }
 
         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
 
         if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) {
-            inQueue.erase(inQueue.begin());
-            inInfo->mOwnedByUs = false;
-            notifyEmptyBufferDone(inHeader);
-
-            outHeader->nFilledLen = 0;
-            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
-
-            outQueue.erase(outQueue.begin());
-            outInfo->mOwnedByUs = false;
-            notifyFillBufferDone(outHeader);
+            handleEOS();
             return;
         }
 
@@ -490,7 +568,6 @@
         }
 
         outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
-        outHeader->nFlags = 0;
 
         outHeader->nTimeStamp = mAnchorTimeUs +
                                 (mNumFramesOutput * 1000000ll) /
@@ -499,22 +576,20 @@
         mNumFramesOutput += numFrames;
 
         if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
-            inHeader->nFilledLen = 0;
+            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+            mHaveEOS = true;
         } else {
-            inInfo->mOwnedByUs = false;
-            inQueue.erase(inQueue.begin());
-            inInfo = NULL;
-            notifyEmptyBufferDone(inHeader);
-            inHeader = NULL;
+            outHeader->nFlags = 0;
         }
 
+        inInfo->mOwnedByUs = false;
+        inQueue.erase(inQueue.begin());
+        notifyEmptyBufferDone(inHeader);
+        ++mInputBufferCount;
+
         outInfo->mOwnedByUs = false;
         outQueue.erase(outQueue.begin());
-        outInfo = NULL;
         notifyFillBufferDone(outHeader);
-        outHeader = NULL;
-
-        ++mInputBufferCount;
     }
 }
 
@@ -526,6 +601,7 @@
         opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
         mAnchorTimeUs = 0;
         mSamplesToDiscard = mSeekPreRoll;
+        mHaveEOS = false;
     }
 }
 
@@ -542,6 +618,7 @@
     }
 
     mOutputPortSettingsChange = NONE;
+    mHaveEOS = false;
 }
 
 void SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.h b/media/libstagefright/codecs/opus/dec/SoftOpus.h
index 97f6561..91cafa1 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.h
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.h
@@ -23,7 +23,7 @@
 
 #define SOFT_OPUS_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 struct OpusMSDecoder;
 
@@ -75,6 +75,7 @@
     int64_t mSamplesToDiscard;
     int64_t mAnchorTimeUs;
     int64_t mNumFramesOutput;
+    bool mHaveEOS;
 
     enum {
         NONE,
@@ -85,6 +86,7 @@
     void initPorts();
     status_t initDecoder();
     bool isConfigured() const;
+    void handleEOS();
 
     DISALLOW_EVIL_CONSTRUCTORS(SoftOpus);
 };
diff --git a/media/libstagefright/codecs/raw/Android.bp b/media/libstagefright/codecs/raw/Android.bp
index c64027b..f21d46f 100644
--- a/media/libstagefright/codecs/raw/Android.bp
+++ b/media/libstagefright/codecs/raw/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_rawdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftRaw.cpp"],
 
@@ -27,4 +31,5 @@
         "libutils",
         "liblog",
     ],
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
index acb2b37..1a527b3 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.cpp
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -60,7 +60,7 @@
     def.eDir = OMX_DirInput;
     def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = 32 * 1024;
+    def.nBufferSize = 64 * 1024;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
@@ -78,7 +78,7 @@
     def.eDir = OMX_DirOutput;
     def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = 32 * 1024;
+    def.nBufferSize = 64 * 1024;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
@@ -100,6 +100,28 @@
 OMX_ERRORTYPE SoftRaw::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding = OMX_AUDIO_CodingPCM;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
@@ -153,6 +175,26 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->eEncoding != OMX_AUDIO_CodingPCM) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
diff --git a/media/libstagefright/codecs/raw/SoftRaw.h b/media/libstagefright/codecs/raw/SoftRaw.h
index 80906b4..ebc2741 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.h
+++ b/media/libstagefright/codecs/raw/SoftRaw.h
@@ -18,7 +18,7 @@
 
 #define SOFT_RAW_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 struct tPVMP4AudioDecoderExternal;
 
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.bp b/media/libstagefright/codecs/vorbis/dec/Android.bp
index 1a4de60..628b36c 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.bp
+++ b/media/libstagefright/codecs/vorbis/dec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_soft_vorbisdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["SoftVorbis.cpp"],
 
@@ -10,7 +14,7 @@
 
     shared_libs: [
         "libvorbisidec",
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_omx",
         "libstagefright_foundation",
         "libutils",
@@ -25,4 +29,5 @@
             "unsigned-integer-overflow",
         ],
     },
+    compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 14dd250..8912f8a 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -129,6 +129,30 @@
 OMX_ERRORTYPE SoftVorbis::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
+        case OMX_IndexParamAudioPortFormat:
+        {
+            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if (formatParams->nIndex > 0) {
+                return OMX_ErrorNoMore;
+            }
+
+            formatParams->eEncoding =
+                (formatParams->nPortIndex == 0)
+                    ? OMX_AUDIO_CodingVORBIS : OMX_AUDIO_CodingPCM;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioVorbis:
         {
             OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
@@ -221,6 +245,29 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPortFormat:
+        {
+            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
+            if (formatParams->nPortIndex > 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            if ((formatParams->nPortIndex == 0
+                        && formatParams->eEncoding != OMX_AUDIO_CodingVORBIS)
+                || (formatParams->nPortIndex == 1
+                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioVorbis:
         {
             const OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
@@ -262,7 +309,33 @@
     oggpack_readinit(bits, ref);
 }
 
-void SoftVorbis::onQueueFilled(OMX_U32 portIndex) {
+void SoftVorbis::handleEOS() {
+    List<BufferInfo *> &inQueue = getPortQueue(0);
+    List<BufferInfo *> &outQueue = getPortQueue(1);
+
+    CHECK(!inQueue.empty() && !outQueue.empty());
+
+    mSawInputEos = true;
+
+    BufferInfo *outInfo = *outQueue.begin();
+    OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+    outHeader->nFilledLen = 0;
+    outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+    outQueue.erase(outQueue.begin());
+    outInfo->mOwnedByUs = false;
+    notifyFillBufferDone(outHeader);
+    mSignalledOutputEos = true;
+
+    BufferInfo *inInfo = *inQueue.begin();
+    OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+    inQueue.erase(inQueue.begin());
+    inInfo->mOwnedByUs = false;
+    notifyEmptyBufferDone(inHeader);
+    ++mInputBufferCount;
+}
+
+void SoftVorbis::onQueueFilled(OMX_U32 /* portIndex */) {
     List<BufferInfo *> &inQueue = getPortQueue(0);
     List<BufferInfo *> &outQueue = getPortQueue(1);
 
@@ -270,69 +343,7 @@
         return;
     }
 
-    if (portIndex == 0 && mInputBufferCount < 2) {
-        BufferInfo *info = *inQueue.begin();
-        OMX_BUFFERHEADERTYPE *header = info->mHeader;
-
-        const uint8_t *data = header->pBuffer + header->nOffset;
-        size_t size = header->nFilledLen;
-        if (size < 7) {
-            ALOGE("Too small input buffer: %zu bytes", size);
-            android_errorWriteLog(0x534e4554, "27833616");
-            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
-            mSignalledError = true;
-            return;
-        }
-
-        ogg_buffer buf;
-        ogg_reference ref;
-        oggpack_buffer bits;
-
-        makeBitReader(
-                (const uint8_t *)data + 7, size - 7,
-                &buf, &ref, &bits);
-
-        if (mInputBufferCount == 0) {
-            CHECK(mVi == NULL);
-            mVi = new vorbis_info;
-            vorbis_info_init(mVi);
-
-            int ret = _vorbis_unpack_info(mVi, &bits);
-            if (ret != 0) {
-                notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
-                mSignalledError = true;
-                return;
-            }
-        } else {
-            int ret = _vorbis_unpack_books(mVi, &bits);
-            if (ret != 0) {
-                notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
-                mSignalledError = true;
-                return;
-            }
-
-            CHECK(mState == NULL);
-            mState = new vorbis_dsp_state;
-            CHECK_EQ(0, vorbis_dsp_init(mState, mVi));
-
-            if (mVi->rate != kDefaultSamplingRate ||
-                    mVi->channels != kDefaultChannelCount) {
-                ALOGV("vorbis: rate/channels changed: %ld/%d", mVi->rate, mVi->channels);
-                notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
-                mOutputPortSettingsChange = AWAITING_DISABLED;
-            }
-        }
-
-        inQueue.erase(inQueue.begin());
-        info->mOwnedByUs = false;
-        notifyEmptyBufferDone(header);
-
-        ++mInputBufferCount;
-
-        return;
-    }
-
-    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
+    while (!mSignalledOutputEos && (!inQueue.empty() || mSawInputEos) && !outQueue.empty()) {
         BufferInfo *inInfo = NULL;
         OMX_BUFFERHEADERTYPE *inHeader = NULL;
         if (!inQueue.empty()) {
@@ -346,6 +357,73 @@
         int32_t numPageSamples = 0;
 
         if (inHeader) {
+            if (mInputBufferCount < 2) {
+                const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
+                size_t size = inHeader->nFilledLen;
+
+                if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && size == 0) {
+                    handleEOS();
+                    return;
+                }
+
+                if (size < 7) {
+                    ALOGE("Too small input buffer: %zu bytes", size);
+                    android_errorWriteLog(0x534e4554, "27833616");
+                    notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+                    mSignalledError = true;
+                    return;
+                }
+
+                ogg_buffer buf;
+                ogg_reference ref;
+                oggpack_buffer bits;
+
+                makeBitReader((const uint8_t *)data + 7, size - 7, &buf, &ref, &bits);
+
+                if (mInputBufferCount == 0) {
+                    CHECK(mVi == NULL);
+                    mVi = new vorbis_info;
+                    vorbis_info_init(mVi);
+
+                    int ret = _vorbis_unpack_info(mVi, &bits);
+                    if (ret != 0) {
+                        notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
+                        mSignalledError = true;
+                        return;
+                    }
+                } else {
+                    int ret = _vorbis_unpack_books(mVi, &bits);
+                    if (ret != 0) {
+                        notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
+                        mSignalledError = true;
+                        return;
+                    }
+
+                    CHECK(mState == NULL);
+                    mState = new vorbis_dsp_state;
+                    CHECK_EQ(0, vorbis_dsp_init(mState, mVi));
+
+                    if (mVi->rate != kDefaultSamplingRate ||
+                            mVi->channels != kDefaultChannelCount) {
+                        ALOGV("vorbis: rate/channels changed: %ld/%d", mVi->rate, mVi->channels);
+                        notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+                        mOutputPortSettingsChange = AWAITING_DISABLED;
+                    }
+                }
+
+                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+                    handleEOS();
+                    return;
+                }
+
+                inQueue.erase(inQueue.begin());
+                inInfo->mOwnedByUs = false;
+                notifyEmptyBufferDone(inHeader);
+                ++mInputBufferCount;
+
+                continue;
+            }
+
             if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
                 mSawInputEos = true;
             }
@@ -359,8 +437,7 @@
                     return;
                 }
                 memcpy(&numPageSamples,
-                       inHeader->pBuffer
-                        + inHeader->nOffset + inHeader->nFilledLen - 4,
+                       inHeader->pBuffer + inHeader->nOffset + inHeader->nFilledLen - 4,
                        sizeof(numPageSamples));
 
                 if (inHeader->nOffset == 0) {
@@ -399,6 +476,14 @@
         int numFrames = 0;
 
         outHeader->nFlags = 0;
+
+        if (mState == nullptr || mVi == nullptr) {
+            notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
+            mSignalledError = true;
+            ALOGE("onQueueFilled, input does not have CSD");
+            return;
+        }
+
         int err = vorbis_dsp_synthesis(mState, &pack, 1);
         if (err != 0) {
             // FIXME temporary workaround for log spam
@@ -448,18 +533,13 @@
         if (inHeader) {
             inInfo->mOwnedByUs = false;
             inQueue.erase(inQueue.begin());
-            inInfo = NULL;
             notifyEmptyBufferDone(inHeader);
-            inHeader = NULL;
+            ++mInputBufferCount;
         }
 
         outInfo->mOwnedByUs = false;
         outQueue.erase(outQueue.begin());
-        outInfo = NULL;
         notifyFillBufferDone(outHeader);
-        outHeader = NULL;
-
-        ++mInputBufferCount;
     }
 }
 
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h
index 30d137b..5ff8ea4 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h
@@ -18,7 +18,7 @@
 
 #define SOFT_VORBIS_H_
 
-#include "SimpleSoftOMXComponent.h"
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 
 struct vorbis_dsp_state;
 struct vorbis_info;
@@ -72,6 +72,7 @@
     void initPorts();
     status_t initDecoder();
     bool isConfigured() const;
+    void handleEOS();
 
     DISALLOW_EVIL_CONSTRUCTORS(SoftVorbis);
 };
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 3ca7cc0..0982006 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -23,6 +23,7 @@
 #include <media/stagefright/MediaErrors.h>
 
 #include "libyuv/convert_from.h"
+#include "libyuv/video_common.h"
 
 #define USE_LIBYUV
 
@@ -41,17 +42,17 @@
 }
 
 bool ColorConverter::isValid() const {
-    if (mDstFormat != OMX_COLOR_Format16bitRGB565) {
-        return false;
-    }
-
     switch (mSrcFormat) {
         case OMX_COLOR_FormatYUV420Planar:
+            return mDstFormat == OMX_COLOR_Format16bitRGB565
+                    || mDstFormat == OMX_COLOR_Format32BitRGBA8888
+                    || mDstFormat == OMX_COLOR_Format32bitBGRA8888;
+
         case OMX_COLOR_FormatCbYCrY:
         case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
         case OMX_COLOR_FormatYUV420SemiPlanar:
         case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
-            return true;
+            return mDstFormat == OMX_COLOR_Format16bitRGB565;
 
         default:
             return false;
@@ -62,14 +63,43 @@
         void *bits,
         size_t width, size_t height,
         size_t cropLeft, size_t cropTop,
-        size_t cropRight, size_t cropBottom)
+        size_t cropRight, size_t cropBottom,
+        OMX_COLOR_FORMATTYPE colorFromat)
     : mBits(bits),
+      mColorFormat(colorFromat),
       mWidth(width),
       mHeight(height),
       mCropLeft(cropLeft),
       mCropTop(cropTop),
       mCropRight(cropRight),
       mCropBottom(cropBottom) {
+    switch(mColorFormat) {
+    case OMX_COLOR_Format16bitRGB565:
+        mBpp = 2;
+        mStride = 2 * mWidth;
+        break;
+
+    case OMX_COLOR_Format32bitBGRA8888:
+    case OMX_COLOR_Format32BitRGBA8888:
+        mBpp = 4;
+        mStride = 4 * mWidth;
+        break;
+
+    case OMX_COLOR_FormatYUV420Planar:
+    case OMX_COLOR_FormatCbYCrY:
+    case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+    case OMX_COLOR_FormatYUV420SemiPlanar:
+    case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+        mBpp = 1;
+        mStride = mWidth;
+        break;
+
+    default:
+        ALOGE("Unsupported color format %d", mColorFormat);
+        mBpp = 1;
+        mStride = mWidth;
+        break;
+    }
 }
 
 size_t ColorConverter::BitmapParams::cropWidth() const {
@@ -89,19 +119,15 @@
         size_t dstWidth, size_t dstHeight,
         size_t dstCropLeft, size_t dstCropTop,
         size_t dstCropRight, size_t dstCropBottom) {
-    if (mDstFormat != OMX_COLOR_Format16bitRGB565) {
-        return ERROR_UNSUPPORTED;
-    }
-
     BitmapParams src(
             const_cast<void *>(srcBits),
             srcWidth, srcHeight,
-            srcCropLeft, srcCropTop, srcCropRight, srcCropBottom);
+            srcCropLeft, srcCropTop, srcCropRight, srcCropBottom, mSrcFormat);
 
     BitmapParams dst(
             dstBits,
             dstWidth, dstHeight,
-            dstCropLeft, dstCropTop, dstCropRight, dstCropBottom);
+            dstCropLeft, dstCropTop, dstCropRight, dstCropBottom, mDstFormat);
 
     status_t err;
 
@@ -212,26 +238,104 @@
         return ERROR_UNSUPPORTED;
     }
 
-    uint16_t *dst_ptr = (uint16_t *)dst.mBits
-        + dst.mCropTop * dst.mWidth + dst.mCropLeft;
+    uint8_t *dst_ptr = (uint8_t *)dst.mBits
+        + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
 
     const uint8_t *src_y =
-        (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
+        (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;
 
     const uint8_t *src_u =
-        (const uint8_t *)src_y + src.mWidth * src.mHeight
-        + src.mCropTop * (src.mWidth / 2) + src.mCropLeft / 2;
+        (const uint8_t *)src.mBits + src.mStride * src.mHeight
+        + (src.mCropTop / 2) * (src.mStride / 2) + (src.mCropLeft / 2);
 
     const uint8_t *src_v =
-        src_u + (src.mWidth / 2) * (src.mHeight / 2);
+        src_u + (src.mStride / 2) * (src.mHeight / 2);
 
+    switch (mDstFormat) {
+    case OMX_COLOR_Format16bitRGB565:
+        libyuv::I420ToRGB565(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
+                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
+        break;
 
-    libyuv::I420ToRGB565(src_y, src.mWidth, src_u, src.mWidth / 2, src_v, src.mWidth / 2,
-            (uint8 *)dst_ptr, dst.mWidth * 2, dst.mWidth, dst.mHeight);
+    case OMX_COLOR_Format32BitRGBA8888:
+        libyuv::ConvertFromI420(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
+                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight(), libyuv::FOURCC_ABGR);
+        break;
+
+    case OMX_COLOR_Format32bitBGRA8888:
+        libyuv::ConvertFromI420(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
+                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight(), libyuv::FOURCC_ARGB);
+        break;
+
+    default:
+        return ERROR_UNSUPPORTED;
+    }
 
     return OK;
 }
 
+void ColorConverter::writeToDst(
+        void *dst_ptr, uint8_t *kAdjustedClip, bool uncropped,
+        signed r1, signed g1, signed b1,
+        signed r2, signed g2, signed b2) {
+    switch (mDstFormat) {
+    case OMX_COLOR_Format16bitRGB565:
+    {
+        uint32_t rgb1 =
+            ((kAdjustedClip[r1] >> 3) << 11)
+            | ((kAdjustedClip[g1] >> 2) << 5)
+            | (kAdjustedClip[b1] >> 3);
+
+        if (uncropped) {
+            uint32_t rgb2 =
+                ((kAdjustedClip[r2] >> 3) << 11)
+                | ((kAdjustedClip[g2] >> 2) << 5)
+                | (kAdjustedClip[b2] >> 3);
+
+            *(uint32_t *)dst_ptr = (rgb2 << 16) | rgb1;
+        } else {
+            *(uint16_t *)dst_ptr = rgb1;
+        }
+        break;
+    }
+    case OMX_COLOR_Format32BitRGBA8888:
+    {
+        ((uint32_t *)dst_ptr)[0] =
+                (kAdjustedClip[r1])
+                | (kAdjustedClip[g1] << 8)
+                | (kAdjustedClip[b1] << 16)
+                | (0xFF << 24);
+
+        if (uncropped) {
+            ((uint32_t *)dst_ptr)[1] =
+                    (kAdjustedClip[r2])
+                    | (kAdjustedClip[g2] << 8)
+                    | (kAdjustedClip[b2] << 16)
+                    | (0xFF << 24);
+        }
+        break;
+    }
+    case OMX_COLOR_Format32bitBGRA8888:
+    {
+        ((uint32_t *)dst_ptr)[0] =
+                (kAdjustedClip[b1])
+                | (kAdjustedClip[g1] << 8)
+                | (kAdjustedClip[r1] << 16)
+                | (0xFF << 24);
+
+        if (uncropped) {
+            ((uint32_t *)dst_ptr)[1] =
+                    (kAdjustedClip[b2])
+                    | (kAdjustedClip[g2] << 8)
+                    | (kAdjustedClip[r2] << 16)
+                    | (0xFF << 24);
+        }
+        break;
+    }
+    default:
+        break;
+    }
+}
 status_t ColorConverter::convertYUV420Planar(
         const BitmapParams &src, const BitmapParams &dst) {
     if (!((src.mCropLeft & 1) == 0
@@ -242,18 +346,18 @@
 
     uint8_t *kAdjustedClip = initClip();
 
-    uint16_t *dst_ptr = (uint16_t *)dst.mBits
-        + dst.mCropTop * dst.mWidth + dst.mCropLeft;
+    uint8_t *dst_ptr = (uint8_t *)dst.mBits
+        + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
 
     const uint8_t *src_y =
-        (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
+        (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;
 
     const uint8_t *src_u =
-        (const uint8_t *)src_y + src.mWidth * src.mHeight
-        + src.mCropTop * (src.mWidth / 2) + src.mCropLeft / 2;
+        (const uint8_t *)src.mBits + src.mStride * src.mHeight
+        + (src.mCropTop / 2) * (src.mStride / 2) + src.mCropLeft / 2;
 
     const uint8_t *src_v =
-        src_u + (src.mWidth / 2) * (src.mHeight / 2);
+        src_u + (src.mStride / 2) * (src.mHeight / 2);
 
     for (size_t y = 0; y < src.cropHeight(); ++y) {
         for (size_t x = 0; x < src.cropWidth(); x += 2) {
@@ -296,31 +400,19 @@
             signed g2 = (tmp2 + v_g + u_g) / 256;
             signed r2 = (tmp2 + v_r) / 256;
 
-            uint32_t rgb1 =
-                ((kAdjustedClip[r1] >> 3) << 11)
-                | ((kAdjustedClip[g1] >> 2) << 5)
-                | (kAdjustedClip[b1] >> 3);
-
-            uint32_t rgb2 =
-                ((kAdjustedClip[r2] >> 3) << 11)
-                | ((kAdjustedClip[g2] >> 2) << 5)
-                | (kAdjustedClip[b2] >> 3);
-
-            if (x + 1 < src.cropWidth()) {
-                *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1;
-            } else {
-                dst_ptr[x] = rgb1;
-            }
+            bool uncropped = x + 1 < src.cropWidth();
+            (void)writeToDst(dst_ptr + x * dst.mBpp,
+                    kAdjustedClip, uncropped, r1, g1, b1, r2, g2, b2);
         }
 
-        src_y += src.mWidth;
+        src_y += src.mStride;
 
         if (y & 1) {
-            src_u += src.mWidth / 2;
-            src_v += src.mWidth / 2;
+            src_u += src.mStride / 2;
+            src_v += src.mStride / 2;
         }
 
-        dst_ptr += dst.mWidth;
+        dst_ptr += dst.mStride;
     }
 
     return OK;
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index ce164a2..829f403 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -34,20 +34,21 @@
             <Feature name="adaptive-playback" />
         </MediaCodec>
         <MediaCodec name="OMX.google.h264.decoder" type="video/avc">
-            <!-- profiles and levels:  ProfileHigh : Level41 -->
-            <Limit name="size" min="16x16" max="1920x1088" />
+            <!-- profiles and levels:  ProfileHigh : Level52 -->
+            <Limit name="size" min="2x2" max="4080x4080" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="16x16" />
-            <Limit name="blocks-per-second" range="1-244800" />
-            <Limit name="bitrate" range="1-12000000" />
+            <Limit name="block-count" range="1-32768" /> <!-- max 4096x2048 equivalent -->
+            <Limit name="blocks-per-second" range="1-1966080" />
+            <Limit name="bitrate" range="1-48000000" />
             <Feature name="adaptive-playback" />
         </MediaCodec>
         <MediaCodec name="OMX.google.hevc.decoder" type="video/hevc">
             <!-- profiles and levels:  ProfileMain : MainTierLevel51 -->
-            <Limit name="size" min="2x2" max="2048x2048" />
+            <Limit name="size" min="2x2" max="4096x4096" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="8x8" />
-            <Limit name="block-count" range="1-139264" />
+            <Limit name="block-count" range="1-196608" /> <!-- max 4096x3072 -->
             <Limit name="blocks-per-second" range="1-2000000" />
             <Limit name="bitrate" range="1-10000000" />
             <Feature name="adaptive-playback" />
@@ -56,6 +57,7 @@
             <Limit name="size" min="2x2" max="2048x2048" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="16x16" />
+            <Limit name="block-count" range="1-16384" />
             <Limit name="blocks-per-second" range="1-1000000" />
             <Limit name="bitrate" range="1-40000000" />
             <Feature name="adaptive-playback" />
@@ -64,6 +66,7 @@
             <Limit name="size" min="2x2" max="2048x2048" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="16x16" />
+            <Limit name="block-count" range="1-16384" />
             <Limit name="blocks-per-second" range="1-500000" />
             <Limit name="bitrate" range="1-40000000" />
             <Feature name="adaptive-playback" />
@@ -79,10 +82,11 @@
         </MediaCodec>
         <MediaCodec name="OMX.google.h264.encoder" type="video/avc">
             <!-- profiles and levels:  ProfileBaseline : Level41 -->
-            <Limit name="size" min="16x16" max="1920x1088" />
+            <Limit name="size" min="16x16" max="2048x2048" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="16x16" />
-            <Limit name="blocks-per-second" range="1-244800" />
+            <Limit name="block-count" range="1-8192" /> <!-- max 2048x1024 -->
+            <Limit name="blocks-per-second" range="1-245760" />
             <Limit name="bitrate" range="1-12000000" />
             <Feature name="intra-refresh" />
         </MediaCodec>
@@ -98,6 +102,9 @@
             <!-- profiles and levels:  ProfileMain : Level_Version0-3 -->
             <Limit name="size" min="2x2" max="2048x2048" />
             <Limit name="alignment" value="2x2" />
+            <Limit name="block-size" value="16x16" />
+            <!-- 2016 devices can encode at about 10fps at this block count -->
+            <Limit name="block-count" range="1-16384" />
             <Limit name="bitrate" range="1-40000000" />
             <Feature name="bitrate-modes" value="VBR,CBR" />
         </MediaCodec>
@@ -105,6 +112,9 @@
             <!-- profiles and levels:  ProfileMain : Level_Version0-3 -->
             <Limit name="size" min="2x2" max="2048x2048" />
             <Limit name="alignment" value="2x2" />
+            <Limit name="block-size" value="16x16" />
+            <!-- 2016 devices can encode at about 8fps at this block count -->
+            <Limit name="block-count" range="1-3600" /> <!-- max 1280x720 -->
             <Limit name="bitrate" range="1-40000000" />
             <Feature name="bitrate-modes" value="VBR,CBR" />
         </MediaCodec>
diff --git a/media/libstagefright/data/media_codecs_google_video_le.xml b/media/libstagefright/data/media_codecs_google_video_le.xml
index 034a038..d7c6570 100644
--- a/media/libstagefright/data/media_codecs_google_video_le.xml
+++ b/media/libstagefright/data/media_codecs_google_video_le.xml
@@ -34,22 +34,22 @@
             <Feature name="adaptive-playback" />
         </MediaCodec>
         <MediaCodec name="OMX.google.h264.decoder" type="video/avc">
-            <!-- profiles and levels:  ProfileBaseline : Level51 -->
+            <!-- profiles and levels:  ProfileHigh : Level51 -->
             <Limit name="size" min="2x2" max="2048x2048" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="16x16" />
-            <Limit name="block-count" range="1-8160" />
-            <Limit name="blocks-per-second" range="1-489600" />
+            <Limit name="block-count" range="1-16384" />
+            <Limit name="blocks-per-second" range="1-491520" />
             <Limit name="bitrate" range="1-40000000" />
             <Feature name="adaptive-playback" />
         </MediaCodec>
         <MediaCodec name="OMX.google.hevc.decoder" type="video/hevc">
             <!-- profiles and levels:  ProfileMain : MainTierLevel51 -->
-            <Limit name="size" min="2x2" max="1280x1280" />
+            <Limit name="size" min="2x2" max="2048x2048" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="8x8" />
-            <Limit name="block-count" range="1-139264" />
-            <Limit name="blocks-per-second" range="1-432000" />
+            <Limit name="block-count" range="1-65536" />
+            <Limit name="blocks-per-second" range="1-491520" />
             <Limit name="bitrate" range="1-5000000" />
             <Feature name="adaptive-playback" />
         </MediaCodec>
@@ -57,7 +57,7 @@
             <Limit name="size" min="2x2" max="2048x2048" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="16x16" />
-            <Limit name="block-count" range="1-8160" />
+            <Limit name="block-count" range="1-8192" /> <!-- max 2048x1024 -->
             <Limit name="blocks-per-second" range="1-500000" />
             <Limit name="bitrate" range="1-40000000" />
             <Feature name="adaptive-playback" />
@@ -66,7 +66,7 @@
             <Limit name="size" min="2x2" max="1280x1280" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="16x16" />
-            <Limit name="block-count" range="1-3600" />
+            <Limit name="block-count" range="1-3600" /> <!-- max 1280x720 -->
             <Limit name="blocks-per-second" range="1-108000" />
             <Limit name="bitrate" range="1-5000000" />
             <Feature name="adaptive-playback" />
@@ -81,12 +81,14 @@
             <Limit name="bitrate" range="1-128000" />
         </MediaCodec>
         <MediaCodec name="OMX.google.h264.encoder" type="video/avc">
-            <!-- profiles and levels:  ProfileBaseline : Level2 -->
-            <Limit name="size" min="16x16" max="896x896" />
-            <Limit name="alignment" value="16x16" />
+            <!-- profiles and levels:  ProfileBaseline : Level3 -->
+            <Limit name="size" min="16x16" max="1808x1808" />
+            <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="16x16" />
-            <Limit name="blocks-per-second" range="1-11880" />
+            <Limit name="block-count" range="1-1620" />
+            <Limit name="blocks-per-second" range="1-40500" />
             <Limit name="bitrate" range="1-2000000" />
+            <Feature name="intra-refresh" />
         </MediaCodec>
         <MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es">
             <!-- profiles and levels:  ProfileCore : Level2 -->
@@ -100,7 +102,8 @@
             <!-- profiles and levels:  ProfileMain : Level_Version0-3 -->
             <Limit name="size" min="2x2" max="1280x1280" />
             <Limit name="alignment" value="2x2" />
-            <Limit name="block-count" range="1-3600" />
+            <Limit name="block-size" value="16x16" />
+            <Limit name="block-count" range="1-3600" /> <!-- max 1280x720 -->
             <Limit name="bitrate" range="1-20000000" />
             <Feature name="bitrate-modes" value="VBR,CBR" />
         </MediaCodec>
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index 284c25f..1b9fe0f 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -1,5 +1,9 @@
 cc_library_shared {
     name: "libstagefright_flacdec",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "FLACDecoder.cpp",
@@ -31,4 +35,5 @@
         "libstagefright_foundation",
         "libutils",
     ],
+    header_libs: ["libmedia_headers"],
 }
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index 657f02c..221af1d 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -1,3 +1,9 @@
+cc_library_headers {
+    name: "libstagefright_foundation_headers",
+    export_include_dirs: ["include"],
+    vendor_available: true,
+}
+
 cc_library_shared {
     name: "libstagefright_foundation",
     vendor_available: true,
@@ -13,12 +19,13 @@
         "include/media/stagefright/foundation",
     ],
 
-    export_include_dirs: [
-        "include",
-    ],
-
     header_libs: [
         "libhardware_headers",
+        "libstagefright_foundation_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libstagefright_foundation_headers",
     ],
 
     export_shared_lib_headers: [
diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp
index cc89064..8f32582 100644
--- a/media/libstagefright/foundation/base64.cpp
+++ b/media/libstagefright/foundation/base64.cpp
@@ -23,6 +23,7 @@
 
 sp<ABuffer> decodeBase64(const AString &s) {
     size_t n = s.size();
+
     if ((n % 4) != 0) {
         return NULL;
     }
@@ -45,7 +46,6 @@
     size_t outLen = (n / 4) * 3 - padding;
 
     sp<ABuffer> buffer = new ABuffer(outLen);
-
     uint8_t *out = buffer->data();
     if (out == NULL || buffer->size() < outLen) {
         return NULL;
@@ -61,9 +61,9 @@
             value = 26 + c - 'a';
         } else if (c >= '0' && c <= '9') {
             value = 52 + c - '0';
-        } else if (c == '+') {
+        } else if (c == '+' || c == '-') {
             value = 62;
-        } else if (c == '/') {
+        } else if (c == '/' || c == '_') {
             value = 63;
         } else if (c != '=') {
             return NULL;
@@ -144,4 +144,26 @@
     }
 }
 
+void encodeBase64Url(
+        const void *_data, size_t size, AString *out) {
+    encodeBase64(_data, size, out);
+
+    if ((-1 != out->find("+")) || (-1 != out->find("/"))) {
+        size_t outLen = out->size();
+        char *base64url = new char[outLen];
+        for (size_t i = 0; i < outLen; ++i) {
+            if (out->c_str()[i] == '+')
+                base64url[i] = '-';
+            else if (out->c_str()[i] == '/')
+                base64url[i] = '_';
+            else
+                base64url[i] = out->c_str()[i];
+        }
+
+        out->setTo(base64url, outLen);
+        delete[] base64url;
+    }
+}
+
+
 }  // namespace android
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h b/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h
index e340b89..abc95e0 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h
@@ -28,6 +28,8 @@
 sp<ABuffer> decodeBase64(const AString &s);
 void encodeBase64(const void *data, size_t size, AString *out);
 
+void encodeBase64Url(const void *data, size_t size, AString *out);
+
 }  // namespace android
 
 #endif  // BASE_64_H_
diff --git a/media/libstagefright/foundation/tests/Android.mk b/media/libstagefright/foundation/tests/Android.mk
index d741c6f..a9e3c76 100644
--- a/media/libstagefright/foundation/tests/Android.mk
+++ b/media/libstagefright/foundation/tests/Android.mk
@@ -9,11 +9,13 @@
 
 LOCAL_SRC_FILES := \
 	AData_test.cpp \
+	Base64_test.cpp \
 	Flagged_test.cpp \
 	TypeTraits_test.cpp \
 	Utils_test.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
+	liblog \
 	libstagefright_foundation \
 	libutils \
 
diff --git a/media/libstagefright/foundation/tests/Base64_test.cpp b/media/libstagefright/foundation/tests/Base64_test.cpp
new file mode 100644
index 0000000..7a4289e
--- /dev/null
+++ b/media/libstagefright/foundation/tests/Base64_test.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <utils/Log.h>
+
+#include "gtest/gtest.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/AStringUtils.h>
+#include <media/stagefright/foundation/base64.h>
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace {
+const android::String8 kBase64Padding("=");
+};
+
+namespace android {
+
+class Base64Test : public ::testing::Test {
+};
+
+void verifyDecode(const AString* expected, const AString* in) {
+    size_t numTests = 0;
+    while (!expected[numTests].empty())
+        ++numTests;
+
+    for (size_t i = 0; i < numTests; ++i) {
+        // Since android::decodeBase64() requires padding characters,
+        // add them so length of encoded text is exactly a multiple of 4.
+        int remainder = in[i].size() % 4;
+        String8 paddedText(in[i].c_str());
+        if (remainder > 0) {
+            for (int i = 0; i < 4 - remainder; ++i) {
+                paddedText.append(kBase64Padding);
+            }
+        }
+        sp<ABuffer> result = decodeBase64(AString(paddedText.string()));
+
+        ASSERT_EQ(AStringUtils::Compare(expected[i].c_str(),
+                reinterpret_cast<char*>(result->data()),
+                expected[i].size(), false), 0);
+    }
+}
+
+void verifyEncode(const AString* expected, const AString* in) {
+    size_t numTests = 0;
+    while (!expected[numTests].empty())
+        ++numTests;
+
+    AString out = AString("");
+    for (size_t i = 0; i < numTests; ++i) {
+        encodeBase64Url(in[i].c_str(), in[i].size(), &out);
+
+        ASSERT_EQ(AStringUtils::Compare(expected[i].c_str(), out.c_str(),
+                expected[i].size(), false), 0);
+    }
+}
+
+TEST_F(Base64Test, TestDecodeBase64) {
+    const AString base64[] = {
+        AString("SGVsbG8gRnJpZW5kIQ"),
+        AString("R29vZCBkYXkh"),
+        AString("")  // string to signal end of array
+    };
+
+    const AString clearText[] = {
+        AString("Hello Friend!"),
+        AString("Good day!"),
+        AString("")
+    };
+
+    verifyDecode(clearText, base64);
+}
+
+TEST_F(Base64Test, TestDecodeBase64Url) {
+    const AString base64Url[] = {
+        AString("SGVsbG8gRnJpZW5kICE-Pw"),
+        AString("SGVsbG8gRnJpZW5kICE_"),
+        AString("SGVsbG8gPz4-IEZyaWVuZCA_Pg"),
+        AString("")
+    };
+
+    const AString clearText[] = {
+        AString("Hello Friend !>?"),
+        AString("Hello Friend !?"),
+        AString("Hello ?>> Friend ?>"),
+        AString("")
+    };
+
+    verifyDecode(clearText, base64Url);
+}
+
+TEST_F(Base64Test, TestDecodeMalformedBase64) {
+    const AString base64Url[] = {
+        AString("1?GawgguFyGrWKav7AX4VKUg"),  // fail on parsing
+        AString("GawgguFyGrWKav7AX4V???"),    // fail on length not multiple of 4
+        AString("GawgguFyGrWKav7AX4VKUg"),    // ditto
+    };
+
+    for (size_t i = 0; i < 3; ++i) {
+        sp<ABuffer> result = decodeBase64(AString(base64Url[i]));
+        EXPECT_TRUE(result == nullptr);
+    }
+}
+
+TEST_F(Base64Test, TestEncodeBase64) {
+    const AString clearText[] = {
+        AString("Hello Friend!"),
+        AString("Good day!"),
+        AString("")
+    };
+
+    const AString base64[] = {
+        AString("SGVsbG8gRnJpZW5kIQ=="),
+        AString("R29vZCBkYXkh"),
+        AString("")
+    };
+
+    verifyEncode(base64, clearText);
+}
+
+TEST_F(Base64Test, TestEncodeBase64Url) {
+    const AString clearText[] = {
+        AString("Hello Friend !>?"),
+        AString("Hello Friend !?"),
+        AString("Hello ?>> Friend ?>"),
+        AString("")
+    };
+
+    const AString base64Url[] = {
+        AString("SGVsbG8gRnJpZW5kICE-Pw=="),
+        AString("SGVsbG8gRnJpZW5kICE_"),
+        AString("SGVsbG8gPz4-IEZyaWVuZCA_Pg"),
+        AString("")
+    };
+
+    verifyEncode(base64Url, clearText);
+}
+
+} // namespace android
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index 0da2e81..f253a52 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -30,6 +30,8 @@
 
 namespace android {
 
+using hardware::hidl_memory;
+
 /**
  * BufferChannelBase implementation for ACodec.
  */
@@ -117,6 +119,7 @@
     sp<MemoryDealer> mDealer;
     sp<IMemory> mDecryptDestination;
     int32_t mHeapSeqNum;
+    hidl_memory mHidlMemory;
 
     // These should only be accessed via std::atomic_* functions.
     //
diff --git a/media/libstagefright/include/ItemTable.h b/media/libstagefright/include/ItemTable.h
new file mode 100644
index 0000000..5a6af5e
--- /dev/null
+++ b/media/libstagefright/include/ItemTable.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ITEM_TABLE_H_
+#define ITEM_TABLE_H_
+
+#include <set>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class DataSource;
+class MetaData;
+
+namespace heif {
+
+struct AssociationEntry;
+struct ImageItem;
+struct ItemLoc;
+struct ItemInfo;
+struct ItemProperty;
+struct ItemReference;
+
+/*
+ * ItemTable keeps track of all image items (including coded images, grids and
+ * tiles) inside a HEIF still image (ISO/IEC FDIS 23008-12.2:2017(E)).
+ */
+
+class ItemTable : public RefBase {
+public:
+    explicit ItemTable(const sp<DataSource> &source);
+
+    status_t parse(uint32_t type, off64_t offset, size_t size);
+
+    bool isValid() { return mImageItemsValid; }
+    sp<MetaData> getImageMeta();
+    uint32_t countImages() const;
+    status_t findPrimaryImage(uint32_t *imageIndex);
+    status_t findThumbnail(uint32_t *thumbnailIndex);
+    status_t getImageOffsetAndSize(
+            uint32_t *imageIndex, off64_t *offset, size_t *size);
+
+protected:
+    ~ItemTable();
+
+private:
+    sp<DataSource> mDataSource;
+
+    KeyedVector<uint32_t, ItemLoc> mItemLocs;
+    Vector<ItemInfo> mItemInfos;
+    Vector<AssociationEntry> mAssociations;
+    Vector<sp<ItemProperty> > mItemProperties;
+    Vector<sp<ItemReference> > mItemReferences;
+
+    uint32_t mPrimaryItemId;
+    off64_t mIdatOffset;
+    size_t mIdatSize;
+
+    std::set<uint32_t> mRequiredBoxes;
+    std::set<uint32_t> mBoxesSeen;
+
+    bool mImageItemsValid;
+    uint32_t mCurrentImageIndex;
+    KeyedVector<uint32_t, ImageItem> mItemIdToImageMap;
+
+    status_t parseIlocBox(off64_t offset, size_t size);
+    status_t parseIinfBox(off64_t offset, size_t size);
+    status_t parsePitmBox(off64_t offset, size_t size);
+    status_t parseIprpBox(off64_t offset, size_t size);
+    status_t parseIdatBox(off64_t offset, size_t size);
+    status_t parseIrefBox(off64_t offset, size_t size);
+
+    void attachProperty(const AssociationEntry &association);
+    status_t buildImageItemsIfPossible(uint32_t type);
+
+    DISALLOW_EVIL_CONSTRUCTORS(ItemTable);
+};
+
+} // namespace heif
+} // namespace android
+
+#endif  // ITEM_TABLE_H_
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
index 2a75298..ac93b5e 100644
--- a/media/libstagefright/include/MPEG2TSExtractor.h
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -45,7 +45,7 @@
 
     virtual sp<MetaData> getMetaData();
 
-    virtual status_t setMediaCas(const sp<ICas> &cas) override;
+    virtual status_t setMediaCas(const HInterfaceToken &casToken) override;
 
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG2TSExtractor"; }
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 1efe6b9..214a3de 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -28,11 +28,14 @@
 #include <utils/String8.h>
 
 namespace android {
-
 struct AMessage;
 class DataSource;
 class SampleTable;
 class String8;
+namespace heif {
+class ItemTable;
+}
+using heif::ItemTable;
 
 struct SidxEntry {
     size_t mSize;
@@ -59,6 +62,7 @@
     virtual sp<MetaData> getMetaData();
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG4Extractor"; }
+    virtual void release();
 
     // for DRM
     virtual char* getDrmTrackInfo(size_t trackID, int *len);
@@ -100,6 +104,7 @@
     status_t mInitCheck;
     uint32_t mHeaderTimescale;
     bool mIsQT;
+    bool mIsHEIF;
 
     Track *mFirstTrack, *mLastTrack;
 
@@ -137,6 +142,8 @@
     SINF *mFirstSINF;
 
     bool mIsDrm;
+    sp<ItemTable> mItemTable;
+
     status_t parseDrmSINF(off64_t *offset, off64_t data_offset);
 
     status_t parseTrackHeader(off64_t data_offset, off64_t data_size);
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h
index b7ac718..277eb3e 100644
--- a/media/libstagefright/include/StagefrightMetadataRetriever.h
+++ b/media/libstagefright/include/StagefrightMetadataRetriever.h
@@ -38,9 +38,9 @@
             const KeyedVector<String8, String8> *headers);
 
     virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t setDataSource(const sp<DataSource>& source);
+    virtual status_t setDataSource(const sp<DataSource>& source, const char *mime);
 
-    virtual VideoFrame *getFrameAtTime(int64_t timeUs, int option);
+    virtual VideoFrame *getFrameAtTime(int64_t timeUs, int option, int colorFormat, bool metaOnly);
     virtual MediaAlbumArt *extractAlbumArt();
     virtual const char *extractMetadata(int keyCode);
 
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index d049df5..424246d 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <android/native_window.h>
 #include <media/hardware/MetadataBufferType.h>
+#include <media/MediaCodecInfo.h>
 #include <media/IOMX.h>
 #include <media/stagefright/foundation/AHierarchicalStateMachine.h>
 #include <media/stagefright/CodecBase.h>
@@ -30,6 +31,8 @@
 #include <OMX_Audio.h>
 #include <hardware/gralloc.h>
 #include <nativebase/nativebase.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
 
 #define TRACK_BUFFER_TIMING     0
 
@@ -42,20 +45,6 @@
 struct DescribeColorFormat2Params;
 struct DataConverter;
 
-// Treble shared memory
-namespace hidl {
-namespace allocator {
-namespace V1_0 {
-struct IAllocator;
-} // V1_0
-} // allocator
-namespace memory {
-namespace V1_0 {
-struct IMemory;
-} // V1_0
-} // memory
-} // hidl
-
 typedef hidl::allocator::V1_0::IAllocator TAllocator;
 typedef hidl::memory::V1_0::IMemory TMemory;
 
@@ -72,9 +61,10 @@
     virtual void initiateStart();
     virtual void initiateShutdown(bool keepComponentAllocated = false);
 
-    virtual status_t queryCapabilities(
-            const AString &name, const AString &mime, bool isEncoder,
-            sp<MediaCodecInfo::Capabilities> *caps);
+    status_t queryCapabilities(
+            const char* owner, const char* name,
+            const char* mime, bool isEncoder,
+            MediaCodecInfo::CapabilitiesWriter* caps);
 
     virtual status_t setSurface(const sp<Surface> &surface);
 
@@ -94,7 +84,8 @@
     // some OMX components as auto level, and by others as invalid level.
     static int /* OMX_VIDEO_AVCLEVELTYPE */ getAVCLevelFor(
             int width, int height, int rate, int bitrate,
-            OMX_VIDEO_AVCPROFILETYPE profile = OMX_VIDEO_AVCProfileBaseline);
+            OMX_VIDEO_AVCPROFILEEXTTYPE profile =
+                (OMX_VIDEO_AVCPROFILEEXTTYPE)OMX_VIDEO_AVCProfileBaseline);
 
     // Quirk still supported, even though deprecated
     enum Quirks {
diff --git a/media/libstagefright/include/media/stagefright/CameraSource.h b/media/libstagefright/include/media/stagefright/CameraSource.h
index 2aaa884..d6149c0 100644
--- a/media/libstagefright/include/media/stagefright/CameraSource.h
+++ b/media/libstagefright/include/media/stagefright/CameraSource.h
@@ -29,7 +29,7 @@
 #include <utils/List.h>
 #include <utils/RefBase.h>
 #include <utils/String16.h>
-#include <MetadataBufferType.h>
+#include <media/hardware/MetadataBufferType.h>
 
 namespace android {
 
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index 0dd77ba..9197f7b 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -24,27 +24,31 @@
 
 #define STRINGIFY_ENUMS
 
-#include <media/ICrypto.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/hardware/HardwareAPI.h>
 #include <media/IOMX.h>
 #include <media/MediaCodecInfo.h>
-#include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/foundation/AHandler.h>
 #include <media/stagefright/foundation/ColorUtils.h>
-#include <media/hardware/HardwareAPI.h>
-
+#include <media/stagefright/MediaErrors.h>
+#include <system/graphics.h>
 #include <utils/NativeHandle.h>
 
-#include <system/graphics.h>
-#include <android/media/IDescrambler.h>
-
 namespace android {
-using namespace media;
 class BufferChannelBase;
 struct BufferProducerWrapper;
 class MediaCodecBuffer;
 struct PersistentSurface;
 struct RenderedFrameInfo;
 class Surface;
+struct ICrypto;
+namespace hardware {
+namespace cas {
+namespace native {
+namespace V1_0 {
+struct IDescrambler;
+}}}}
+using hardware::cas::native::V1_0::IDescrambler;
 
 struct CodecBase : public AHandler, /* static */ ColorUtils {
     /**
@@ -209,10 +213,6 @@
     // require an explicit message handler
     virtual void onMessageReceived(const sp<AMessage> &msg) = 0;
 
-    virtual status_t queryCapabilities(
-            const AString& /*name*/, const AString& /*mime*/, bool /*isEncoder*/,
-            sp<MediaCodecInfo::Capabilities>* /*caps*/ /* nonnull */) { return INVALID_OPERATION; }
-
     virtual status_t setSurface(const sp<Surface>& /*surface*/) { return INVALID_OPERATION; }
 
     virtual void signalFlush() = 0;
@@ -256,13 +256,9 @@
         mCallback = std::move(callback);
     }
 
-    inline void setCrypto(const sp<ICrypto> &crypto) {
-        mCrypto = crypto;
-    }
+    void setCrypto(const sp<ICrypto> &crypto);
 
-    inline void setDescrambler(const sp<IDescrambler> &descrambler) {
-        mDescrambler = descrambler;
-    }
+    void setDescrambler(const sp<IDescrambler> &descrambler);
 
     /**
      * Queue an input buffer into the buffer channel.
diff --git a/media/libstagefright/include/media/stagefright/ColorConverter.h b/media/libstagefright/include/media/stagefright/ColorConverter.h
index 270c809..7ac9b37 100644
--- a/media/libstagefright/include/media/stagefright/ColorConverter.h
+++ b/media/libstagefright/include/media/stagefright/ColorConverter.h
@@ -49,14 +49,17 @@
                 void *bits,
                 size_t width, size_t height,
                 size_t cropLeft, size_t cropTop,
-                size_t cropRight, size_t cropBottom);
+                size_t cropRight, size_t cropBottom,
+                OMX_COLOR_FORMATTYPE colorFromat);
 
         size_t cropWidth() const;
         size_t cropHeight() const;
 
         void *mBits;
+        OMX_COLOR_FORMATTYPE mColorFormat;
         size_t mWidth, mHeight;
         size_t mCropLeft, mCropTop, mCropRight, mCropBottom;
+        size_t mBpp, mStride;
     };
 
     OMX_COLOR_FORMATTYPE mSrcFormat, mDstFormat;
@@ -82,6 +85,10 @@
     status_t convertTIYUV420PackedSemiPlanar(
             const BitmapParams &src, const BitmapParams &dst);
 
+    void writeToDst(void *dst_ptr, uint8_t *kAdjustedClip, bool uncropped,
+            signed r1, signed g1, signed b1,
+            signed r2, signed g2, signed b2);
+
     ColorConverter(const ColorConverter &);
     ColorConverter &operator=(const ColorConverter &);
 };
diff --git a/media/libstagefright/include/media/stagefright/DataSource.h b/media/libstagefright/include/media/stagefright/DataSource.h
index 63eccea..bd863ba 100644
--- a/media/libstagefright/include/media/stagefright/DataSource.h
+++ b/media/libstagefright/include/media/stagefright/DataSource.h
@@ -73,6 +73,11 @@
     bool getUInt32(off64_t offset, uint32_t *x);
     bool getUInt64(off64_t offset, uint64_t *x);
 
+    // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
+    bool getUInt16Var(off64_t offset, uint16_t *x, size_t size);
+    bool getUInt32Var(off64_t offset, uint32_t *x, size_t size);
+    bool getUInt64Var(off64_t offset, uint64_t *x, size_t size);
+
     // Reads in "count" entries of type T into vector *x.
     // Returns true if "count" entries can be read.
     // If fewer than "count" entries can be read, return false. In this case,
diff --git a/media/libstagefright/include/media/stagefright/FrameRenderTracker.h b/media/libstagefright/include/media/stagefright/FrameRenderTracker.h
index 044699c..c14755a 100644
--- a/media/libstagefright/include/media/stagefright/FrameRenderTracker.h
+++ b/media/libstagefright/include/media/stagefright/FrameRenderTracker.h
@@ -23,6 +23,8 @@
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AString.h>
+#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
 
 #include <list>
 
@@ -30,9 +32,6 @@
 
 namespace android {
 
-class Fence;
-class GraphicBuffer;
-
 // Tracks the render information about a frame. Frames go through several states while
 // the render information is tracked:
 //
diff --git a/media/libstagefright/include/media/stagefright/MPEG4Writer.h b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
index dd357cc..1c7b4a6 100644
--- a/media/libstagefright/include/media/stagefright/MPEG4Writer.h
+++ b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
@@ -204,7 +204,10 @@
     void lock();
     void unlock();
 
-    void initInternal(int fd);
+    // Init all the internal variables for each recording session. Some variables
+    // will only need to be set for the first recording session and they will stay
+    // the same across all the recording sessions.
+    void initInternal(int fd, bool isFirstSession);
 
     // Acquire lock before calling these methods
     off64_t addSample_l(MediaBuffer *buffer);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 4140266..1030407 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -47,10 +47,13 @@
 struct PersistentSurface;
 class SoftwareRenderer;
 class Surface;
-namespace media {
-class IDescrambler;
-};
-using namespace media;
+namespace hardware {
+namespace cas {
+namespace native {
+namespace V1_0 {
+struct IDescrambler;
+}}}}
+using hardware::cas::native::V1_0::IDescrambler;
 
 struct MediaCodec : public AHandler {
     enum ConfigureFlags {
@@ -84,11 +87,6 @@
 
     static sp<PersistentSurface> CreatePersistentInputSurface();
 
-    // utility method to query capabilities
-    static status_t QueryCapabilities(
-            const AString &name, const AString &mime, bool isEncoder,
-            sp<MediaCodecInfo::Capabilities> *caps /* nonnull */);
-
     status_t configure(
             const sp<AMessage> &format,
             const sp<Surface> &nativeWindow,
@@ -316,6 +314,8 @@
     SoftwareRenderer *mSoftRenderer;
 
     MediaAnalyticsItem *mAnalyticsItem;
+    void initAnalyticsItem();
+    void flushAnalyticsItem();
 
     sp<AMessage> mOutputFormat;
     sp<AMessage> mInputFormat;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index 430bc16..f2bd496 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -21,7 +21,6 @@
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AString.h>
 #include <media/IMediaCodecList.h>
-#include <media/IOMX.h>
 #include <media/MediaCodecInfo.h>
 
 #include <sys/types.h>
@@ -36,6 +35,8 @@
 
 struct AMessage;
 
+struct MediaCodecListBuilderBase;
+
 struct MediaCodecList : public BnMediaCodecList {
     static sp<IMediaCodecList> getInstance();
 
@@ -51,7 +52,7 @@
             ALOGE("b/24445127");
             return NULL;
         }
-        return mCodecInfos.itemAt(index);
+        return mCodecInfos[index];
     }
 
     virtual const sp<AMessage> getGlobalSettings() const;
@@ -62,9 +63,6 @@
     // only to be used by getLocalInstance
     static void *profilerThreadWrapper(void * /*arg*/);
 
-    // only to be used by MediaPlayerService
-    void parseTopLevelXMLFile(const char *path, bool ignore_errors = false);
-
     enum Flags {
         kPreferSoftwareCodecs   = 1,
         kHardwareCodecsOnly     = 2,
@@ -74,13 +72,11 @@
             const char *mime,
             bool createEncoder,
             uint32_t flags,
-            Vector<AString> *matching);
-
-    static uint32_t getQuirksFor(const char *mComponentName);
+            Vector<AString> *matchingCodecs,
+            Vector<AString> *owners = nullptr);
 
     static bool isSoftwareCodec(const AString &componentName);
 
-
 private:
     class BinderDeathObserver : public IBinder::DeathRecipient {
         void binderDied(const wp<IBinder> &the_late_who __unused);
@@ -88,64 +84,86 @@
 
     static sp<BinderDeathObserver> sBinderDeathObserver;
 
-    enum Section {
-        SECTION_TOPLEVEL,
-        SECTION_SETTINGS,
-        SECTION_DECODERS,
-        SECTION_DECODER,
-        SECTION_DECODER_TYPE,
-        SECTION_ENCODERS,
-        SECTION_ENCODER,
-        SECTION_ENCODER_TYPE,
-        SECTION_INCLUDE,
-    };
-
     static sp<IMediaCodecList> sCodecList;
     static sp<IMediaCodecList> sRemoteList;
 
     status_t mInitCheck;
-    Section mCurrentSection;
-    bool mUpdate;
-    Vector<Section> mPastSections;
-    int32_t mDepth;
-    AString mHrefBase;
 
     sp<AMessage> mGlobalSettings;
-    KeyedVector<AString, CodecSettings> mOverrides;
+    std::vector<sp<MediaCodecInfo> > mCodecInfos;
 
-    Vector<sp<MediaCodecInfo> > mCodecInfos;
-    sp<MediaCodecInfo> mCurrentInfo;
+    /**
+     * This constructor will call `buildMediaCodecList()` from the given
+     * `MediaCodecListBuilderBase` object.
+     */
+    MediaCodecList(MediaCodecListBuilderBase* builder);
 
-    MediaCodecList();
     ~MediaCodecList();
 
     status_t initCheck() const;
-    void parseXMLFile(const char *path);
 
-    static void StartElementHandlerWrapper(
-            void *me, const char *name, const char **attrs);
+    MediaCodecList(const MediaCodecList&) = delete;
+    MediaCodecList& operator=(const MediaCodecList&) = delete;
 
-    static void EndElementHandlerWrapper(void *me, const char *name);
+    friend MediaCodecListWriter;
+};
 
-    void startElementHandler(const char *name, const char **attrs);
-    void endElementHandler(const char *name);
+/**
+ * This class is to be used by a `MediaCodecListBuilderBase` instance to add
+ * information to the associated `MediaCodecList` object.
+ */
+struct MediaCodecListWriter {
+    /**
+     * Add a key-value pair to a `MediaCodecList`'s global settings.
+     *
+     * @param key Key.
+     * @param value Value.
+     */
+    void addGlobalSetting(const char* key, const char* value);
+    /**
+     * Create an add a new `MediaCodecInfo` object to a `MediaCodecList`, and
+     * return a `MediaCodecInfoWriter` object associated with the newly added
+     * `MediaCodecInfo`.
+     *
+     * @return The `MediaCodecInfoWriter` object associated with the newly
+     * added `MediaCodecInfo` object.
+     */
+    std::unique_ptr<MediaCodecInfoWriter> addMediaCodecInfo();
+private:
+    /**
+     * The associated `MediaCodecList` object.
+     */
+    MediaCodecList* mList;
 
-    status_t includeXMLFile(const char **attrs);
-    status_t addSettingFromAttributes(const char **attrs);
-    status_t addMediaCodecFromAttributes(bool encoder, const char **attrs);
-    void addMediaCodec(bool encoder, const char *name, const char *type = NULL);
+    /**
+     * Construct this writer object associated with the given `MediaCodecList`
+     * object.
+     *
+     * @param list The "base" `MediaCodecList` object.
+     */
+    MediaCodecListWriter(MediaCodecList* list);
 
-    void setCurrentCodecInfo(bool encoder, const char *name, const char *type);
+    friend MediaCodecList;
+};
 
-    status_t addQuirk(const char **attrs);
-    status_t addTypeFromAttributes(const char **attrs);
-    status_t addLimit(const char **attrs);
-    status_t addFeature(const char **attrs);
-    void addType(const char *name);
+/**
+ * This interface is to be used by `MediaCodecList` to fill its members with
+ * appropriate information. `buildMediaCodecList()` will be called from a
+ * `MediaCodecList` object during its construction.
+ */
+struct MediaCodecListBuilderBase {
+    /**
+     * Build the `MediaCodecList` via the given `MediaCodecListWriter` interface.
+     *
+     * @param writer The writer interface.
+     * @return The status of the construction. `NO_ERROR` means success.
+     */
+    virtual status_t buildMediaCodecList(MediaCodecListWriter* writer) = 0;
 
-    status_t initializeCapabilities(const char *type);
-
-    DISALLOW_EVIL_CONSTRUCTORS(MediaCodecList);
+    /**
+     * The default destructor does nothing.
+     */
+    virtual ~MediaCodecListBuilderBase();
 };
 
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/MediaErrors.h b/media/libstagefright/include/media/stagefright/MediaErrors.h
index 2e663ec..6a5c6b6 100644
--- a/media/libstagefright/include/media/stagefright/MediaErrors.h
+++ b/media/libstagefright/include/media/stagefright/MediaErrors.h
@@ -79,6 +79,26 @@
     HEARTBEAT_ERROR_BASE = -3000,
     ERROR_HEARTBEAT_TERMINATE_REQUESTED                     = HEARTBEAT_ERROR_BASE,
 
+    // CAS-related error codes
+    CAS_ERROR_BASE = -4000,
+
+    ERROR_CAS_UNKNOWN                        = CAS_ERROR_BASE,
+    ERROR_CAS_NO_LICENSE                     = CAS_ERROR_BASE - 1,
+    ERROR_CAS_LICENSE_EXPIRED                = CAS_ERROR_BASE - 2,
+    ERROR_CAS_SESSION_NOT_OPENED             = CAS_ERROR_BASE - 3,
+    ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED   = CAS_ERROR_BASE - 4,
+    ERROR_CAS_DECRYPT                        = CAS_ERROR_BASE - 5,
+    ERROR_CAS_CANNOT_HANDLE                  = CAS_ERROR_BASE - 6,
+    ERROR_CAS_TAMPER_DETECTED                = CAS_ERROR_BASE - 7,
+    ERROR_CAS_NOT_PROVISIONED                = CAS_ERROR_BASE - 8,
+    ERROR_CAS_DEVICE_REVOKED                 = CAS_ERROR_BASE - 9,
+    ERROR_CAS_RESOURCE_BUSY                  = CAS_ERROR_BASE - 10,
+    ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = CAS_ERROR_BASE - 11,
+    ERROR_CAS_LAST_USED_ERRORCODE            = CAS_ERROR_BASE - 11,
+
+    ERROR_CAS_VENDOR_MAX                     = CAS_ERROR_BASE - 500,
+    ERROR_CAS_VENDOR_MIN                     = CAS_ERROR_BASE - 999,
+
     // NDK Error codes
     // frameworks/av/include/ndk/NdkMediaError.h
     // from -10000 (0xFFFFD8F0 - 0xFFFFD8EC)
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractor.h b/media/libstagefright/include/media/stagefright/MediaExtractor.h
index a856b2b..6ec7eaf 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractor.h
@@ -23,10 +23,6 @@
 #include <media/MediaAnalyticsItem.h>
 
 namespace android {
-namespace media {
-class ICas;
-};
-using namespace media;
 class DataSource;
 struct MediaSource;
 class MetaData;
@@ -70,12 +66,14 @@
     }
     virtual void setUID(uid_t /*uid*/) {
     }
-    virtual status_t setMediaCas(const sp<ICas>& /*cas*/) override {
+    virtual status_t setMediaCas(const HInterfaceToken &/*casToken*/) override {
         return INVALID_OPERATION;
     }
 
     virtual const char * name() { return "<unspecified>"; }
 
+    virtual void release() {}
+
 protected:
     MediaExtractor();
     virtual ~MediaExtractor();
diff --git a/media/libstagefright/include/media/stagefright/MetaData.h b/media/libstagefright/include/media/stagefright/MetaData.h
index 9676b97..6cfde9c 100644
--- a/media/libstagefright/include/media/stagefright/MetaData.h
+++ b/media/libstagefright/include/media/stagefright/MetaData.h
@@ -38,6 +38,8 @@
     kKeyDisplayHeight     = 'dHgt',  // int32_t, display/presentation
     kKeySARWidth          = 'sarW',  // int32_t, sampleAspectRatio width
     kKeySARHeight         = 'sarH',  // int32_t, sampleAspectRatio height
+    kKeyThumbnailWidth    = 'thbW',  // int32_t, thumbnail width
+    kKeyThumbnailHeight   = 'thbH',  // int32_t, thumbnail height
 
     // a rectangle, if absent assumed to be (0, 0, width - 1, height - 1)
     kKeyCropRect          = 'crop',
@@ -58,6 +60,7 @@
     kKeyAACProfile        = 'aacp',  // int32_t
     kKeyAVCC              = 'avcc',  // raw data
     kKeyHVCC              = 'hvcc',  // raw data
+    kKeyThumbnailHVCC     = 'thvc',  // raw data
     kKeyD263              = 'd263',  // raw data
     kKeyVorbisInfo        = 'vinf',  // raw data
     kKeyVorbisBooks       = 'vboo',  // raw data
@@ -209,6 +212,10 @@
                                    // color Matrix, value defined by ColorAspects.MatrixCoeffs.
     kKeyTemporalLayerId  = 'iLyr', // int32_t, temporal layer-id. 0-based (0 => base layer)
     kKeyTemporalLayerCount = 'cLyr', // int32_t, number of temporal layers encoded
+
+    kKeyGridWidth        = 'grdW', // int32_t, HEIF grid width
+    kKeyGridHeight       = 'grdH', // int32_t, HEIF grid height
+    kKeyIccProfile       = 'prof', // raw data, ICC prifile data
 };
 
 enum {
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 3e3cc17..6a93bd5 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -28,10 +28,6 @@
 #include <utils/Vector.h>
 
 namespace android {
-namespace media {
-class ICas;
-}
-using namespace media;
 
 struct ABuffer;
 struct AMessage;
@@ -64,7 +60,7 @@
 
     status_t setDataSource(const sp<DataSource> &datasource);
 
-    status_t setMediaCas(const sp<ICas> &cas);
+    status_t setMediaCas(const HInterfaceToken &casToken);
 
     size_t countTracks() const;
     status_t getTrackFormat(size_t index, sp<AMessage> *format, uint32_t flags = 0) const;
@@ -115,7 +111,7 @@
     sp<DataSource> mDataSource;
 
     sp<IMediaExtractor> mImpl;
-    sp<ICas> mCas;
+    HInterfaceToken mCasToken;
 
     Vector<TrackInfo> mSelectedTracks;
     int64_t mTotalBitrate;  // in bits/sec
diff --git a/media/libstagefright/include/media/stagefright/OMXClient.h b/media/libstagefright/include/media/stagefright/OMXClient.h
index 203a181..2f159b0 100644
--- a/media/libstagefright/include/media/stagefright/OMXClient.h
+++ b/media/libstagefright/include/media/stagefright/OMXClient.h
@@ -28,9 +28,10 @@
 
     status_t connect();
     status_t connect(bool* trebleFlag);
+    status_t connect(const char* name, bool* trebleFlag = nullptr);
 
     status_t connectLegacy();
-    status_t connectTreble();
+    status_t connectTreble(const char* name = "default");
     void disconnect();
 
     sp<IOMX> interface() {
@@ -40,8 +41,8 @@
 private:
     sp<IOMX> mOMX;
 
-    OMXClient(const OMXClient &);
-    OMXClient &operator=(const OMXClient &);
+    OMXClient(const OMXClient &) = delete;
+    OMXClient &operator=(const OMXClient &) = delete;
 };
 
 }  // namespace android
diff --git a/drm/libmediadrm/aidl/android/media/IDescrambler.aidl b/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h
similarity index 62%
rename from drm/libmediadrm/aidl/android/media/IDescrambler.aidl
rename to media/libstagefright/include/media/stagefright/OmxInfoBuilder.h
index fdf99eb..1b4d873 100644
--- a/drm/libmediadrm/aidl/android/media/IDescrambler.aidl
+++ b/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h
@@ -14,14 +14,20 @@
  * limitations under the License.
  */
 
-package android.media;
+#ifndef OMX_INFO_BUILDER_H_
+#define OMX_INFO_BUILDER_H_
 
-import android.media.MediaDescrambler;
+#include <media/stagefright/MediaCodecList.h>
+#include <utils/Errors.h>
 
-/** @hide */
-interface IDescrambler {
-    void setMediaCasSession(in byte[] sessionId);
-    boolean requiresSecureDecoderComponent(String mime);
-    int descramble(in MediaDescrambler.DescrambleInfo descrambleInfo);
-    void release();
-}
\ No newline at end of file
+namespace android {
+
+class OmxInfoBuilder : public MediaCodecListBuilderBase {
+public:
+    OmxInfoBuilder();
+    status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
+};
+
+}  // namespace android
+
+#endif  // OMX_INFO_BUILDER_H_
diff --git a/media/libstagefright/include/media/stagefright/SurfaceMediaSource.h b/media/libstagefright/include/media/stagefright/SurfaceMediaSource.h
index d38c337..d1677fa 100644
--- a/media/libstagefright/include/media/stagefright/SurfaceMediaSource.h
+++ b/media/libstagefright/include/media/stagefright/SurfaceMediaSource.h
@@ -25,7 +25,7 @@
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MediaBuffer.h>
 
-#include <MetadataBufferType.h>
+#include <media/hardware/MetadataBufferType.h>
 
 #include "foundation/ABase.h"
 
diff --git a/media/libstagefright/include/media/stagefright/Utils.h b/media/libstagefright/include/media/stagefright/Utils.h
index 88a416a..77cbd4c 100644
--- a/media/libstagefright/include/media/stagefright/Utils.h
+++ b/media/libstagefright/include/media/stagefright/Utils.h
@@ -95,7 +95,7 @@
 void readFromAMessage(const sp<AMessage> &msg, BufferingSettings *buffering /* nonnull */);
 
 AString nameForFd(int fd);
-
+void MakeFourCCString(uint32_t x, char *s);
 }  // namespace android
 
 #endif  // UTILS_H_
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 31edb21..a256a4d 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -23,8 +23,8 @@
 #include "ESQueue.h"
 #include "include/avc_utils.h"
 
-#include <android/media/IDescrambler.h>
-#include <binder/MemoryDealer.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <cutils/native_handle.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -41,8 +41,12 @@
 #include <inttypes.h>
 
 namespace android {
-using binder::Status;
-using MediaDescrambler::DescrambleInfo;
+using hardware::hidl_handle;
+using hardware::hidl_memory;
+using hardware::hidl_string;
+using hardware::hidl_vec;
+using namespace hardware::cas::V1_0;
+using namespace hardware::cas::native::V1_0;
 
 // I want the expression "y" evaluated even if verbose logging is off.
 #define MY_LOGV(x, y) \
@@ -203,6 +207,7 @@
     sp<AMessage> mSampleAesKeyItem;
     sp<IMemory> mMem;
     sp<MemoryDealer> mDealer;
+    hardware::cas::native::V1_0::SharedBuffer mDescramblerSrcBuffer;
     sp<ABuffer> mDescrambledBuffer;
     List<SubSampleInfo> mSubSamples;
     sp<IDescrambler> mDescrambler;
@@ -235,7 +240,7 @@
 
     // Ensure internal buffers can hold specified size, and will re-allocate
     // as needed.
-    void ensureBufferCapacity(size_t size);
+    bool ensureBufferCapacity(size_t size);
 
     DISALLOW_EVIL_CONSTRUCTORS(Stream);
 };
@@ -807,9 +812,9 @@
     mQueue = NULL;
 }
 
-void ATSParser::Stream::ensureBufferCapacity(size_t neededSize) {
+bool ATSParser::Stream::ensureBufferCapacity(size_t neededSize) {
     if (mBuffer != NULL && mBuffer->capacity() >= neededSize) {
-        return;
+        return true;
     }
 
     ALOGV("ensureBufferCapacity: current size %zu, new size %zu, scrambled %d",
@@ -837,6 +842,26 @@
         mMem = newMem;
         mDealer = newDealer;
         mDescrambledBuffer = newScrambledBuffer;
+
+        ssize_t offset;
+        size_t size;
+        sp<IMemoryHeap> heap = newMem->getMemory(&offset, &size);
+        if (heap == NULL) {
+            return false;
+        }
+        native_handle_t* nativeHandle = native_handle_create(1, 0);
+        if (!nativeHandle) {
+            ALOGE("[stream %d] failed to create native handle", mElementaryPID);
+            return false;
+        }
+        nativeHandle->data[0] = heap->getHeapID();
+        mDescramblerSrcBuffer.heapBase = hidl_memory("ashmem",
+                hidl_handle(nativeHandle), heap->getSize());
+        mDescramblerSrcBuffer.offset = (uint64_t) offset;
+        mDescramblerSrcBuffer.size = (uint64_t) size;
+
+        ALOGD("[stream %d] created shared buffer for descrambling, offset %zd, size %zu",
+                mElementaryPID, offset, size);
     } else {
         // Align to multiples of 64K.
         neededSize = (neededSize + 65535) & ~65535;
@@ -850,6 +875,7 @@
         newBuffer->setRange(0, 0);
     }
     mBuffer = newBuffer;
+    return true;
 }
 
 status_t ATSParser::Stream::parse(
@@ -923,7 +949,9 @@
     }
 
     size_t neededSize = mBuffer->size() + payloadSizeBits / 8;
-    ensureBufferCapacity(neededSize);
+    if (!ensureBufferCapacity(neededSize)) {
+        return NO_MEMORY;
+    }
 
     memcpy(mBuffer->data() + mBuffer->size(), br->data(), payloadSizeBits / 8);
     mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
@@ -1365,47 +1393,59 @@
         memcpy(mDescrambledBuffer->data(), mBuffer->data(), descrambleBytes);
         mDescrambledBuffer->setRange(0, descrambleBytes);
 
-        sp<ABuffer> subSamples = new ABuffer(
-                sizeof(DescramblerPlugin::SubSample) * descrambleSubSamples);
-
-        DescrambleInfo info;
-        info.dstType = DescrambleInfo::kDestinationTypeVmPointer;
-        info.scramblingControl = (DescramblerPlugin::ScramblingControl)sctrl;
-        info.numSubSamples = descrambleSubSamples;
-        info.subSamples = (DescramblerPlugin::SubSample *)subSamples->data();
-        info.srcMem = mMem;
-        info.srcOffset = 0;
-        info.dstPtr = NULL; // in-place descrambling into srcMem
-        info.dstOffset = 0;
+        hidl_vec<SubSample> subSamples;
+        subSamples.resize(descrambleSubSamples);
 
         int32_t i = 0;
         for (auto it = mSubSamples.begin();
                 it != mSubSamples.end() && i < descrambleSubSamples; it++, i++) {
             if (it->transport_scrambling_mode != 0 || pesScramblingControl != 0) {
-                info.subSamples[i].mNumBytesOfClearData = 0;
-                info.subSamples[i].mNumBytesOfEncryptedData = it->subSampleSize;
+                subSamples[i].numBytesOfClearData = 0;
+                subSamples[i].numBytesOfEncryptedData = it->subSampleSize;
             } else {
-                info.subSamples[i].mNumBytesOfClearData = it->subSampleSize;
-                info.subSamples[i].mNumBytesOfEncryptedData = 0;
+                subSamples[i].numBytesOfClearData = it->subSampleSize;
+                subSamples[i].numBytesOfEncryptedData = 0;
             }
         }
+
+        uint64_t srcOffset = 0, dstOffset = 0;
         // If scrambled at PES-level, PES header should be skipped
         if (pesScramblingControl != 0) {
-            info.srcOffset = info.dstOffset = pesOffset;
-            info.subSamples[0].mNumBytesOfEncryptedData -= pesOffset;
+            srcOffset = dstOffset = pesOffset;
+            subSamples[0].numBytesOfEncryptedData -= pesOffset;
         }
 
-        int32_t result;
-        Status status = mDescrambler->descramble(info, &result);
+        Status status = Status::OK;
+        uint32_t bytesWritten = 0;
+        hidl_string detailedError;
 
-        if (!status.isOk()) {
-            ALOGE("[stream %d] descramble failed, exceptionCode=%d",
-                    mElementaryPID, status.exceptionCode());
+        DestinationBuffer dstBuffer;
+        dstBuffer.type = BufferType::SHARED_MEMORY;
+        dstBuffer.nonsecureMemory = mDescramblerSrcBuffer;
+
+        auto returnVoid = mDescrambler->descramble(
+                (ScramblingControl) sctrl,
+                subSamples,
+                mDescramblerSrcBuffer,
+                srcOffset,
+                dstBuffer,
+                dstOffset,
+                [&status, &bytesWritten, &detailedError] (
+                        Status _status, uint32_t _bytesWritten,
+                        const hidl_string& _detailedError) {
+                    status = _status;
+                    bytesWritten = _bytesWritten;
+                    detailedError = _detailedError;
+                });
+
+        if (!returnVoid.isOk()) {
+            ALOGE("[stream %d] descramble failed, trans=%s",
+                    mElementaryPID, returnVoid.description().c_str());
             return UNKNOWN_ERROR;
         }
 
         ALOGV("[stream %d] descramble succeeded, %d bytes",
-                mElementaryPID, result);
+                mElementaryPID, bytesWritten);
         memcpy(mBuffer->data(), mDescrambledBuffer->data(), descrambleBytes);
     }
 
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 374e011..41c19cd 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -29,11 +29,13 @@
 #include <vector>
 
 namespace android {
-namespace media {
-class ICas;
-class IDescrambler;
-};
-using namespace media;
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+struct ICas;
+}}}
+using hardware::cas::V1_0::ICas;
+
 class ABitReader;
 struct ABuffer;
 struct AnotherPacketSource;
diff --git a/media/libstagefright/mpeg2ts/Android.bp b/media/libstagefright/mpeg2ts/Android.bp
index 96eb5bf..21259c4 100644
--- a/media/libstagefright/mpeg2ts/Android.bp
+++ b/media/libstagefright/mpeg2ts/Android.bp
@@ -35,5 +35,8 @@
     shared_libs: [
         "libcrypto",
         "libmedia",
+        "libhidlmemory",
+        "android.hardware.cas.native@1.0",
+        "android.hidl.memory@1.0",
     ],
 }
diff --git a/media/libstagefright/mpeg2ts/CasManager.cpp b/media/libstagefright/mpeg2ts/CasManager.cpp
index 047b1b3..9ff4521 100644
--- a/media/libstagefright/mpeg2ts/CasManager.cpp
+++ b/media/libstagefright/mpeg2ts/CasManager.cpp
@@ -18,15 +18,19 @@
 #define LOG_TAG "CasManager"
 #include "CasManager.h"
 
-#include <android/media/ICas.h>
-#include <android/media/IDescrambler.h>
-#include <android/media/IMediaCasService.h>
-#include <binder/IServiceManager.h>
+#include <android/hardware/cas/1.0/ICas.h>
+#include <android/hardware/cas/1.0/IMediaCasService.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <hidl/HidlSupport.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <utils/Log.h>
 
 namespace android {
-using binder::Status;
+
+using hardware::hidl_vec;
+using hardware::Return;
+using namespace hardware::cas::V1_0;
+using namespace hardware::cas::native::V1_0;
 
 struct ATSParser::CasManager::ProgramCasManager : public RefBase {
     ProgramCasManager(unsigned programNumber, const CADescriptor &descriptor);
@@ -125,45 +129,60 @@
          const sp<ICas>& cas,
          PidToSessionMap &sessionMap,
          CasSession *session) {
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> casServiceBinder = sm->getService(String16("media.cas"));
-    sp<IMediaCasService> casService =
-            interface_cast<IMediaCasService>(casServiceBinder);
-
+    sp<IMediaCasService> casService = IMediaCasService::getService("default");
     if (casService == NULL) {
         ALOGE("Cannot obtain IMediaCasService");
         return NO_INIT;
     }
 
+    Status status;
     sp<IDescrambler> descrambler;
+    sp<IDescramblerBase> descramblerBase;
+    Return<Status> returnStatus(Status::OK);
+    Return<sp<IDescramblerBase> > returnDescrambler(NULL);
     std::vector<uint8_t> sessionId;
     const CADescriptor &descriptor = session->mCADescriptor;
 
-    Status status = cas->openSession(&sessionId);
-    if (!status.isOk()) {
-        ALOGE("Failed to open session: exception=%d, error=%d",
-                status.exceptionCode(), status.serviceSpecificErrorCode());
+    auto returnVoid = cas->openSession(
+            [&status, &sessionId] (Status _status, const hidl_vec<uint8_t>& _sessionId) {
+                status = _status;
+                sessionId = _sessionId;
+            });
+    if (!returnVoid.isOk() || status != Status::OK) {
+        ALOGE("Failed to open session: trans=%s, status=%d",
+                returnVoid.description().c_str(), status);
         goto l_fail;
     }
 
-    cas->setSessionPrivateData(sessionId, descriptor.mPrivateData);
-    if (!status.isOk()) {
-        ALOGE("Failed to set private data: exception=%d, error=%d",
-                status.exceptionCode(), status.serviceSpecificErrorCode());
+    returnStatus = cas->setSessionPrivateData(sessionId, descriptor.mPrivateData);
+    if (!returnStatus.isOk() || returnStatus != Status::OK) {
+        ALOGE("Failed to set private data: trans=%s, status=%d",
+                returnStatus.description().c_str(), (Status)returnStatus);
         goto l_fail;
     }
 
-    status = casService->createDescrambler(descriptor.mSystemID, &descrambler);
-    if (!status.isOk() || descrambler == NULL) {
-        ALOGE("Failed to create descrambler: : exception=%d, error=%d",
-                status.exceptionCode(), status.serviceSpecificErrorCode());
+    returnDescrambler = casService->createDescrambler(descriptor.mSystemID);
+    if (!returnDescrambler.isOk()) {
+        ALOGE("Failed to create descrambler: trans=%s",
+                returnDescrambler.description().c_str());
+        goto l_fail;
+    }
+    descramblerBase = (sp<IDescramblerBase>) returnDescrambler;
+    if (descramblerBase == NULL) {
+        ALOGE("Failed to create descrambler: null ptr");
         goto l_fail;
     }
 
-    status = descrambler->setMediaCasSession(sessionId);
-    if (!status.isOk()) {
-        ALOGE("Failed to init descrambler: : exception=%d, error=%d",
-                status.exceptionCode(), status.serviceSpecificErrorCode());
+    returnStatus = descramblerBase->setMediaCasSession(sessionId);
+    if (!returnStatus.isOk() || (Status) returnStatus != Status::OK) {
+        ALOGE("Failed to init descrambler: : trans=%s, status=%d",
+                returnStatus.description().c_str(), (Status) returnStatus);
+        goto l_fail;
+    }
+
+    descrambler = IDescrambler::castFrom(descramblerBase);
+    if (descrambler == NULL) {
+        ALOGE("Failed to cast from IDescramblerBase to IDescrambler");
         goto l_fail;
     }
 
@@ -177,8 +196,8 @@
     if (!sessionId.empty()) {
         cas->closeSession(sessionId);
     }
-    if (descrambler != NULL) {
-        descrambler->release();
+    if (descramblerBase != NULL) {
+        descramblerBase->release();
     }
     return NO_INIT;
 }
@@ -316,11 +335,12 @@
     if (index < 0) {
         return false;
     }
-    MediaCas::ParcelableCasData ecm(br->data(), br->numBitsLeft() / 8);
-    Status status = mICas->processEcm(mCAPidToSessionIdMap[index], ecm);
-    if (!status.isOk()) {
-        ALOGE("Failed to process ECM: exception=%d, error=%d",
-                status.exceptionCode(), status.serviceSpecificErrorCode());
+    hidl_vec<uint8_t> ecm;
+    ecm.setToExternal((uint8_t*)br->data(), br->numBitsLeft() / 8);
+    auto returnStatus = mICas->processEcm(mCAPidToSessionIdMap[index], ecm);
+    if (!returnStatus.isOk() || (Status) returnStatus != Status::OK) {
+        ALOGE("Failed to process ECM: trans=%s, status=%d",
+                returnStatus.description().c_str(), (Status) returnStatus);
     }
     return true; // handled
 }
diff --git a/media/libstagefright/mpeg2ts/CasManager.h b/media/libstagefright/mpeg2ts/CasManager.h
index 8088dec..81f6546 100644
--- a/media/libstagefright/mpeg2ts/CasManager.h
+++ b/media/libstagefright/mpeg2ts/CasManager.h
@@ -21,10 +21,13 @@
 #include <set>
 
 namespace android {
-namespace media {
-class ICas;
-class IDescrambler;
-}
+namespace hardware {
+namespace cas {
+namespace native {
+namespace V1_0 {
+struct IDescrambler;
+}}}}
+using hardware::cas::native::V1_0::IDescrambler;
 
 struct ATSParser::CasManager : public RefBase {
     CasManager();
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index c3f1274..9d684e0 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -38,8 +38,13 @@
 #include "AnotherPacketSource.h"
 #include "ATSParser.h"
 
+#include <hidl/HybridInterface.h>
+#include <android/hardware/cas/1.0/ICas.h>
+
 namespace android {
 
+using hardware::cas::V1_0::ICas;
+
 static const size_t kTSPacketSize = 188;
 static const int kMaxDurationReadSize = 250000LL;
 static const int kMaxDurationRetry = 6;
@@ -156,7 +161,10 @@
                     || !strcasecmp(MEDIA_MIMETYPE_AUDIO_SCRAMBLED, mime));
 }
 
-status_t MPEG2TSExtractor::setMediaCas(const sp<ICas> &cas) {
+status_t MPEG2TSExtractor::setMediaCas(const HInterfaceToken &casToken) {
+    HalToken halToken;
+    halToken.setToExternal((uint8_t*)casToken.data(), casToken.size());
+    sp<ICas> cas = ICas::castFrom(retrieveHalInterface(halToken));
     ALOGD("setMediaCas: %p", cas.get());
 
     status_t err = mParser->setMediaCas(cas);
diff --git a/media/libstagefright/omx/1.0/Omx.cpp b/media/libstagefright/omx/1.0/Omx.cpp
index 789379a..fe50656 100644
--- a/media/libstagefright/omx/1.0/Omx.cpp
+++ b/media/libstagefright/omx/1.0/Omx.cpp
@@ -19,20 +19,19 @@
 
 #include <android-base/logging.h>
 #include <gui/IGraphicBufferProducer.h>
-#include <OMX_Core.h>
-#include <OMX_AsString.h>
+#include <media/openmax/OMX_Core.h>
+#include <media/openmax/OMX_AsString.h>
 
-#include "../OMXUtils.h"
-#include "../OMXMaster.h"
-#include "../GraphicBufferSource.h"
+#include <media/stagefright/omx/OMXUtils.h>
+#include <media/stagefright/omx/OMXMaster.h>
+#include <media/stagefright/omx/GraphicBufferSource.h>
 
-#include "WOmxNode.h"
-#include "WOmxObserver.h"
-#include "WGraphicBufferProducer.h"
-#include "WGraphicBufferSource.h"
-#include "Conversion.h"
-
-#include "Omx.h"
+#include <media/stagefright/omx/1.0/WOmxNode.h>
+#include <media/stagefright/omx/1.0/WOmxObserver.h>
+#include <media/stagefright/omx/1.0/WGraphicBufferProducer.h>
+#include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
+#include <media/stagefright/omx/1.0/Conversion.h>
+#include <media/stagefright/omx/1.0/Omx.h>
 
 namespace android {
 namespace hardware {
@@ -115,15 +114,23 @@
             return Void();
         }
         instance->setHandle(handle);
-        std::vector<AString> quirkVector;
-        if (mParser.getQuirks(name.c_str(), &quirkVector) == OK) {
+
+        // Find quirks from mParser
+        const auto& codec = mParser.getCodecMap().find(name.c_str());
+        if (codec == mParser.getCodecMap().cend()) {
+            LOG(WARNING) << "Failed to obtain quirks for omx component "
+                    "'" << name.c_str() << "' "
+                    "from XML files";
+        } else {
             uint32_t quirks = 0;
-            for (const AString quirk : quirkVector) {
+            for (const auto& quirk : codec->second.quirkSet) {
                 if (quirk == "requires-allocate-on-input-ports") {
-                    quirks |= kRequiresAllocateBufferOnInputPorts;
+                    quirks |= OMXNodeInstance::
+                            kRequiresAllocateBufferOnInputPorts;
                 }
                 if (quirk == "requires-allocate-on-output-ports") {
-                    quirks |= kRequiresAllocateBufferOnOutputPorts;
+                    quirks |= OMXNodeInstance::
+                            kRequiresAllocateBufferOnOutputPorts;
                 }
             }
             instance->setQuirks(quirks);
diff --git a/media/libstagefright/omx/1.0/OmxStore.cpp b/media/libstagefright/omx/1.0/OmxStore.cpp
index 0e37af9..447af6f 100644
--- a/media/libstagefright/omx/1.0/OmxStore.cpp
+++ b/media/libstagefright/omx/1.0/OmxStore.cpp
@@ -19,8 +19,9 @@
 
 #include <android-base/logging.h>
 
-#include "Conversion.h"
-#include "OmxStore.h"
+#include <media/stagefright/omx/1.0/Conversion.h>
+#include <media/stagefright/omx/1.0/OmxStore.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
 
 namespace android {
 namespace hardware {
@@ -29,24 +30,87 @@
 namespace V1_0 {
 namespace implementation {
 
-OmxStore::OmxStore() {
+OmxStore::OmxStore(
+        const char* owner,
+        const char* const* searchDirs,
+        const char* mainXmlName,
+        const char* performanceXmlName,
+        const char* profilingResultsXmlPath) {
+    MediaCodecsXmlParser parser(searchDirs,
+            mainXmlName,
+            performanceXmlName,
+            profilingResultsXmlPath);
+    mParsingStatus = toStatus(parser.getParsingStatus());
+
+    const auto& serviceAttributeMap = parser.getServiceAttributeMap();
+    mServiceAttributeList.resize(serviceAttributeMap.size());
+    size_t i = 0;
+    for (const auto& attributePair : serviceAttributeMap) {
+        ServiceAttribute attribute;
+        attribute.key = attributePair.first;
+        attribute.value = attributePair.second;
+        mServiceAttributeList[i] = std::move(attribute);
+        ++i;
+    }
+
+    const auto& roleMap = parser.getRoleMap();
+    mRoleList.resize(roleMap.size());
+    i = 0;
+    for (const auto& rolePair : roleMap) {
+        RoleInfo role;
+        role.role = rolePair.first;
+        role.type = rolePair.second.type;
+        role.isEncoder = rolePair.second.isEncoder;
+        // TODO: Currently, preferPlatformNodes information is not available in
+        // the xml file. Once we have a way to provide this information, it
+        // should be parsed properly.
+        role.preferPlatformNodes = rolePair.first.compare(0, 5, "audio") == 0;
+        hidl_vec<NodeInfo>& nodeList = role.nodes;
+        nodeList.resize(rolePair.second.nodeList.size());
+        size_t j = 0;
+        for (const auto& nodePair : rolePair.second.nodeList) {
+            NodeInfo node;
+            node.name = nodePair.second.name;
+            node.owner = owner;
+            hidl_vec<NodeAttribute>& attributeList = node.attributes;
+            attributeList.resize(nodePair.second.attributeList.size());
+            size_t k = 0;
+            for (const auto& attributePair : nodePair.second.attributeList) {
+                NodeAttribute attribute;
+                attribute.key = attributePair.first;
+                attribute.value = attributePair.second;
+                attributeList[k] = std::move(attribute);
+                ++k;
+            }
+            nodeList[j] = std::move(node);
+            ++j;
+        }
+        mRoleList[i] = std::move(role);
+        ++i;
+    }
+
+    mPrefix = parser.getCommonPrefix();
 }
 
 OmxStore::~OmxStore() {
 }
 
 Return<void> OmxStore::listServiceAttributes(listServiceAttributes_cb _hidl_cb) {
-    _hidl_cb(toStatus(NO_ERROR), hidl_vec<ServiceAttribute>());
+    if (mParsingStatus == Status::NO_ERROR) {
+        _hidl_cb(Status::NO_ERROR, mServiceAttributeList);
+    } else {
+        _hidl_cb(mParsingStatus, hidl_vec<ServiceAttribute>());
+    }
     return Void();
 }
 
 Return<void> OmxStore::getNodePrefix(getNodePrefix_cb _hidl_cb) {
-    _hidl_cb(hidl_string());
+    _hidl_cb(mPrefix);
     return Void();
 }
 
 Return<void> OmxStore::listRoles(listRoles_cb _hidl_cb) {
-    _hidl_cb(hidl_vec<RoleInfo>());
+    _hidl_cb(mRoleList);
     return Void();
 }
 
@@ -54,12 +118,6 @@
     return IOmx::tryGetService(omxName);
 }
 
-// Methods from ::android::hidl::base::V1_0::IBase follow.
-
-IOmxStore* HIDL_FETCH_IOmxStore(const char* /* name */) {
-    return new OmxStore();
-}
-
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace omx
diff --git a/media/libstagefright/omx/1.0/WGraphicBufferProducer.cpp b/media/libstagefright/omx/1.0/WGraphicBufferProducer.cpp
index acda060..c4499dc 100644
--- a/media/libstagefright/omx/1.0/WGraphicBufferProducer.cpp
+++ b/media/libstagefright/omx/1.0/WGraphicBufferProducer.cpp
@@ -18,9 +18,9 @@
 
 #include <android-base/logging.h>
 
-#include "WGraphicBufferProducer.h"
-#include "WProducerListener.h"
-#include "Conversion.h"
+#include <media/stagefright/omx/1.0/WGraphicBufferProducer.h>
+#include <media/stagefright/omx/1.0/WProducerListener.h>
+#include <media/stagefright/omx/1.0/Conversion.h>
 #include <system/window.h>
 
 namespace android {
@@ -41,7 +41,9 @@
     sp<GraphicBuffer> buf;
     status_t status = mBase->requestBuffer(slot, &buf);
     AnwBuffer anwBuffer;
-    wrapAs(&anwBuffer, *buf);
+    if (buf != nullptr) {
+        wrapAs(&anwBuffer, *buf);
+    }
     _hidl_cb(static_cast<int32_t>(status), anwBuffer);
     return Void();
 }
@@ -64,10 +66,9 @@
     sp<Fence> fence;
     ::android::FrameEventHistoryDelta outTimestamps;
     status_t status = mBase->dequeueBuffer(
-            &slot, &fence,
-            width, height,
-            static_cast<::android::PixelFormat>(format), usage,
-            getFrameTimestamps ? &outTimestamps : nullptr);
+        &slot, &fence, width, height,
+        static_cast<::android::PixelFormat>(format), usage, nullptr,
+        getFrameTimestamps ? &outTimestamps : nullptr);
     hidl_handle tFence;
     FrameEventHistoryDelta tOutTimestamps;
 
diff --git a/media/libstagefright/omx/1.0/WGraphicBufferSource.cpp b/media/libstagefright/omx/1.0/WGraphicBufferSource.cpp
index d8540f8..3201c32 100644
--- a/media/libstagefright/omx/1.0/WGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/1.0/WGraphicBufferSource.cpp
@@ -17,15 +17,14 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "TWGraphicBufferSource"
 
+#include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
+#include <media/stagefright/omx/1.0/WOmxNode.h>
+#include <media/stagefright/omx/1.0/Conversion.h>
+#include <media/stagefright/omx/OMXUtils.h>
 #include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
-#include <OMX_Component.h>
-#include <OMX_IndexExt.h>
-
-#include "omx/OMXUtils.h"
-#include "WGraphicBufferSource.h"
-#include "WOmxNode.h"
-#include "Conversion.h"
+#include <media/openmax/OMX_Component.h>
+#include <media/openmax/OMX_IndexExt.h>
 
 namespace android {
 namespace hardware {
@@ -68,7 +67,14 @@
         tMsg.data.eventData.data1 = dataSpace;
         tMsg.data.eventData.data2 = aspects;
         tMsg.data.eventData.data3 = pixelFormat;
-        mOmxNode->dispatchMessage(tMsg);
+        if (!mOmxNode->dispatchMessage(tMsg).isOk()) {
+            ALOGE("TWOmxNodeWrapper failed to dispatch message "
+                    "OMX_EventDataSpaceChanged: "
+                    "dataSpace = %ld, aspects = %ld, pixelFormat = %ld",
+                    static_cast<long>(dataSpace),
+                    static_cast<long>(aspects),
+                    static_cast<long>(pixelFormat));
+        }
     }
 };
 
@@ -144,10 +150,13 @@
                         outParams.data() + outParams.size(),
                         params);
             });
-    omxNode->getParameter(
+    auto transStatus = omxNode->getParameter(
             static_cast<uint32_t>(OMX_IndexParamConsumerUsageBits),
             inHidlBytes(&consumerUsage, sizeof(consumerUsage)),
             _hidl_cb);
+    if (!transStatus.isOk()) {
+        return toStatus(FAILED_TRANSACTION);
+    }
     if (fnStatus != OK) {
         consumerUsage = 0;
     }
@@ -158,10 +167,13 @@
 
     _params = &def;
     params = static_cast<uint8_t*>(_params);
-    omxNode->getParameter(
+    transStatus = omxNode->getParameter(
             static_cast<uint32_t>(OMX_IndexParamPortDefinition),
             inHidlBytes(&def, sizeof(def)),
             _hidl_cb);
+    if (!transStatus.isOk()) {
+        return toStatus(FAILED_TRANSACTION);
+    }
     if (fnStatus != NO_ERROR) {
         ALOGE("Failed to get port definition: %d", fnStatus);
         return toStatus(fnStatus);
diff --git a/media/libstagefright/omx/1.0/WOmxBufferSource.cpp b/media/libstagefright/omx/1.0/WOmxBufferSource.cpp
index 803283a..c8c963f 100644
--- a/media/libstagefright/omx/1.0/WOmxBufferSource.cpp
+++ b/media/libstagefright/omx/1.0/WOmxBufferSource.cpp
@@ -16,8 +16,8 @@
 
 #include <utils/String8.h>
 
-#include "WOmxBufferSource.h"
-#include "Conversion.h"
+#include <media/stagefright/omx/1.0/WOmxBufferSource.h>
+#include <media/stagefright/omx/1.0/Conversion.h>
 
 namespace android {
 namespace hardware {
diff --git a/media/libstagefright/omx/1.0/WOmxNode.cpp b/media/libstagefright/omx/1.0/WOmxNode.cpp
index 91d1010..9f82283 100644
--- a/media/libstagefright/omx/1.0/WOmxNode.cpp
+++ b/media/libstagefright/omx/1.0/WOmxNode.cpp
@@ -16,9 +16,9 @@
 
 #include <algorithm>
 
-#include "WOmxNode.h"
-#include "WOmxBufferSource.h"
-#include "Conversion.h"
+#include <media/stagefright/omx/1.0/WOmxNode.h>
+#include <media/stagefright/omx/1.0/WOmxBufferSource.h>
+#include <media/stagefright/omx/1.0/Conversion.h>
 
 namespace android {
 namespace hardware {
diff --git a/media/libstagefright/omx/1.0/WOmxObserver.cpp b/media/libstagefright/omx/1.0/WOmxObserver.cpp
index 354db29..ccbe25c 100644
--- a/media/libstagefright/omx/1.0/WOmxObserver.cpp
+++ b/media/libstagefright/omx/1.0/WOmxObserver.cpp
@@ -16,14 +16,14 @@
 
 #define LOG_TAG "WOmxObserver-impl"
 
-#include <vector>
-
 #include <android-base/logging.h>
 #include <cutils/native_handle.h>
 #include <binder/Binder.h>
 
-#include "WOmxObserver.h"
-#include "Conversion.h"
+#include <media/stagefright/omx/1.0/WOmxObserver.h>
+#include <media/stagefright/omx/1.0/Conversion.h>
+
+#include <vector>
 
 namespace android {
 namespace hardware {
diff --git a/media/libstagefright/omx/1.0/WProducerListener.cpp b/media/libstagefright/omx/1.0/WProducerListener.cpp
index be0d4d5..bdc3aa1 100644
--- a/media/libstagefright/omx/1.0/WProducerListener.cpp
+++ b/media/libstagefright/omx/1.0/WProducerListener.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "WProducerListener.h"
+#include <media/stagefright/omx/1.0/WProducerListener.h>
 
 namespace android {
 namespace hardware {
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 69ede3d..bd3c1c6 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -1,12 +1,16 @@
 cc_library_shared {
     name: "libstagefright_omx",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "FrameDropper.cpp",
         "GraphicBufferSource.cpp",
         "BWGraphicBufferSource.cpp",
         "OMX.cpp",
+        "OMXStore.cpp",
         "OMXMaster.cpp",
         "OMXNodeInstance.cpp",
         "OMXUtils.cpp",
@@ -25,14 +29,16 @@
         "1.0/WOmxBufferSource.cpp",
     ],
 
-    include_dirs: [
-        "frameworks/av/include", // for media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h
-        "frameworks/av/include/media/",
-        "frameworks/av/media/libstagefright",
-        "frameworks/av/media/libstagefright/include",
-        "frameworks/native/include", // for media/hardware/MetadataBufferType.h
-        "frameworks/native/include/media/hardware",
-        "frameworks/native/include/media/openmax",
+    export_include_dirs: [
+        "include",
+    ],
+
+    header_libs: [
+        "media_plugin_headers",
+    ],
+
+    export_header_lib_headers: [
+        "media_plugin_headers",
     ],
 
     shared_libs: [
@@ -45,12 +51,12 @@
         "libgui",
         "libcutils",
         "libstagefright_foundation",
+        "libstagefright_xmlparser",
         "libdl",
         "libhidlbase",
         "libhidlmemory",
         "libhidltransport",
         "libnativewindow", // TODO(b/62923479): use header library
-        "libstagefright_xmlparser@1.0",
         "android.hidl.memory@1.0",
         "android.hidl.token@1.0-utils",
         "android.hardware.media@1.0",
@@ -59,7 +65,12 @@
         "android.hardware.graphics.bufferqueue@1.0",
     ],
 
-    export_shared_lib_headers: ["android.hidl.memory@1.0"],
+    export_shared_lib_headers: [
+        "android.hidl.memory@1.0",
+        "libmedia_omx",
+        "libstagefright_foundation",
+        "libstagefright_xmlparser",
+    ],
 
     cflags: [
         "-Werror",
@@ -80,15 +91,29 @@
     },
 }
 
-cc_library_static {
+cc_library_shared {
     name: "libstagefright_omx_utils",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     srcs: ["OMXUtils.cpp"],
-    include_dirs: [
-        "frameworks/av/media/libstagefright",
-        "frameworks/native/include/media/hardware",
-        "frameworks/native/include/media/openmax",
+    export_include_dirs: [
+        "include",
     ],
-    shared_libs: ["libmedia"],
+    header_libs: [
+        "media_plugin_headers",
+    ],
+    export_header_lib_headers: [
+        "media_plugin_headers",
+    ],
+    shared_libs: [
+        "libmedia_omx",
+        "liblog",
+    ],
+    export_shared_lib_headers: [
+        "libmedia_omx",
+    ],
     sanitize: {
         misc_undefined: [
             "signed-integer-overflow",
diff --git a/media/libstagefright/omx/BWGraphicBufferSource.cpp b/media/libstagefright/omx/BWGraphicBufferSource.cpp
index 79f6d93..94ef598 100644
--- a/media/libstagefright/omx/BWGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/BWGraphicBufferSource.cpp
@@ -17,15 +17,13 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "BWGraphicBufferSource"
 
-#include <OMX_Component.h>
-#include <OMX_IndexExt.h>
-
+#include <media/stagefright/omx/BWGraphicBufferSource.h>
+#include <media/stagefright/omx/OMXUtils.h>
+#include <media/openmax/OMX_Component.h>
+#include <media/openmax/OMX_IndexExt.h>
 #include <media/OMXBuffer.h>
 #include <media/IOMX.h>
 
-#include "OMXUtils.h"
-#include "BWGraphicBufferSource.h"
-
 namespace android {
 
 static const OMX_U32 kPortIndexInput = 0;
diff --git a/media/libstagefright/omx/FrameDropper.cpp b/media/libstagefright/omx/FrameDropper.cpp
index 9a4952e..0c50c58 100644
--- a/media/libstagefright/omx/FrameDropper.cpp
+++ b/media/libstagefright/omx/FrameDropper.cpp
@@ -18,8 +18,7 @@
 #define LOG_TAG "FrameDropper"
 #include <utils/Log.h>
 
-#include "FrameDropper.h"
-
+#include <media/stagefright/omx/FrameDropper.h>
 #include <media/stagefright/foundation/ADebug.h>
 
 namespace android {
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index d85ef89..1917d2a 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -22,7 +22,9 @@
 
 #define STRINGIFY_ENUMS // for asString in HardwareAPI.h/VideoAPI.h
 
-#include "GraphicBufferSource.h"
+#include <media/stagefright/omx/GraphicBufferSource.h>
+#include <media/stagefright/omx/FrameDropper.h>
+#include <media/stagefright/omx/OMXUtils.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/ColorUtils.h>
@@ -31,14 +33,12 @@
 #include <media/hardware/MetadataBufferType.h>
 #include <ui/GraphicBuffer.h>
 #include <gui/BufferItem.h>
-#include <HardwareAPI.h>
-#include "omx/OMXUtils.h"
-#include <OMX_Component.h>
-#include <OMX_IndexExt.h>
-#include "media/OMXBuffer.h"
+#include <media/hardware/HardwareAPI.h>
+#include <media/openmax/OMX_Component.h>
+#include <media/openmax/OMX_IndexExt.h>
+#include <media/OMXBuffer.h>
 
 #include <inttypes.h>
-#include "FrameDropper.h"
 
 #include <functional>
 #include <memory>
@@ -733,7 +733,7 @@
         } else {
             // snap to nearest capture point
             int64_t nFrames = std::llround(
-                    (timeUs - mPrevCaptureUs) * mCaptureFps);
+                    (timeUs - mPrevCaptureUs) * mCaptureFps / 1000000);
             if (nFrames <= 0) {
                 // skip this frame as it's too close to previous capture
                 ALOGV("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
@@ -741,9 +741,9 @@
             }
             mFrameCount += nFrames;
             mPrevCaptureUs = mBaseCaptureUs + std::llround(
-                    mFrameCount / mCaptureFps);
+                    mFrameCount * 1000000 / mCaptureFps);
             mPrevFrameUs = mBaseFrameUs + std::llround(
-                    mFrameCount / mFps);
+                    mFrameCount * 1000000 / mFps);
         }
 
         ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 8c1141d..09c4019 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -22,15 +22,12 @@
 
 #include <dlfcn.h>
 
-#include "../include/OMX.h"
-
-#include "../include/OMXNodeInstance.h"
-
+#include <media/stagefright/omx/OMX.h>
+#include <media/stagefright/omx/OMXNodeInstance.h>
+#include <media/stagefright/omx/BWGraphicBufferSource.h>
+#include <media/stagefright/omx/OMXMaster.h>
+#include <media/stagefright/omx/OMXUtils.h>
 #include <media/stagefright/foundation/ADebug.h>
-#include "BWGraphicBufferSource.h"
-
-#include "OMXMaster.h"
-#include "OMXUtils.h"
 
 namespace android {
 
@@ -118,15 +115,22 @@
         return StatusFromOMXError(err);
     }
     instance->setHandle(handle);
-    std::vector<AString> quirkVector;
-    if (mParser.getQuirks(name, &quirkVector) == OK) {
+
+    // Find quirks from mParser
+    const auto& codec = mParser.getCodecMap().find(name);
+    if (codec == mParser.getCodecMap().cend()) {
+        ALOGW("Failed to obtain quirks for omx component '%s' from XML files",
+                name);
+    } else {
         uint32_t quirks = 0;
-        for (const AString quirk : quirkVector) {
+        for (const auto& quirk : codec->second.quirkSet) {
             if (quirk == "requires-allocate-on-input-ports") {
-                quirks |= kRequiresAllocateBufferOnInputPorts;
+                quirks |= OMXNodeInstance::
+                        kRequiresAllocateBufferOnInputPorts;
             }
             if (quirk == "requires-allocate-on-output-ports") {
-                quirks |= kRequiresAllocateBufferOnOutputPorts;
+                quirks |= OMXNodeInstance::
+                        kRequiresAllocateBufferOnOutputPorts;
             }
         }
         instance->setQuirks(quirks);
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index ac9b0c3..fd97fdc 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -18,15 +18,13 @@
 #define LOG_TAG "OMXMaster"
 #include <utils/Log.h>
 
-#include "OMXMaster.h"
-
-#include "SoftOMXPlugin.h"
+#include <media/stagefright/omx/OMXMaster.h>
+#include <media/stagefright/omx/SoftOMXPlugin.h>
+#include <media/stagefright/foundation/ADebug.h>
 
 #include <dlfcn.h>
 #include <fcntl.h>
 
-#include <media/stagefright/foundation/ADebug.h>
-
 namespace android {
 
 OMXMaster::OMXMaster()
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 22d7d27..015a148 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -20,20 +20,20 @@
 
 #include <inttypes.h>
 
-#include "../include/OMXNodeInstance.h"
-#include "OMXMaster.h"
-#include "OMXUtils.h"
+#include <media/stagefright/omx/OMXNodeInstance.h>
+#include <media/stagefright/omx/OMXMaster.h>
+#include <media/stagefright/omx/OMXUtils.h>
 #include <android/IOMXBufferSource.h>
 
-#include <OMX_Component.h>
-#include <OMX_IndexExt.h>
-#include <OMX_VideoExt.h>
-#include <OMX_AsString.h>
+#include <media/openmax/OMX_Component.h>
+#include <media/openmax/OMX_IndexExt.h>
+#include <media/openmax/OMX_VideoExt.h>
+#include <media/openmax/OMX_AsString.h>
 
 #include <binder/IMemory.h>
 #include <cutils/properties.h>
 #include <gui/BufferQueue.h>
-#include <HardwareAPI.h>
+#include <media/hardware/HardwareAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ColorUtils.h>
@@ -41,7 +41,7 @@
 #include <utils/misc.h>
 #include <utils/NativeHandle.h>
 #include <media/OMXBuffer.h>
-#include <media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
 
 #include <hidlmemory/mapping.h>
 
@@ -246,6 +246,15 @@
     virtual ~CallbackDispatcher();
 
 private:
+    enum {
+        // This is used for frame_rendered message batching, which will eventually end up in a
+        // single AMessage in MediaCodec when it is signaled to the app. AMessage can contain
+        // up-to 64 key-value pairs, and each frame_rendered message uses 2 keys, so the max
+        // value for this would be 32. Nonetheless, limit this to 12 to which gives at least 10
+        // mseconds of batching at 120Hz.
+        kMaxQueueSize = 12,
+    };
+
     Mutex mLock;
 
     sp<OMXNodeInstance> const mOwner;
@@ -290,7 +299,7 @@
     Mutex::Autolock autoLock(mLock);
 
     mQueue.push_back(msg);
-    if (realTime) {
+    if (realTime || mQueue.size() >= kMaxQueueSize) {
         mQueueChanged.signal();
     }
 }
@@ -363,6 +372,8 @@
     mPortMode[1] = IOMX::kPortModePresetByteBuffer;
     mSecureBufferType[0] = kSecureBufferTypeUnknown;
     mSecureBufferType[1] = kSecureBufferTypeUnknown;
+    mGraphicBufferEnabled[0] = false;
+    mGraphicBufferEnabled[1] = false;
     mIsSecure = AString(name).endsWith(".secure");
     mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled("legacy-adaptive");
 }
@@ -486,6 +497,9 @@
             LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state);
             break;
     }
+
+    Mutex::Autolock _l(mLock);
+
     status_t err = mOwner->freeNode(this);
 
     mDispatcher.clear();
@@ -665,6 +679,11 @@
         return BAD_VALUE;
     }
 
+    if (mSailed || mNumPortBuffers[portIndex] > 0) {
+        android_errorWriteLog(0x534e4554, "29422020");
+        return INVALID_OPERATION;
+    }
+
     CLOG_CONFIG(setPortMode, "%s(%d), port %d", asString(mode), mode, portIndex);
 
     switch (mode) {
@@ -796,6 +815,12 @@
             } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
                 mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
             }
+        } else {
+            if (err == OMX_ErrorNone) {
+                mGraphicBufferEnabled[portIndex] = enable;
+            } else if (enable) {
+                mGraphicBufferEnabled[portIndex] = false;
+            }
         }
     } else {
         CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
@@ -1064,6 +1089,12 @@
     OMX_ERRORTYPE err = OMX_ErrorNone;
     bool isMetadata = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
 
+    if (!isMetadata && mGraphicBufferEnabled[portIndex]) {
+        ALOGE("b/62948670");
+        android_errorWriteLog(0x534e4554, "62948670");
+        return INVALID_OPERATION;
+    }
+
     size_t paramsSize;
     void* paramsPointer;
     if (params != NULL && hParams != NULL) {
@@ -1249,6 +1280,13 @@
                 portIndex, graphicBuffer, buffer);
     }
 
+    if (!mGraphicBufferEnabled[portIndex]) {
+        // Report error if this is not in graphic buffer mode.
+        ALOGE("b/62948670");
+        android_errorWriteLog(0x534e4554, "62948670");
+        return INVALID_OPERATION;
+    }
+
     // See if the newer version of the extension is present.
     OMX_INDEXTYPE index;
     if (OMX_GetExtensionIndex(
@@ -2168,8 +2206,8 @@
             msg.fenceFd = -1;
             msg.u.render_data.timestamp = renderData[i].nMediaTimeUs;
             msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs;
-
-            instance->mDispatcher->post(msg, false /* realTime */);
+            bool realTime = msg.u.render_data.timestamp == INT64_MAX;
+            instance->mDispatcher->post(msg, realTime);
         }
         return OMX_ErrorNone;
     }
diff --git a/media/libstagefright/omx/OMXStore.cpp b/media/libstagefright/omx/OMXStore.cpp
new file mode 100644
index 0000000..345336d
--- /dev/null
+++ b/media/libstagefright/omx/OMXStore.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMXStore"
+#include <utils/Log.h>
+
+#include <media/stagefright/omx/OMXUtils.h>
+#include <media/stagefright/omx/OMX.h>
+#include <media/stagefright/omx/OMXStore.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+
+#include <map>
+#include <string>
+
+namespace android {
+
+namespace {
+    struct RoleProperties {
+        std::string type;
+        bool isEncoder;
+        bool preferPlatformNodes;
+        std::multimap<size_t, IOMXStore::NodeInfo> nodeList;
+    };
+}  // Unnamed namespace
+
+OMXStore::OMXStore(
+        const char* owner,
+        const char* const* searchDirs,
+        const char* mainXmlName,
+        const char* performanceXmlName,
+        const char* profilingResultsXmlPath) {
+    MediaCodecsXmlParser parser(
+            searchDirs,
+            mainXmlName,
+            performanceXmlName,
+            profilingResultsXmlPath);
+    mParsingStatus = parser.getParsingStatus();
+
+    const auto& serviceAttributeMap = parser.getServiceAttributeMap();
+    mServiceAttributeList.reserve(serviceAttributeMap.size());
+    for (const auto& attributePair : serviceAttributeMap) {
+        Attribute attribute;
+        attribute.key = attributePair.first;
+        attribute.value = attributePair.second;
+        mServiceAttributeList.push_back(std::move(attribute));
+    }
+
+    const auto& roleMap = parser.getRoleMap();
+    mRoleList.reserve(roleMap.size());
+    for (const auto& rolePair : roleMap) {
+        RoleInfo role;
+        role.role = rolePair.first;
+        role.type = rolePair.second.type;
+        role.isEncoder = rolePair.second.isEncoder;
+        // TODO: Currently, preferPlatformNodes information is not available in
+        // the xml file. Once we have a way to provide this information, it
+        // should be parsed properly.
+        role.preferPlatformNodes = rolePair.first.compare(0, 5, "audio") == 0;
+        std::vector<NodeInfo>& nodeList = role.nodes;
+        nodeList.reserve(rolePair.second.nodeList.size());
+        for (const auto& nodePair : rolePair.second.nodeList) {
+            NodeInfo node;
+            node.name = nodePair.second.name;
+            node.owner = owner;
+            std::vector<Attribute>& attributeList = node.attributes;
+            attributeList.reserve(nodePair.second.attributeList.size());
+            for (const auto& attributePair : nodePair.second.attributeList) {
+                Attribute attribute;
+                attribute.key = attributePair.first;
+                attribute.value = attributePair.second;
+                attributeList.push_back(std::move(attribute));
+            }
+            nodeList.push_back(std::move(node));
+        }
+        mRoleList.push_back(std::move(role));
+    }
+
+    mPrefix = parser.getCommonPrefix();
+}
+
+status_t OMXStore::listServiceAttributes(std::vector<Attribute>* attributes) {
+    *attributes = mServiceAttributeList;
+    return mParsingStatus;
+}
+
+status_t OMXStore::getNodePrefix(std::string* prefix) {
+    *prefix = mPrefix;
+    return mParsingStatus;
+}
+
+status_t OMXStore::listRoles(std::vector<RoleInfo>* roleList) {
+    *roleList = mRoleList;
+    return mParsingStatus;
+}
+
+status_t OMXStore::getOmx(const std::string& name, sp<IOMX>* omx) {
+    *omx = new OMX();
+    return NO_ERROR;
+}
+
+OMXStore::~OMXStore() {
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/omx/OMXUtils.cpp b/media/libstagefright/omx/OMXUtils.cpp
index a66d565..5894837 100644
--- a/media/libstagefright/omx/OMXUtils.cpp
+++ b/media/libstagefright/omx/OMXUtils.cpp
@@ -19,13 +19,13 @@
 
 #include <string.h>
 
-#include <media/hardware/HardwareAPI.h>
+#include <media/stagefright/omx/OMXUtils.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaErrors.h>
+#include <media/hardware/HardwareAPI.h>
 #include <media/MediaDefs.h>
 #include <system/graphics-base.h>
-#include "OMXUtils.h"
 
 namespace android {
 
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index 5bae7e8..1ba5852 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -18,8 +18,7 @@
 #define LOG_TAG "SimpleSoftOMXComponent"
 #include <utils/Log.h>
 
-#include "include/SimpleSoftOMXComponent.h"
-
+#include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
diff --git a/media/libstagefright/omx/SoftOMXComponent.cpp b/media/libstagefright/omx/SoftOMXComponent.cpp
index df978f8..ee269e1 100644
--- a/media/libstagefright/omx/SoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftOMXComponent.cpp
@@ -18,8 +18,7 @@
 #define LOG_TAG "SoftOMXComponent"
 #include <utils/Log.h>
 
-#include "include/SoftOMXComponent.h"
-
+#include <media/stagefright/omx/SoftOMXComponent.h>
 #include <media/stagefright/foundation/ADebug.h>
 
 namespace android {
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index fccb12b..4946ada 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -18,8 +18,8 @@
 #define LOG_TAG "SoftOMXPlugin"
 #include <utils/Log.h>
 
-#include "SoftOMXPlugin.h"
-#include "include/SoftOMXComponent.h"
+#include <media/stagefright/omx/SoftOMXPlugin.h>
+#include <media/stagefright/omx/SoftOMXComponent.h>
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AString.h>
@@ -85,7 +85,21 @@
         libName.append(kComponents[i].mLibNameSuffix);
         libName.append(".so");
 
-        void *libHandle = dlopen(libName.c_str(), RTLD_NOW);
+        // RTLD_NODELETE means we keep the shared library around forever.
+        // this eliminates thrashing during sequences like loading soundpools.
+        // It also leaves the rest of the logic around the dlopen()/dlclose()
+        // calls in this file unchanged.
+        //
+        // Implications of the change:
+        // -- the codec process (where this happens) will have a slightly larger
+        //    long-term memory footprint as it accumulates the loaded shared libraries.
+        //    This is expected to be a small amount of memory.
+        // -- plugin codecs can no longer (and never should have) depend on a
+        //    free reset of any static data as the library would have crossed
+        //    a dlclose/dlopen cycle.
+        //
+
+        void *libHandle = dlopen(libName.c_str(), RTLD_NOW|RTLD_NODELETE);
 
         if (libHandle == NULL) {
             ALOGE("unable to dlopen %s: %s", libName.c_str(), dlerror());
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 920dd18..cb811a0 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -20,14 +20,14 @@
 #define LOG_TAG "SoftVideoDecoderOMXComponent"
 #include <utils/Log.h>
 
-#include "include/SoftVideoDecoderOMXComponent.h"
+#include <media/stagefright/omx/SoftVideoDecoderOMXComponent.h>
 
-#include <media/hardware/HardwareAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/MediaDefs.h>
+#include <media/hardware/HardwareAPI.h>
+#include <media/MediaDefs.h>
 
 namespace android {
 
@@ -182,11 +182,11 @@
 
 
 uint32_t SoftVideoDecoderOMXComponent::outputBufferWidth() {
-    return mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
+    return max(mIsAdaptive ? mAdaptiveMaxWidth : 0, mWidth);
 }
 
 uint32_t SoftVideoDecoderOMXComponent::outputBufferHeight() {
-    return mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
+    return max(mIsAdaptive ? mAdaptiveMaxHeight : 0, mHeight);
 }
 
 void SoftVideoDecoderOMXComponent::handlePortSettingsChange(
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 7ecfbbb..f33bdc0 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -21,25 +21,22 @@
 #include <utils/Log.h>
 #include <utils/misc.h>
 
-#include "include/SoftVideoEncoderOMXComponent.h"
-
-#include <media/hardware/HardwareAPI.h>
+#include <media/stagefright/omx/SoftVideoEncoderOMXComponent.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/MediaDefs.h>
+#include <media/hardware/HardwareAPI.h>
+#include <media/openmax/OMX_IndexExt.h>
+#include <media/MediaDefs.h>
 
 #include <ui/Fence.h>
 #include <ui/GraphicBufferMapper.h>
 #include <ui/Rect.h>
 
 #include <hardware/gralloc.h>
-
 #include <nativebase/nativebase.h>
 
-#include <OMX_IndexExt.h>
-
 namespace android {
 
 const static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = {
diff --git a/media/libstagefright/omx/1.0/Conversion.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
similarity index 99%
rename from media/libstagefright/omx/1.0/Conversion.h
rename to media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
index fd91574..8d8a2d9 100644
--- a/media/libstagefright/omx/1.0/Conversion.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
@@ -29,12 +29,12 @@
 #include <binder/Binder.h>
 #include <binder/Status.h>
 #include <ui/FenceTime.h>
-#include <media/OMXFenceParcelable.h>
 #include <cutils/native_handle.h>
 #include <gui/IGraphicBufferProducer.h>
 
+#include <media/OMXFenceParcelable.h>
 #include <media/OMXBuffer.h>
-#include <VideoAPI.h>
+#include <media/hardware/VideoAPI.h>
 
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
@@ -2064,8 +2064,10 @@
     int const* constFds = static_cast<int const*>(baseFds.get());
     numFds = baseNumFds;
     if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
-        native_handle_close(nh);
-        native_handle_delete(nh);
+        if (nh != nullptr) {
+            native_handle_close(nh);
+            native_handle_delete(nh);
+        }
         return false;
     }
 
diff --git a/media/libstagefright/omx/1.0/Omx.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
similarity index 95%
rename from media/libstagefright/omx/1.0/Omx.h
rename to media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
index 23784aa..a6a9d3e 100644
--- a/media/libstagefright/omx/1.0/Omx.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
@@ -20,10 +20,9 @@
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
-#include "../../include/OMXNodeInstance.h"
-
+#include <media/stagefright/omx/OMXNodeInstance.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
-#include <media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h>
 
 namespace android {
 
diff --git a/media/libstagefright/omx/1.0/OmxStore.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/OmxStore.h
similarity index 71%
rename from media/libstagefright/omx/1.0/OmxStore.h
rename to media/libstagefright/omx/include/media/stagefright/omx/1.0/OmxStore.h
index f377f5a..006d2d9 100644
--- a/media/libstagefright/omx/1.0/OmxStore.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/OmxStore.h
@@ -21,6 +21,7 @@
 #include <hidl/Status.h>
 
 #include <android/hardware/media/omx/1.0/IOmxStore.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
 
 namespace android {
 namespace hardware {
@@ -41,17 +42,31 @@
 using ::android::wp;
 
 struct OmxStore : public IOmxStore {
-    OmxStore();
+    OmxStore(
+            const char* owner = "default",
+            const char* const* searchDirs
+                = MediaCodecsXmlParser::defaultSearchDirs,
+            const char* mainXmlName
+                = MediaCodecsXmlParser::defaultMainXmlName,
+            const char* performanceXmlName
+                = MediaCodecsXmlParser::defaultPerformanceXmlName,
+            const char* profilingResultsXmlPath
+                = MediaCodecsXmlParser::defaultProfilingResultsXmlPath);
+
     virtual ~OmxStore();
 
-    // Methods from IOmx
+    // Methods from IOmxStore
     Return<void> listServiceAttributes(listServiceAttributes_cb) override;
     Return<void> getNodePrefix(getNodePrefix_cb) override;
     Return<void> listRoles(listRoles_cb) override;
     Return<sp<IOmx>> getOmx(hidl_string const&) override;
-};
 
-extern "C" IOmxStore* HIDL_FETCH_IOmxStore(const char* name);
+protected:
+    Status mParsingStatus;
+    hidl_string mPrefix;
+    hidl_vec<ServiceAttribute> mServiceAttributeList;
+    hidl_vec<RoleInfo> mRoleList;
+};
 
 }  // namespace implementation
 }  // namespace V1_0
diff --git a/media/libstagefright/omx/1.0/WGraphicBufferProducer.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferProducer.h
similarity index 100%
rename from media/libstagefright/omx/1.0/WGraphicBufferProducer.h
rename to media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferProducer.h
diff --git a/media/libstagefright/omx/1.0/WGraphicBufferSource.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferSource.h
similarity index 98%
rename from media/libstagefright/omx/1.0/WGraphicBufferSource.h
rename to media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferSource.h
index 4549c97..b9f22ab 100644
--- a/media/libstagefright/omx/1.0/WGraphicBufferSource.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferSource.h
@@ -28,7 +28,7 @@
 
 #include <android/BnGraphicBufferSource.h>
 
-#include "../GraphicBufferSource.h"
+#include <media/stagefright/omx/GraphicBufferSource.h>
 
 namespace android {
 namespace hardware {
diff --git a/media/libstagefright/omx/1.0/WOmxBufferSource.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WOmxBufferSource.h
similarity index 100%
rename from media/libstagefright/omx/1.0/WOmxBufferSource.h
rename to media/libstagefright/omx/include/media/stagefright/omx/1.0/WOmxBufferSource.h
diff --git a/media/libstagefright/omx/1.0/WOmxNode.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WOmxNode.h
similarity index 98%
rename from media/libstagefright/omx/1.0/WOmxNode.h
rename to media/libstagefright/omx/include/media/stagefright/omx/1.0/WOmxNode.h
index d715374..38d5885 100644
--- a/media/libstagefright/omx/1.0/WOmxNode.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WOmxNode.h
@@ -22,7 +22,7 @@
 
 #include <utils/Errors.h>
 
-#include "../../include/OMXNodeInstance.h"
+#include <media/stagefright/omx/OMXNodeInstance.h>
 
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
diff --git a/media/libstagefright/omx/1.0/WOmxObserver.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WOmxObserver.h
similarity index 100%
rename from media/libstagefright/omx/1.0/WOmxObserver.h
rename to media/libstagefright/omx/include/media/stagefright/omx/1.0/WOmxObserver.h
diff --git a/media/libstagefright/omx/1.0/WProducerListener.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WProducerListener.h
similarity index 100%
rename from media/libstagefright/omx/1.0/WProducerListener.h
rename to media/libstagefright/omx/include/media/stagefright/omx/1.0/WProducerListener.h
diff --git a/media/libstagefright/omx/BWGraphicBufferSource.h b/media/libstagefright/omx/include/media/stagefright/omx/BWGraphicBufferSource.h
similarity index 100%
rename from media/libstagefright/omx/BWGraphicBufferSource.h
rename to media/libstagefright/omx/include/media/stagefright/omx/BWGraphicBufferSource.h
diff --git a/media/libstagefright/omx/FrameDropper.h b/media/libstagefright/omx/include/media/stagefright/omx/FrameDropper.h
similarity index 100%
rename from media/libstagefright/omx/FrameDropper.h
rename to media/libstagefright/omx/include/media/stagefright/omx/FrameDropper.h
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/include/media/stagefright/omx/GraphicBufferSource.h
similarity index 99%
rename from media/libstagefright/omx/GraphicBufferSource.h
rename to media/libstagefright/omx/include/media/stagefright/omx/GraphicBufferSource.h
index 009691d..84fee6f 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/GraphicBufferSource.h
@@ -22,7 +22,7 @@
 #include <gui/BufferQueue.h>
 #include <utils/RefBase.h>
 
-#include <VideoAPI.h>
+#include <media/hardware/VideoAPI.h>
 #include <media/IOMX.h>
 #include <media/OMXFenceParcelable.h>
 #include <media/stagefright/foundation/ABase.h>
diff --git a/media/libstagefright/omx/IOmxNodeWrapper.h b/media/libstagefright/omx/include/media/stagefright/omx/IOmxNodeWrapper.h
similarity index 100%
rename from media/libstagefright/omx/IOmxNodeWrapper.h
rename to media/libstagefright/omx/include/media/stagefright/omx/IOmxNodeWrapper.h
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
similarity index 96%
rename from media/libstagefright/include/OMX.h
rename to media/libstagefright/omx/include/media/stagefright/omx/OMX.h
index 4af3d39..594b4c0 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
@@ -20,7 +20,7 @@
 #include <media/IOMX.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
-#include <media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
 #include "OmxNodeOwner.h"
 
 namespace android {
diff --git a/media/libstagefright/omx/OMXMaster.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXMaster.h
similarity index 97%
rename from media/libstagefright/omx/OMXMaster.h
rename to media/libstagefright/omx/include/media/stagefright/omx/OMXMaster.h
index 3f9c0ca..897f287 100644
--- a/media/libstagefright/omx/OMXMaster.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXMaster.h
@@ -18,7 +18,7 @@
 
 #define OMX_MASTER_H_
 
-#include <OMXPluginBase.h>
+#include <media/hardware/OMXPluginBase.h>
 
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
similarity index 95%
rename from media/libstagefright/include/OMXNodeInstance.h
rename to media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
index 8e08d15..1065ca5 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
@@ -92,6 +92,15 @@
     status_t getExtensionIndex(
             const char *parameterName, OMX_INDEXTYPE *index);
 
+    // Quirk still supported, even though deprecated
+    enum Quirks {
+        kRequiresAllocateBufferOnInputPorts   = 1,
+        kRequiresAllocateBufferOnOutputPorts  = 2,
+
+        kQuirksMask = kRequiresAllocateBufferOnInputPorts
+                    | kRequiresAllocateBufferOnOutputPorts,
+    };
+
     status_t setQuirks(OMX_U32 quirks);
 
     bool isSecure() const {
@@ -143,7 +152,7 @@
 
     bool mLegacyAdaptiveExperiment;
     IOMX::PortMode mPortMode[2];
-    // metadata and secure buffer type tracking
+    // metadata and secure buffer types and graphic buffer mode tracking
     MetadataBufferType mMetadataType[2];
     enum SecureBufferType {
         kSecureBufferTypeUnknown,
@@ -151,6 +160,7 @@
         kSecureBufferTypeNativeHandle,
     };
     SecureBufferType mSecureBufferType[2];
+    bool mGraphicBufferEnabled[2];
 
     // Following are OMX parameters managed by us (instead of the component)
     // OMX_IndexParamMaxFrameDurationForBitrateControl
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
new file mode 100644
index 0000000..e00d713
--- /dev/null
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_OMXSTORE_H_
+#define ANDROID_OMXSTORE_H_
+
+#include <media/IOMXStore.h>
+#include <media/IOMX.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+
+#include <vector>
+#include <string>
+
+namespace android {
+
+class OMXStore : public BnOMXStore {
+public:
+    OMXStore(
+            const char* owner = "default",
+            const char* const* searchDirs
+                = MediaCodecsXmlParser::defaultSearchDirs,
+            const char* mainXmlName
+                = MediaCodecsXmlParser::defaultMainXmlName,
+            const char* performanceXmlName
+                = MediaCodecsXmlParser::defaultPerformanceXmlName,
+            const char* profilingResultsXmlPath
+                = MediaCodecsXmlParser::defaultProfilingResultsXmlPath);
+
+    status_t listServiceAttributes(
+            std::vector<Attribute>* attributes) override;
+
+    status_t getNodePrefix(std::string* prefix) override;
+
+    status_t listRoles(std::vector<RoleInfo>* roleList) override;
+
+    status_t getOmx(const std::string& name, sp<IOMX>* omx) override;
+
+    ~OMXStore() override;
+
+protected:
+    status_t mParsingStatus;
+    std::string mPrefix;
+    std::vector<Attribute> mServiceAttributeList;
+    std::vector<RoleInfo> mRoleList;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_OMXSTORE_H_
diff --git a/media/libstagefright/omx/OMXUtils.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXUtils.h
similarity index 100%
rename from media/libstagefright/omx/OMXUtils.h
rename to media/libstagefright/omx/include/media/stagefright/omx/OMXUtils.h
diff --git a/media/libstagefright/include/SimpleSoftOMXComponent.h b/media/libstagefright/omx/include/media/stagefright/omx/SimpleSoftOMXComponent.h
similarity index 100%
rename from media/libstagefright/include/SimpleSoftOMXComponent.h
rename to media/libstagefright/omx/include/media/stagefright/omx/SimpleSoftOMXComponent.h
diff --git a/media/libstagefright/include/SoftOMXComponent.h b/media/libstagefright/omx/include/media/stagefright/omx/SoftOMXComponent.h
similarity index 100%
rename from media/libstagefright/include/SoftOMXComponent.h
rename to media/libstagefright/omx/include/media/stagefright/omx/SoftOMXComponent.h
diff --git a/media/libstagefright/omx/SoftOMXPlugin.h b/media/libstagefright/omx/include/media/stagefright/omx/SoftOMXPlugin.h
similarity index 96%
rename from media/libstagefright/omx/SoftOMXPlugin.h
rename to media/libstagefright/omx/include/media/stagefright/omx/SoftOMXPlugin.h
index c89cd87..8ec717e 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/SoftOMXPlugin.h
@@ -19,7 +19,7 @@
 #define SOFT_OMX_PLUGIN_H_
 
 #include <media/stagefright/foundation/ABase.h>
-#include <OMXPluginBase.h>
+#include <media/hardware/OMXPluginBase.h>
 
 namespace android {
 
diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoDecoderOMXComponent.h
similarity index 100%
rename from media/libstagefright/include/SoftVideoDecoderOMXComponent.h
rename to media/libstagefright/omx/include/media/stagefright/omx/SoftVideoDecoderOMXComponent.h
diff --git a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h b/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h
similarity index 100%
rename from media/libstagefright/include/SoftVideoEncoderOMXComponent.h
rename to media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h
diff --git a/media/libstagefright/omx/tests/FrameDropper_test.cpp b/media/libstagefright/omx/tests/FrameDropper_test.cpp
index f966b5e..a925da6 100644
--- a/media/libstagefright/omx/tests/FrameDropper_test.cpp
+++ b/media/libstagefright/omx/tests/FrameDropper_test.cpp
@@ -20,7 +20,7 @@
 
 #include <gtest/gtest.h>
 
-#include "FrameDropper.h"
+#include <media/stagefright/omx/FrameDropper.h>
 #include <media/stagefright/foundation/ADebug.h>
 
 namespace android {
diff --git a/media/libstagefright/tests/MediaCodecListOverrides_test.cpp b/media/libstagefright/tests/MediaCodecListOverrides_test.cpp
index 2599608..0c22a42 100644
--- a/media/libstagefright/tests/MediaCodecListOverrides_test.cpp
+++ b/media/libstagefright/tests/MediaCodecListOverrides_test.cpp
@@ -26,6 +26,8 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaCodecList.h>
 
+#include <vector>
+
 namespace android {
 
 static const char kTestOverridesStr[] =
@@ -117,7 +119,7 @@
 // TODO: the codec component never returns OMX_EventCmdComplete in unit test.
 TEST_F(MediaCodecListOverridesTest, DISABLED_profileCodecs) {
     sp<IMediaCodecList> list = MediaCodecList::getInstance();
-    Vector<sp<MediaCodecInfo>> infos;
+    std::vector<sp<MediaCodecInfo>> infos;
     for (size_t i = 0; i < list->countCodecs(); ++i) {
         infos.push_back(list->getCodecInfo(i));
     }
diff --git a/media/vndk/xmlparser/1.0/Android.bp b/media/libstagefright/xmlparser/Android.bp
similarity index 67%
rename from media/vndk/xmlparser/1.0/Android.bp
rename to media/libstagefright/xmlparser/Android.bp
index 2f10cb1..3507284 100644
--- a/media/vndk/xmlparser/1.0/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -1,14 +1,16 @@
 cc_library_shared {
-    name: "libstagefright_xmlparser@1.0",
+    name: "libstagefright_xmlparser",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "MediaCodecsXmlParser.cpp",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright",
-        "frameworks/av/include",
+    export_include_dirs: [
+        "include",
     ],
 
     shared_libs: [
@@ -17,6 +19,7 @@
         "liblog",
         "libcutils",
         "libstagefright_foundation",
+        "libstagefright_omx_utils",
     ],
 
     cflags: [
@@ -31,6 +34,10 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
+        cfi: true,
+        diag: {
+            cfi: true,
+        },
     },
 
 }
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
new file mode 100644
index 0000000..ffd30ea
--- /dev/null
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -0,0 +1,1054 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaCodecsXmlParser"
+
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+
+#include <utils/Log.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/omx/OMXUtils.h>
+#include <sys/stat.h>
+#include <expat.h>
+
+#include <cctype>
+#include <algorithm>
+
+namespace android {
+
+namespace {
+
+/**
+ * Search for a file in a list of search directories.
+ *
+ * For each string `searchDir` in `searchDirs`, `searchDir/fileName` will be
+ * tested whether it is a valid file name or not. If it is a valid file name,
+ * the concatenated name (`searchDir/fileName`) will be stored in the output
+ * variable `outPath`, and the function will return `true`. Otherwise, the
+ * search continues until the `nullptr` element in `searchDirs` is reached, at
+ * which point the function returns `false`.
+ *
+ * \param[in] searchDirs Null-terminated array of search paths.
+ * \param[in] fileName Name of the file to search.
+ * \param[out] outPath Full path of the file. `outPath` will hold a valid file
+ * name if the return value of this function is `true`.
+ * \return `true` if some element in `searchDirs` combined with `fileName` is a
+ * valid file name; `false` otherwise.
+ */
+bool findFileInDirs(
+        const char* const* searchDirs,
+        const char *fileName,
+        std::string *outPath) {
+    for (; *searchDirs != nullptr; ++searchDirs) {
+        *outPath = std::string(*searchDirs) + "/" + fileName;
+        struct stat fileStat;
+        if (stat(outPath->c_str(), &fileStat) == 0 &&
+                S_ISREG(fileStat.st_mode)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool strnEq(const char* s1, const char* s2, size_t count) {
+    return strncmp(s1, s2, count) == 0;
+}
+
+bool strEq(const char* s1, const char* s2) {
+    return strcmp(s1, s2) == 0;
+}
+
+bool striEq(const char* s1, const char* s2) {
+    return strcasecmp(s1, s2) == 0;
+}
+
+bool strHasPrefix(const char* test, const char* prefix) {
+    return strnEq(test, prefix, strlen(prefix));
+}
+
+bool parseBoolean(const char* s) {
+    return striEq(s, "y") ||
+            striEq(s, "yes") ||
+            striEq(s, "t") ||
+            striEq(s, "true") ||
+            striEq(s, "1");
+}
+
+status_t limitFoundMissingAttr(const char* name, const char *attr, bool found = true) {
+    ALOGE("limit '%s' with %s'%s' attribute", name,
+            (found ? "" : "no "), attr);
+    return -EINVAL;
+}
+
+status_t limitError(const char* name, const char *msg) {
+    ALOGE("limit '%s' %s", name, msg);
+    return -EINVAL;
+}
+
+status_t limitInvalidAttr(const char* name, const char* attr, const char* value) {
+    ALOGE("limit '%s' with invalid '%s' attribute (%s)", name,
+            attr, value);
+    return -EINVAL;
+}
+
+}; // unnamed namespace
+
+constexpr char const* MediaCodecsXmlParser::defaultSearchDirs[];
+constexpr char const* MediaCodecsXmlParser::defaultMainXmlName;
+constexpr char const* MediaCodecsXmlParser::defaultPerformanceXmlName;
+constexpr char const* MediaCodecsXmlParser::defaultProfilingResultsXmlPath;
+
+MediaCodecsXmlParser::MediaCodecsXmlParser(
+        const char* const* searchDirs,
+        const char* mainXmlName,
+        const char* performanceXmlName,
+        const char* profilingResultsXmlPath) :
+    mParsingStatus(NO_INIT),
+    mUpdate(false),
+    mCodecCounter(0) {
+    std::string path;
+    if (findFileInDirs(searchDirs, mainXmlName, &path)) {
+        parseTopLevelXMLFile(path.c_str(), false);
+    } else {
+        ALOGE("Cannot find %s", mainXmlName);
+        mParsingStatus = NAME_NOT_FOUND;
+    }
+    if (findFileInDirs(searchDirs, performanceXmlName, &path)) {
+        parseTopLevelXMLFile(path.c_str(), true);
+    }
+    if (profilingResultsXmlPath != nullptr) {
+        parseTopLevelXMLFile(profilingResultsXmlPath, true);
+    }
+}
+
+bool MediaCodecsXmlParser::parseTopLevelXMLFile(
+        const char *codecs_xml,
+        bool ignore_errors) {
+    // get href_base
+    const char *href_base_end = strrchr(codecs_xml, '/');
+    if (href_base_end != nullptr) {
+        mHrefBase = std::string(codecs_xml, href_base_end - codecs_xml + 1);
+    }
+
+    mParsingStatus = OK; // keeping this here for safety
+    mCurrentSection = SECTION_TOPLEVEL;
+
+    parseXMLFile(codecs_xml);
+
+    if (mParsingStatus != OK) {
+        ALOGW("parseTopLevelXMLFile(%s) failed", codecs_xml);
+        if (ignore_errors) {
+            mParsingStatus = OK;
+            return false;
+        }
+        mCodecMap.clear();
+        return false;
+    }
+    return true;
+}
+
+MediaCodecsXmlParser::~MediaCodecsXmlParser() {
+}
+
+void MediaCodecsXmlParser::parseXMLFile(const char *path) {
+    FILE *file = fopen(path, "r");
+
+    if (file == nullptr) {
+        ALOGW("unable to open media codecs configuration xml file: %s", path);
+        mParsingStatus = NAME_NOT_FOUND;
+        return;
+    }
+
+    XML_Parser parser = ::XML_ParserCreate(nullptr);
+    LOG_FATAL_IF(parser == nullptr, "XML_MediaCodecsXmlParserCreate() failed.");
+
+    ::XML_SetUserData(parser, this);
+    ::XML_SetElementHandler(
+            parser, StartElementHandlerWrapper, EndElementHandlerWrapper);
+
+    static constexpr int BUFF_SIZE = 512;
+    while (mParsingStatus == OK) {
+        void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
+        if (buff == nullptr) {
+            ALOGE("failed in call to XML_GetBuffer()");
+            mParsingStatus = UNKNOWN_ERROR;
+            break;
+        }
+
+        int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);
+        if (bytes_read < 0) {
+            ALOGE("failed in call to read");
+            mParsingStatus = ERROR_IO;
+            break;
+        }
+
+        XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0);
+        if (status != XML_STATUS_OK) {
+            ALOGE("malformed (%s)", ::XML_ErrorString(::XML_GetErrorCode(parser)));
+            mParsingStatus = ERROR_MALFORMED;
+            break;
+        }
+
+        if (bytes_read == 0) {
+            break;
+        }
+    }
+
+    ::XML_ParserFree(parser);
+
+    fclose(file);
+    file = nullptr;
+}
+
+// static
+void MediaCodecsXmlParser::StartElementHandlerWrapper(
+        void *me, const char *name, const char **attrs) {
+    static_cast<MediaCodecsXmlParser*>(me)->startElementHandler(name, attrs);
+}
+
+// static
+void MediaCodecsXmlParser::EndElementHandlerWrapper(void *me, const char *name) {
+    static_cast<MediaCodecsXmlParser*>(me)->endElementHandler(name);
+}
+
+status_t MediaCodecsXmlParser::includeXMLFile(const char **attrs) {
+    const char *href = nullptr;
+    size_t i = 0;
+    while (attrs[i] != nullptr) {
+        if (strEq(attrs[i], "href")) {
+            if (attrs[++i] == nullptr) {
+                return -EINVAL;
+            }
+            href = attrs[i];
+        } else {
+            ALOGE("includeXMLFile: unrecognized attribute: %s", attrs[i]);
+            return -EINVAL;
+        }
+        ++i;
+    }
+
+    // For security reasons and for simplicity, file names can only contain
+    // [a-zA-Z0-9_.] and must start with  media_codecs_ and end with .xml
+    for (i = 0; href[i] != '\0'; i++) {
+        if (href[i] == '.' || href[i] == '_' ||
+                (href[i] >= '0' && href[i] <= '9') ||
+                (href[i] >= 'A' && href[i] <= 'Z') ||
+                (href[i] >= 'a' && href[i] <= 'z')) {
+            continue;
+        }
+        ALOGE("invalid include file name: %s", href);
+        return -EINVAL;
+    }
+
+    std::string filename = href;
+    if (filename.compare(0, 13, "media_codecs_") != 0 ||
+            filename.compare(filename.size() - 4, 4, ".xml") != 0) {
+        ALOGE("invalid include file name: %s", href);
+        return -EINVAL;
+    }
+    filename.insert(0, mHrefBase);
+
+    parseXMLFile(filename.c_str());
+    return mParsingStatus;
+}
+
+void MediaCodecsXmlParser::startElementHandler(
+        const char *name, const char **attrs) {
+    if (mParsingStatus != OK) {
+        return;
+    }
+
+    bool inType = true;
+
+    if (strEq(name, "Include")) {
+        mParsingStatus = includeXMLFile(attrs);
+        if (mParsingStatus == OK) {
+            mSectionStack.push_back(mCurrentSection);
+            mCurrentSection = SECTION_INCLUDE;
+        }
+        return;
+    }
+
+    switch (mCurrentSection) {
+        case SECTION_TOPLEVEL:
+        {
+            if (strEq(name, "Decoders")) {
+                mCurrentSection = SECTION_DECODERS;
+            } else if (strEq(name, "Encoders")) {
+                mCurrentSection = SECTION_ENCODERS;
+            } else if (strEq(name, "Settings")) {
+                mCurrentSection = SECTION_SETTINGS;
+            }
+            break;
+        }
+
+        case SECTION_SETTINGS:
+        {
+            if (strEq(name, "Setting")) {
+                mParsingStatus = addSettingFromAttributes(attrs);
+            }
+            break;
+        }
+
+        case SECTION_DECODERS:
+        {
+            if (strEq(name, "MediaCodec")) {
+                mParsingStatus =
+                    addMediaCodecFromAttributes(false /* encoder */, attrs);
+
+                mCurrentSection = SECTION_DECODER;
+            }
+            break;
+        }
+
+        case SECTION_ENCODERS:
+        {
+            if (strEq(name, "MediaCodec")) {
+                mParsingStatus =
+                    addMediaCodecFromAttributes(true /* encoder */, attrs);
+
+                mCurrentSection = SECTION_ENCODER;
+            }
+            break;
+        }
+
+        case SECTION_DECODER:
+        case SECTION_ENCODER:
+        {
+            if (strEq(name, "Quirk")) {
+                mParsingStatus = addQuirk(attrs);
+            } else if (strEq(name, "Type")) {
+                mParsingStatus = addTypeFromAttributes(attrs,
+                        (mCurrentSection == SECTION_ENCODER));
+                mCurrentSection =
+                        (mCurrentSection == SECTION_DECODER ?
+                        SECTION_DECODER_TYPE : SECTION_ENCODER_TYPE);
+            }
+        }
+        inType = false;
+        // fall through
+
+        case SECTION_DECODER_TYPE:
+        case SECTION_ENCODER_TYPE:
+        {
+            // ignore limits and features specified outside of type
+            bool outside = !inType &&
+                    mCurrentType == mCurrentCodec->second.typeMap.end();
+            if (outside &&
+                    (strEq(name, "Limit") || strEq(name, "Feature"))) {
+                ALOGW("ignoring %s specified outside of a Type", name);
+            } else if (strEq(name, "Limit")) {
+                mParsingStatus = addLimit(attrs);
+            } else if (strEq(name, "Feature")) {
+                mParsingStatus = addFeature(attrs);
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+
+}
+
+void MediaCodecsXmlParser::endElementHandler(const char *name) {
+    if (mParsingStatus != OK) {
+        return;
+    }
+
+    switch (mCurrentSection) {
+        case SECTION_SETTINGS:
+        {
+            if (strEq(name, "Settings")) {
+                mCurrentSection = SECTION_TOPLEVEL;
+            }
+            break;
+        }
+
+        case SECTION_DECODERS:
+        {
+            if (strEq(name, "Decoders")) {
+                mCurrentSection = SECTION_TOPLEVEL;
+            }
+            break;
+        }
+
+        case SECTION_ENCODERS:
+        {
+            if (strEq(name, "Encoders")) {
+                mCurrentSection = SECTION_TOPLEVEL;
+            }
+            break;
+        }
+
+        case SECTION_DECODER_TYPE:
+        case SECTION_ENCODER_TYPE:
+        {
+            if (strEq(name, "Type")) {
+                mCurrentSection =
+                        (mCurrentSection == SECTION_DECODER_TYPE ?
+                        SECTION_DECODER : SECTION_ENCODER);
+
+                mCurrentType = mCurrentCodec->second.typeMap.end();
+            }
+            break;
+        }
+
+        case SECTION_DECODER:
+        {
+            if (strEq(name, "MediaCodec")) {
+                mCurrentSection = SECTION_DECODERS;
+                mCurrentName.clear();
+            }
+            break;
+        }
+
+        case SECTION_ENCODER:
+        {
+            if (strEq(name, "MediaCodec")) {
+                mCurrentSection = SECTION_ENCODERS;
+                mCurrentName.clear();
+            }
+            break;
+        }
+
+        case SECTION_INCLUDE:
+        {
+            if (strEq(name, "Include") && (mSectionStack.size() > 0)) {
+                mCurrentSection = mSectionStack.back();
+                mSectionStack.pop_back();
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+
+}
+
+status_t MediaCodecsXmlParser::addSettingFromAttributes(const char **attrs) {
+    const char *name = nullptr;
+    const char *value = nullptr;
+    const char *update = nullptr;
+
+    size_t i = 0;
+    while (attrs[i] != nullptr) {
+        if (strEq(attrs[i], "name")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addSettingFromAttributes: name is null");
+                return -EINVAL;
+            }
+            name = attrs[i];
+        } else if (strEq(attrs[i], "value")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addSettingFromAttributes: value is null");
+                return -EINVAL;
+            }
+            value = attrs[i];
+        } else if (strEq(attrs[i], "update")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addSettingFromAttributes: update is null");
+                return -EINVAL;
+            }
+            update = attrs[i];
+        } else {
+            ALOGE("addSettingFromAttributes: unrecognized attribute: %s", attrs[i]);
+            return -EINVAL;
+        }
+        ++i;
+    }
+
+    if (name == nullptr || value == nullptr) {
+        ALOGE("addSettingFromAttributes: name or value unspecified");
+        return -EINVAL;
+    }
+
+    // Boolean values are converted to "0" or "1".
+    if (strHasPrefix(name, "supports-")) {
+        value = parseBoolean(value) ? "1" : "0";
+    }
+
+    mUpdate = (update != nullptr) && parseBoolean(update);
+    auto attribute = mServiceAttributeMap.find(name);
+    if (attribute == mServiceAttributeMap.end()) { // New attribute name
+        if (mUpdate) {
+            ALOGE("addSettingFromAttributes: updating non-existing setting");
+            return -EINVAL;
+        }
+        mServiceAttributeMap.insert(Attribute(name, value));
+    } else { // Existing attribute name
+        if (!mUpdate) {
+            ALOGE("addSettingFromAttributes: adding existing setting");
+        }
+        attribute->second = value;
+    }
+
+    return OK;
+}
+
+status_t MediaCodecsXmlParser::addMediaCodecFromAttributes(
+        bool encoder, const char **attrs) {
+    const char *name = nullptr;
+    const char *type = nullptr;
+    const char *update = nullptr;
+
+    size_t i = 0;
+    while (attrs[i] != nullptr) {
+        if (strEq(attrs[i], "name")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addMediaCodecFromAttributes: name is null");
+                return -EINVAL;
+            }
+            name = attrs[i];
+        } else if (strEq(attrs[i], "type")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addMediaCodecFromAttributes: type is null");
+                return -EINVAL;
+            }
+            type = attrs[i];
+        } else if (strEq(attrs[i], "update")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addMediaCodecFromAttributes: update is null");
+                return -EINVAL;
+            }
+            update = attrs[i];
+        } else {
+            ALOGE("addMediaCodecFromAttributes: unrecognized attribute: %s", attrs[i]);
+            return -EINVAL;
+        }
+        ++i;
+    }
+
+    if (name == nullptr) {
+        ALOGE("addMediaCodecFromAttributes: name not found");
+        return -EINVAL;
+    }
+
+    mUpdate = (update != nullptr) && parseBoolean(update);
+    mCurrentCodec = mCodecMap.find(name);
+    if (mCurrentCodec == mCodecMap.end()) { // New codec name
+        if (mUpdate) {
+            ALOGE("addMediaCodecFromAttributes: updating non-existing codec");
+            return -EINVAL;
+        }
+        // Create a new codec in mCodecMap
+        mCurrentCodec = mCodecMap.insert(
+                Codec(name, CodecProperties())).first;
+        if (type != nullptr) {
+            mCurrentType = mCurrentCodec->second.typeMap.insert(
+                    Type(type, AttributeMap())).first;
+        } else {
+            mCurrentType = mCurrentCodec->second.typeMap.end();
+        }
+        mCurrentCodec->second.isEncoder = encoder;
+        mCurrentCodec->second.order = mCodecCounter++;
+    } else { // Existing codec name
+        if (!mUpdate) {
+            ALOGE("addMediaCodecFromAttributes: adding existing codec");
+            return -EINVAL;
+        }
+        if (type != nullptr) {
+            mCurrentType = mCurrentCodec->second.typeMap.find(type);
+            if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
+                ALOGE("addMediaCodecFromAttributes: updating non-existing type");
+                return -EINVAL;
+            }
+        } else {
+            // This should happen only when the codec has at most one type.
+            mCurrentType = mCurrentCodec->second.typeMap.begin();
+        }
+    }
+
+    return OK;
+}
+
+status_t MediaCodecsXmlParser::addQuirk(const char **attrs) {
+    const char *name = nullptr;
+
+    size_t i = 0;
+    while (attrs[i] != nullptr) {
+        if (strEq(attrs[i], "name")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addQuirk: name is null");
+                return -EINVAL;
+            }
+            name = attrs[i];
+        } else {
+            ALOGE("addQuirk: unrecognized attribute: %s", attrs[i]);
+            return -EINVAL;
+        }
+        ++i;
+    }
+
+    if (name == nullptr) {
+        ALOGE("addQuirk: name not found");
+        return -EINVAL;
+    }
+
+    mCurrentCodec->second.quirkSet.emplace(name);
+    return OK;
+}
+
+status_t MediaCodecsXmlParser::addTypeFromAttributes(const char **attrs, bool encoder) {
+    const char *name = nullptr;
+    const char *update = nullptr;
+
+    size_t i = 0;
+    while (attrs[i] != nullptr) {
+        if (strEq(attrs[i], "name")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addTypeFromAttributes: name is null");
+                return -EINVAL;
+            }
+            name = attrs[i];
+        } else if (strEq(attrs[i], "update")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addTypeFromAttributes: update is null");
+                return -EINVAL;
+            }
+            update = attrs[i];
+        } else {
+            ALOGE("addTypeFromAttributes: unrecognized attribute: %s", attrs[i]);
+            return -EINVAL;
+        }
+        ++i;
+    }
+
+    if (name == nullptr) {
+        return -EINVAL;
+    }
+
+    mCurrentCodec->second.isEncoder = encoder;
+    mCurrentType = mCurrentCodec->second.typeMap.find(name);
+    if (!mUpdate) {
+        if (mCurrentType != mCurrentCodec->second.typeMap.end()) {
+            ALOGE("addTypeFromAttributes: re-defining existing type without update");
+            return -EINVAL;
+        }
+        mCurrentType = mCurrentCodec->second.typeMap.insert(
+                Type(name, AttributeMap())).first;
+    } else if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
+        ALOGE("addTypeFromAttributes: updating non-existing type");
+    }
+    return OK;
+}
+
+status_t MediaCodecsXmlParser::addLimit(const char **attrs) {
+    const char* a_name = nullptr;
+    const char* a_default = nullptr;
+    const char* a_in = nullptr;
+    const char* a_max = nullptr;
+    const char* a_min = nullptr;
+    const char* a_range = nullptr;
+    const char* a_ranges = nullptr;
+    const char* a_scale = nullptr;
+    const char* a_value = nullptr;
+
+    size_t i = 0;
+    while (attrs[i] != nullptr) {
+        if (strEq(attrs[i], "name")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addLimit: name is null");
+                return -EINVAL;
+            }
+            a_name = attrs[i];
+        } else if (strEq(attrs[i], "default")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addLimit: default is null");
+                return -EINVAL;
+            }
+            a_default = attrs[i];
+        } else if (strEq(attrs[i], "in")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addLimit: in is null");
+                return -EINVAL;
+            }
+            a_in = attrs[i];
+        } else if (strEq(attrs[i], "max")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addLimit: max is null");
+                return -EINVAL;
+            }
+            a_max = attrs[i];
+        } else if (strEq(attrs[i], "min")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addLimit: min is null");
+                return -EINVAL;
+            }
+            a_min = attrs[i];
+        } else if (strEq(attrs[i], "range")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addLimit: range is null");
+                return -EINVAL;
+            }
+            a_range = attrs[i];
+        } else if (strEq(attrs[i], "ranges")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addLimit: ranges is null");
+                return -EINVAL;
+            }
+            a_ranges = attrs[i];
+        } else if (strEq(attrs[i], "scale")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addLimit: scale is null");
+                return -EINVAL;
+            }
+            a_scale = attrs[i];
+        } else if (strEq(attrs[i], "value")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addLimit: value is null");
+                return -EINVAL;
+            }
+            a_value = attrs[i];
+        } else {
+            ALOGE("addLimit: unrecognized limit: %s", attrs[i]);
+            return -EINVAL;
+        }
+        ++i;
+    }
+
+    if (a_name == nullptr) {
+        ALOGE("limit with no 'name' attribute");
+        return -EINVAL;
+    }
+
+    // size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio,
+    // measured-frame-rate, measured-blocks-per-second: range
+    // quality: range + default + [scale]
+    // complexity: range + default
+    if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
+        ALOGW("ignoring null type");
+        return OK;
+    }
+
+    std::string range;
+    if (strEq(a_name, "aspect-ratio") ||
+            strEq(a_name, "bitrate") ||
+            strEq(a_name, "block-count") ||
+            strEq(a_name, "blocks-per-second") ||
+            strEq(a_name, "complexity") ||
+            strEq(a_name, "frame-rate") ||
+            strEq(a_name, "quality") ||
+            strEq(a_name, "size") ||
+            strEq(a_name, "measured-blocks-per-second") ||
+            strHasPrefix(a_name, "measured-frame-rate-")) {
+        // "range" is specified in exactly one of the following forms:
+        // 1) min-max
+        // 2) value-value
+        // 3) range
+        if (a_min != nullptr && a_max != nullptr) {
+            // min-max
+            if (a_range != nullptr || a_value != nullptr) {
+                return limitError(a_name, "has 'min' and 'max' as well as 'range' or "
+                        "'value' attributes");
+            }
+            range = a_min;
+            range += '-';
+            range += a_max;
+        } else if (a_min != nullptr || a_max != nullptr) {
+            return limitError(a_name, "has only 'min' or 'max' attribute");
+        } else if (a_value != nullptr) {
+            // value-value
+            if (a_range != nullptr) {
+                return limitError(a_name, "has both 'range' and 'value' attributes");
+            }
+            range = a_value;
+            range += '-';
+            range += a_value;
+        } else if (a_range == nullptr) {
+            return limitError(a_name, "with no 'range', 'value' or 'min'/'max' attributes");
+        } else {
+            // range
+            range = a_range;
+        }
+
+        // "aspect-ratio" requires some special treatment.
+        if (strEq(a_name, "aspect-ratio")) {
+            // "aspect-ratio" must have "in".
+            if (a_in == nullptr) {
+                return limitFoundMissingAttr(a_name, "in", false);
+            }
+            // "in" must be either "pixels" or "blocks".
+            if (!strEq(a_in, "pixels") && !strEq(a_in, "blocks")) {
+                return limitInvalidAttr(a_name, "in", a_in);
+            }
+            // name will be "pixel-aspect-ratio-range" or
+            // "block-aspect-ratio-range".
+            mCurrentType->second[
+                    std::string(a_in).substr(0, strlen(a_in) - 1) +
+                    "-aspect-ratio-range"] = range;
+        } else {
+            // For everything else (apart from "aspect-ratio"), simply append
+            // "-range" to the name for the range-type property.
+            mCurrentType->second[std::string(a_name) + "-range"] = range;
+
+            // Only "quality" may have "scale".
+            if (!strEq(a_name, "quality") && a_scale != nullptr) {
+                return limitFoundMissingAttr(a_name, "scale");
+            } else if (strEq(a_name, "quality")) {
+                // The default value of "quality-scale" is "linear".
+                mCurrentType->second["quality-scale"] = a_scale == nullptr ?
+                        "linear" : a_scale;
+            }
+
+            // "quality" and "complexity" must have "default".
+            // Other limits must not have "default".
+            if (strEq(a_name, "quality") || strEq(a_name, "complexity")) {
+                if (a_default == nullptr) {
+                    return limitFoundMissingAttr(a_name, "default", false);
+                }
+                // name will be "quality-default" or "complexity-default".
+                mCurrentType->second[std::string(a_name) + "-default"] = a_default;
+            } else if (a_default != nullptr) {
+                return limitFoundMissingAttr(a_name, "default", true);
+            }
+        }
+    } else {
+        if (a_default != nullptr) {
+            return limitFoundMissingAttr(a_name, "default");
+        }
+        if (a_in != nullptr) {
+            return limitFoundMissingAttr(a_name, "in");
+        }
+        if (a_scale != nullptr) {
+            return limitFoundMissingAttr(a_name, "scale");
+        }
+        if (a_range != nullptr) {
+            return limitFoundMissingAttr(a_name, "range");
+        }
+        if (a_min != nullptr) {
+            return limitFoundMissingAttr(a_name, "min");
+        }
+
+        if (a_max != nullptr) {
+            // "max" must exist if and only if name is "channel-count" or
+            // "concurrent-instances".
+            // "min" is not ncessary.
+            if (strEq(a_name, "channel-count") ||
+                    strEq(a_name, "concurrent-instances")) {
+                mCurrentType->second[std::string("max-") + a_name] = a_max;
+            } else {
+                return limitFoundMissingAttr(a_name, "max", false);
+            }
+        } else if (strEq(a_name, "channel-count") ||
+                strEq(a_name, "concurrent-instances")) {
+            return limitFoundMissingAttr(a_name, "max");
+        }
+
+        if (a_ranges != nullptr) {
+            // "ranges" must exist if and only if name is "sample-rate".
+            if (strEq(a_name, "sample-rate")) {
+                mCurrentType->second["sample-rate-ranges"] = a_ranges;
+            } else {
+                return limitFoundMissingAttr(a_name, "ranges", false);
+            }
+        } else if (strEq(a_name, "sample-rate")) {
+            return limitFoundMissingAttr(a_name, "ranges");
+        }
+
+        if (a_value != nullptr) {
+            // "value" must exist if and only if name is "alignment" or
+            // "block-size".
+            if (strEq(a_name, "alignment") || strEq(a_name, "block-size")) {
+                mCurrentType->second[a_name] = a_value;
+            } else {
+                return limitFoundMissingAttr(a_name, "value", false);
+            }
+        } else if (strEq(a_name, "alignment") || strEq(a_name, "block-size")) {
+            return limitFoundMissingAttr(a_name, "value", false);
+        }
+
+    }
+
+    return OK;
+}
+
+status_t MediaCodecsXmlParser::addFeature(const char **attrs) {
+    size_t i = 0;
+    const char *name = nullptr;
+    int32_t optional = -1;
+    int32_t required = -1;
+    const char *value = nullptr;
+
+    while (attrs[i] != nullptr) {
+        if (strEq(attrs[i], "name")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addFeature: name is null");
+                return -EINVAL;
+            }
+            name = attrs[i];
+        } else if (strEq(attrs[i], "optional")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addFeature: optional is null");
+                return -EINVAL;
+            }
+            optional = parseBoolean(attrs[i]) ? 1 : 0;
+        } else if (strEq(attrs[i], "required")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addFeature: required is null");
+                return -EINVAL;
+            }
+            required = parseBoolean(attrs[i]) ? 1 : 0;
+        } else if (strEq(attrs[i], "value")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addFeature: value is null");
+                return -EINVAL;
+            }
+            value = attrs[i];
+        } else {
+            ALOGE("addFeature: unrecognized attribute: %s", attrs[i]);
+            return -EINVAL;
+        }
+        ++i;
+    }
+
+    // Every feature must have a name.
+    if (name == nullptr) {
+        ALOGE("feature with no 'name' attribute");
+        return -EINVAL;
+    }
+
+    if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
+        ALOGW("ignoring null type");
+        return OK;
+    }
+
+    if ((optional != -1) || (required != -1)) {
+        if (optional == required) {
+            ALOGE("feature '%s' is both/neither optional and required", name);
+            return -EINVAL;
+        }
+        if ((optional == 1) || (required == 1)) {
+            if (value != nullptr) {
+                ALOGE("feature '%s' cannot have extra 'value'", name);
+                return -EINVAL;
+            }
+            mCurrentType->second[std::string("feature-") + name] =
+                    optional == 1 ? "0" : "1";
+            return OK;
+        }
+    }
+    mCurrentType->second[std::string("feature-") + name] = value == nullptr ?
+            "0" : value;
+    return OK;
+}
+
+const MediaCodecsXmlParser::AttributeMap&
+        MediaCodecsXmlParser::getServiceAttributeMap() const {
+    return mServiceAttributeMap;
+}
+
+const MediaCodecsXmlParser::CodecMap&
+        MediaCodecsXmlParser::getCodecMap() const {
+    return mCodecMap;
+}
+
+const MediaCodecsXmlParser::RoleMap&
+        MediaCodecsXmlParser::getRoleMap() const {
+    if (mRoleMap.empty()) {
+        generateRoleMap();
+    }
+    return mRoleMap;
+}
+
+const char* MediaCodecsXmlParser::getCommonPrefix() const {
+    if (mCommonPrefix.empty()) {
+        generateCommonPrefix();
+    }
+    return mCommonPrefix.data();
+}
+
+status_t MediaCodecsXmlParser::getParsingStatus() const {
+    return mParsingStatus;
+}
+
+void MediaCodecsXmlParser::generateRoleMap() const {
+    for (const auto& codec : mCodecMap) {
+        const auto& codecName = codec.first;
+        bool isEncoder = codec.second.isEncoder;
+        size_t order = codec.second.order;
+        const auto& typeMap = codec.second.typeMap;
+        for (const auto& type : typeMap) {
+            const auto& typeName = type.first;
+            const char* roleName = GetComponentRole(isEncoder, typeName.data());
+            if (roleName == nullptr) {
+                ALOGE("Cannot find the role for %s of type %s",
+                        isEncoder ? "an encoder" : "a decoder",
+                        typeName.data());
+                continue;
+            }
+            const auto& typeAttributeMap = type.second;
+
+            auto roleIterator = mRoleMap.find(roleName);
+            std::multimap<size_t, NodeInfo>* nodeList;
+            if (roleIterator == mRoleMap.end()) {
+                RoleProperties roleProperties;
+                roleProperties.type = typeName;
+                roleProperties.isEncoder = isEncoder;
+                auto insertResult = mRoleMap.insert(
+                        std::make_pair(roleName, roleProperties));
+                if (!insertResult.second) {
+                    ALOGE("Cannot add role %s", roleName);
+                    continue;
+                }
+                nodeList = &insertResult.first->second.nodeList;
+            } else {
+                if (roleIterator->second.type != typeName) {
+                    ALOGE("Role %s has mismatching types: %s and %s",
+                            roleName,
+                            roleIterator->second.type.data(),
+                            typeName.data());
+                    continue;
+                }
+                if (roleIterator->second.isEncoder != isEncoder) {
+                    ALOGE("Role %s cannot be both an encoder and a decoder",
+                            roleName);
+                    continue;
+                }
+                nodeList = &roleIterator->second.nodeList;
+            }
+
+            NodeInfo nodeInfo;
+            nodeInfo.name = codecName;
+            nodeInfo.attributeList.reserve(typeAttributeMap.size());
+            for (const auto& attribute : typeAttributeMap) {
+                nodeInfo.attributeList.push_back(
+                        Attribute{attribute.first, attribute.second});
+            }
+            nodeList->insert(std::make_pair(
+                    std::move(order), std::move(nodeInfo)));
+        }
+    }
+}
+
+void MediaCodecsXmlParser::generateCommonPrefix() const {
+    if (mCodecMap.empty()) {
+        return;
+    }
+    auto i = mCodecMap.cbegin();
+    auto first = i->first.cbegin();
+    auto last = i->first.cend();
+    for (++i; i != mCodecMap.cend(); ++i) {
+        last = std::mismatch(
+                first, last, i->first.cbegin(), i->first.cend()).first;
+    }
+    mCommonPrefix.insert(mCommonPrefix.begin(), first, last);
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
new file mode 100644
index 0000000..cc69e52
--- /dev/null
+++ b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_STAGEFRIGHT_XMLPARSER_H_
+#define MEDIA_STAGEFRIGHT_XMLPARSER_H_
+
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <utils/StrongPointer.h>
+
+#include <string>
+#include <set>
+#include <map>
+#include <vector>
+
+namespace android {
+
+class MediaCodecsXmlParser {
+public:
+
+    // Treblized media codec list will be located in /odm/etc or /vendor/etc.
+    static constexpr char const* defaultSearchDirs[] =
+            {"/odm/etc", "/vendor/etc", "/etc", nullptr};
+    static constexpr char const* defaultMainXmlName =
+            "media_codecs.xml";
+    static constexpr char const* defaultPerformanceXmlName =
+            "media_codecs_performance.xml";
+    static constexpr char const* defaultProfilingResultsXmlPath =
+            "/data/misc/media/media_codecs_profiling_results.xml";
+
+    MediaCodecsXmlParser(
+            const char* const* searchDirs = defaultSearchDirs,
+            const char* mainXmlName = defaultMainXmlName,
+            const char* performanceXmlName = defaultPerformanceXmlName,
+            const char* profilingResultsXmlPath = defaultProfilingResultsXmlPath);
+    ~MediaCodecsXmlParser();
+
+    typedef std::pair<std::string, std::string> Attribute;
+    typedef std::map<std::string, std::string> AttributeMap;
+
+    typedef std::pair<std::string, AttributeMap> Type;
+    typedef std::map<std::string, AttributeMap> TypeMap;
+
+    typedef std::set<std::string> QuirkSet;
+
+    /**
+     * Properties of a codec (node)
+     */
+    struct CodecProperties {
+        bool isEncoder;    ///< Whether this codec is an encoder or a decoder
+        size_t order;      ///< Order of appearance in the file (starting from 0)
+        QuirkSet quirkSet; ///< Set of quirks requested by this codec
+        TypeMap typeMap;   ///< Map of types supported by this codec
+    };
+
+    typedef std::pair<std::string, CodecProperties> Codec;
+    typedef std::map<std::string, CodecProperties> CodecMap;
+
+    /**
+     * Properties of a node (for IOmxStore)
+     */
+    struct NodeInfo {
+        std::string name;
+        std::vector<Attribute> attributeList;
+    };
+
+    /**
+     * Properties of a role (for IOmxStore)
+     */
+    struct RoleProperties {
+        std::string type;
+        bool isEncoder;
+        std::multimap<size_t, NodeInfo> nodeList;
+    };
+
+    typedef std::pair<std::string, RoleProperties> Role;
+    typedef std::map<std::string, RoleProperties> RoleMap;
+
+    /**
+     * Return a map for attributes that are service-specific.
+     */
+    const AttributeMap& getServiceAttributeMap() const;
+
+    /**
+     * Return a map for codecs and their properties.
+     */
+    const CodecMap& getCodecMap() const;
+
+    /**
+     * Return a map for roles and their properties.
+     * This map is generated from the CodecMap.
+     */
+    const RoleMap& getRoleMap() const;
+
+    /**
+     * Return a common prefix of all node names.
+     *
+     * The prefix is not provided in the xml, so it has to be computed by taking
+     * the longest common prefix of all node names.
+     */
+    const char* getCommonPrefix() const;
+
+    status_t getParsingStatus() const;
+
+private:
+    enum Section {
+        SECTION_TOPLEVEL,
+        SECTION_SETTINGS,
+        SECTION_DECODERS,
+        SECTION_DECODER,
+        SECTION_DECODER_TYPE,
+        SECTION_ENCODERS,
+        SECTION_ENCODER,
+        SECTION_ENCODER_TYPE,
+        SECTION_INCLUDE,
+    };
+
+    status_t mParsingStatus;
+    Section mCurrentSection;
+    bool mUpdate;
+    std::vector<Section> mSectionStack;
+    std::string mHrefBase;
+
+    // Service attributes
+    AttributeMap mServiceAttributeMap;
+
+    // Codec attributes
+    std::string mCurrentName;
+    std::set<std::string> mCodecSet;
+    Codec mCodecListTemp[2048];
+    CodecMap mCodecMap;
+    size_t mCodecCounter;
+    CodecMap::iterator mCurrentCodec;
+    TypeMap::iterator mCurrentType;
+
+    // Role map
+    mutable RoleMap mRoleMap;
+
+    // Computed longest common prefix
+    mutable std::string mCommonPrefix;
+
+    bool parseTopLevelXMLFile(const char *path, bool ignore_errors = false);
+
+    void parseXMLFile(const char *path);
+
+    static void StartElementHandlerWrapper(
+            void *me, const char *name, const char **attrs);
+
+    static void EndElementHandlerWrapper(void *me, const char *name);
+
+    void startElementHandler(const char *name, const char **attrs);
+    void endElementHandler(const char *name);
+
+    status_t includeXMLFile(const char **attrs);
+    status_t addSettingFromAttributes(const char **attrs);
+    status_t addMediaCodecFromAttributes(bool encoder, const char **attrs);
+    void addMediaCodec(bool encoder, const char *name,
+            const char *type = nullptr);
+
+    status_t addQuirk(const char **attrs);
+    status_t addTypeFromAttributes(const char **attrs, bool encoder);
+    status_t addLimit(const char **attrs);
+    status_t addFeature(const char **attrs);
+    void addType(const char *name);
+
+    void generateRoleMap() const;
+    void generateCommonPrefix() const;
+
+    MediaCodecsXmlParser(const MediaCodecsXmlParser&) = delete;
+    MediaCodecsXmlParser& operator=(const MediaCodecsXmlParser&) = delete;
+};
+
+} // namespace android
+
+#endif // MEDIA_STAGEFRIGHT_XMLPARSER_H_
+
diff --git a/media/mtp/MtpDebug.cpp b/media/mtp/MtpDebug.cpp
index 1c04bcf..d2ede1c 100644
--- a/media/mtp/MtpDebug.cpp
+++ b/media/mtp/MtpDebug.cpp
@@ -102,6 +102,7 @@
     { "MTP_FORMAT_JP2",                             0x380F },
     { "MTP_FORMAT_JPX",                             0x3810 },
     { "MTP_FORMAT_DNG",                             0x3811 },
+    { "MTP_FORMAT_HEIF",                            0x3812 },
     { "MTP_FORMAT_UNDEFINED_FIRMWARE",              0xB802 },
     { "MTP_FORMAT_WINDOWS_IMAGE_FORMAT",            0xB881 },
     { "MTP_FORMAT_UNDEFINED_AUDIO",                 0xB900 },
diff --git a/media/mtp/mtp.h b/media/mtp/mtp.h
index 644780f..1c7829d 100644
--- a/media/mtp/mtp.h
+++ b/media/mtp/mtp.h
@@ -94,6 +94,7 @@
 #define MTP_FORMAT_JP2                                  0x380F   // JPEG2000 Baseline File Format
 #define MTP_FORMAT_JPX                                  0x3810   // JPEG2000 Extended File Format
 #define MTP_FORMAT_DNG                                  0x3811   // Digital Negative
+#define MTP_FORMAT_HEIF                                 0x3812   // HEIF images
 #define MTP_FORMAT_UNDEFINED_FIRMWARE                   0xB802
 #define MTP_FORMAT_WINDOWS_IMAGE_FORMAT                 0xB881
 #define MTP_FORMAT_UNDEFINED_AUDIO                      0xB900
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 6d28d1b..87b649a 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -53,21 +53,25 @@
 
 void
 AImage::close(int releaseFenceFd) {
+    lockReader();
     Mutex::Autolock _l(mLock);
     if (mIsClosed) {
         return;
     }
     sp<AImageReader> reader = mReader.promote();
-    if (reader == nullptr) {
-        LOG_ALWAYS_FATAL("Error: AImage not closed before AImageReader close!");
-        return;
+    if (reader != nullptr) {
+        reader->releaseImageLocked(this, releaseFenceFd);
+    } else if (mBuffer != nullptr) {
+        LOG_ALWAYS_FATAL("%s: parent AImageReader closed without releasing image %p",
+                __FUNCTION__, this);
     }
-    reader->releaseImageLocked(this, releaseFenceFd);
+
     // Should have been set to nullptr in releaseImageLocked
     // Set to nullptr here for extra safety only
     mBuffer = nullptr;
     mLockedBuffer = nullptr;
     mIsClosed = true;
+    unlockReader();
 }
 
 void
@@ -618,9 +622,7 @@
 void AImage_deleteAsync(AImage* image, int releaseFenceFd) {
     ALOGV("%s", __FUNCTION__);
     if (image != nullptr) {
-        image->lockReader();
         image->close(releaseFenceFd);
-        image->unlockReader();
         if (!image->isClosed()) {
             LOG_ALWAYS_FATAL("Image close failed!");
         }
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index 5d1a20b..e90783d 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -44,7 +44,11 @@
 const char* AImageReader::kGraphicBufferKey = "GraphicBuffer";
 
 bool
-AImageReader::isSupportedFormat(int32_t format) {
+AImageReader::isSupportedFormatAndUsage(int32_t format, uint64_t usage) {
+    // Check whether usage has either CPU_READ_OFTEN or CPU_READ set. Note that check against
+    // AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN (0x6) is sufficient as it implies
+    // AHARDWAREBUFFER_USAGE_CPU_READ (0x2).
+    bool hasCpuUsage = usage & AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
     switch (format) {
         case AIMAGE_FORMAT_RGBA_8888:
         case AIMAGE_FORMAT_RGBX_8888:
@@ -60,6 +64,9 @@
         case AIMAGE_FORMAT_DEPTH16:
         case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
             return true;
+        case AIMAGE_FORMAT_PRIVATE:
+            // For private format, cpu usage is prohibited.
+            return !hasCpuUsage;
         default:
             return false;
     }
@@ -83,6 +90,8 @@
         case AIMAGE_FORMAT_DEPTH16:
         case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
             return 1;
+        case AIMAGE_FORMAT_PRIVATE:
+            return 0;
         default:
             return -1;
     }
@@ -340,6 +349,7 @@
     for (auto it = mAcquiredImages.begin();
               it != mAcquiredImages.end(); it++) {
         AImage* image = *it;
+        releaseImageLocked(image, /*releaseFenceFd*/-1);
         image->close();
     }
 
@@ -606,9 +616,9 @@
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
 
-    if (!AImageReader::isSupportedFormat(format)) {
-        ALOGE("%s: format %d is not supported by AImageReader",
-                __FUNCTION__, format);
+    if (!AImageReader::isSupportedFormatAndUsage(format, usage)) {
+        ALOGE("%s: format %d is not supported with usage 0x%" PRIx64 " by AImageReader",
+                __FUNCTION__, format, usage);
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
 
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 989c1fd..989b937 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -49,7 +49,7 @@
 
 struct AImageReader : public RefBase {
   public:
-    static bool isSupportedFormat(int32_t format);
+    static bool isSupportedFormatAndUsage(int32_t format, uint64_t usage0);
     static int getNumPlanesForFormat(int32_t format);
 
     AImageReader(int32_t width,
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index 51143ac..eecc858 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -421,7 +421,7 @@
 
     for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
         keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
-        keyValuePairs[i].mValue = mObj->mQueryResults.keyAt(i).string();
+        keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
     }
     *numPairs = mObj->mQueryResults.size();
     return AMEDIA_OK;
diff --git a/media/ndk/include/media/NdkImage.h b/media/ndk/include/media/NdkImage.h
index d301d83..99cf5d5 100644
--- a/media/ndk/include/media/NdkImage.h
+++ b/media/ndk/include/media/NdkImage.h
@@ -491,7 +491,13 @@
     /**
      * Android private opaque image format.
      *
-     * <p>This format is not currently supported by {@link AImageReader}.</p>
+     * <p>The choices of the actual format and pixel data layout are entirely up to the
+     * device-specific and framework internal implementations, and may vary depending on use cases
+     * even for the same device. Also note that the contents of these buffers are not directly
+     * accessible to the application.</p>
+     *
+     * <p>When an {@link AImage} of this format is obtained from an {@link AImageReader} or
+     * {@link AImage_getNumberOfPlanes()} method will return zero.</p>
      */
     AIMAGE_FORMAT_PRIVATE           = 0x22
 };
diff --git a/media/ndk/include/media/NdkImageReader.h b/media/ndk/include/media/NdkImageReader.h
index c9c7a6b..a8667c9 100644
--- a/media/ndk/include/media/NdkImageReader.h
+++ b/media/ndk/include/media/NdkImageReader.h
@@ -68,7 +68,9 @@
  * @param height The default height in pixels of the Images that this reader will produce.
  * @param format The format of the Image that this reader will produce. This must be one of the
  *            AIMAGE_FORMAT_* enum value defined in {@link AIMAGE_FORMATS}. Note that not all
- *            formats are supported, like {@link AIMAGE_FORMAT_PRIVATE}.
+ *            formats are supported. One example is {@link AIMAGE_FORMAT_PRIVATE}, as it is not
+ *            intended to be read by applications directly. That format is supported by
+ *            {@link AImageReader_newWithUsage} introduced in API 26.
  * @param maxImages The maximum number of images the user will want to access simultaneously. This
  *            should be as small as possible to limit memory use. Once maxImages Images are obtained
  *            by the user, one of them has to be released before a new {@link AImage} will become
@@ -305,6 +307,28 @@
  * for the consumer usage. All other parameters and the return values are identical to those passed
  * to {@line AImageReader_new}.
  *
+ * <p>If the {@code format} is {@link AIMAGE_FORMAT_PRIVATE}, the created {@link AImageReader}
+ * will produce images whose contents are not directly accessible by the application. The application can
+ * still acquire images from this {@link AImageReader} and access {@link AHardwareBuffer} via
+ * {@link AImage_getHardwareBuffer()}. The {@link AHardwareBuffer} gained this way can then
+ * be passed back to hardware (such as GPU or hardware encoder if supported) for future processing.
+ * For example, you can obtain an {@link EGLClientBuffer} from the {@link AHardwareBuffer} by using
+ * {@link eglGetNativeClientBufferANDROID} extension and pass that {@link EGLClientBuffer} to {@link
+ * eglCreateImageKHR} to create an {@link EGLImage} resource type, which may then be bound to a
+ * texture via {@link glEGLImageTargetTexture2DOES} on supported devices. This can be useful for
+ * transporting textures that may be shared cross-process.</p>
+ * <p>In general, when software access to image data is not necessary, an {@link AImageReader}
+ * created with {@link AIMAGE_FORMAT_PRIVATE} format is more efficient, compared with {@link
+ * AImageReader}s using other format such as {@link AIMAGE_FORMAT_YUV_420_888}.</p>
+ *
+ * <p>Note that not all format and usage flag combination is supported by the {@link AImageReader},
+ * especially if {@code format} is {@link AIMAGE_FORMAT_PRIVATE}, {@code usage} must not include either
+ * {@link AHARDWAREBUFFER_USAGE_READ_RARELY} or {@link AHARDWAREBUFFER_USAGE_READ_OFTEN}</p>
+ *
+ * @param width The default width in pixels of the Images that this reader will produce.
+ * @param height The default height in pixels of the Images that this reader will produce.
+ * @param format The format of the Image that this reader will produce. This must be one of the
+ *            AIMAGE_FORMAT_* enum value defined in {@link AIMAGE_FORMATS}.
  * @param usage specifies how the consumer will access the AImage, using combination of the
  *            AHARDWAREBUFFER_USAGE flags described in {@link hardware_buffer.h}.
  *            Passing {@link AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN} is equivalent to calling
@@ -329,6 +353,11 @@
  *   {@link AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE}, or combined</td>
  * </tr>
  * </table>
+ * @return <ul>
+ *         <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ *         <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader is NULL, or one or more of width,
+ *                 height, format, maxImages, or usage arguments is not supported.</li>
+ *         <li>{@link AMEDIA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
  *
  * @see AImage
  * @see AImageReader_new
diff --git a/media/vndk/Android.bp b/media/vndk/Android.bp
deleted file mode 100644
index e93fd16..0000000
--- a/media/vndk/Android.bp
+++ /dev/null
@@ -1,4 +0,0 @@
-subdirs = [
-    "xmlparser/1.0",
-]
-
diff --git a/media/vndk/xmlparser/1.0/MediaCodecsXmlParser.cpp b/media/vndk/xmlparser/1.0/MediaCodecsXmlParser.cpp
deleted file mode 100644
index 84e5514..0000000
--- a/media/vndk/xmlparser/1.0/MediaCodecsXmlParser.cpp
+++ /dev/null
@@ -1,862 +0,0 @@
-/*
- * Copyright 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaCodecsXmlParser"
-#include <utils/Log.h>
-
-#include <media/vndk/xmlparser/1.0/MediaCodecsXmlParser.h>
-
-#include <media/MediaCodecInfo.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/MediaErrors.h>
-
-#include <sys/stat.h>
-
-#include <expat.h>
-#include <string>
-
-#define MEDIA_CODECS_CONFIG_FILE_PATH_MAX_LENGTH 256
-
-namespace android {
-
-namespace { // Local variables and functions
-
-const char *kProfilingResults =
-        "/data/misc/media/media_codecs_profiling_results.xml";
-
-// Treblized media codec list will be located in /odm/etc or /vendor/etc.
-const char *kConfigLocationList[] =
-        {"/odm/etc", "/vendor/etc", "/etc"};
-constexpr int kConfigLocationListSize =
-        (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
-
-bool findMediaCodecListFileFullPath(
-        const char *file_name, std::string *out_path) {
-    for (int i = 0; i < kConfigLocationListSize; i++) {
-        *out_path = std::string(kConfigLocationList[i]) + "/" + file_name;
-        struct stat file_stat;
-        if (stat(out_path->c_str(), &file_stat) == 0 &&
-                S_ISREG(file_stat.st_mode)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-// Find TypeInfo by name.
-std::vector<TypeInfo>::iterator findTypeInfo(
-        CodecInfo &codecInfo, const AString &typeName) {
-    return std::find_if(
-            codecInfo.mTypes.begin(), codecInfo.mTypes.end(),
-            [typeName](const auto &typeInfo) {
-                return typeInfo.mName == typeName;
-            });
-}
-
-// Convert a string into a boolean value.
-bool ParseBoolean(const char *s) {
-    if (!strcasecmp(s, "true") || !strcasecmp(s, "yes") || !strcasecmp(s, "y")) {
-        return true;
-    }
-    char *end;
-    unsigned long res = strtoul(s, &end, 10);
-    return *s != '\0' && *end == '\0' && res > 0;
-}
-
-} // unnamed namespace
-
-MediaCodecsXmlParser::MediaCodecsXmlParser() :
-    mInitCheck(NO_INIT),
-    mUpdate(false) {
-    std::string config_file_path;
-    if (findMediaCodecListFileFullPath(
-            "media_codecs.xml", &config_file_path)) {
-        parseTopLevelXMLFile(config_file_path.c_str(), false);
-    } else {
-        mInitCheck = NAME_NOT_FOUND;
-    }
-    if (findMediaCodecListFileFullPath(
-            "media_codecs_performance.xml", &config_file_path)) {
-        parseTopLevelXMLFile(config_file_path.c_str(), true);
-    }
-    parseTopLevelXMLFile(kProfilingResults, true);
-}
-
-void MediaCodecsXmlParser::parseTopLevelXMLFile(
-        const char *codecs_xml, bool ignore_errors) {
-    // get href_base
-    const char *href_base_end = strrchr(codecs_xml, '/');
-    if (href_base_end != NULL) {
-        mHrefBase = AString(codecs_xml, href_base_end - codecs_xml + 1);
-    }
-
-    mInitCheck = OK; // keeping this here for safety
-    mCurrentSection = SECTION_TOPLEVEL;
-    mDepth = 0;
-
-    parseXMLFile(codecs_xml);
-
-    if (mInitCheck != OK) {
-        if (ignore_errors) {
-            mInitCheck = OK;
-            return;
-        }
-        mCodecInfos.clear();
-        return;
-    }
-}
-
-MediaCodecsXmlParser::~MediaCodecsXmlParser() {
-}
-
-status_t MediaCodecsXmlParser::initCheck() const {
-    return mInitCheck;
-}
-
-void MediaCodecsXmlParser::parseXMLFile(const char *path) {
-    FILE *file = fopen(path, "r");
-
-    if (file == NULL) {
-        ALOGW("unable to open media codecs configuration xml file: %s", path);
-        mInitCheck = NAME_NOT_FOUND;
-        return;
-    }
-
-    ALOGV("Start parsing %s", path);
-    XML_Parser parser = ::XML_ParserCreate(NULL);
-    CHECK(parser != NULL);
-
-    ::XML_SetUserData(parser, this);
-    ::XML_SetElementHandler(
-            parser, StartElementHandlerWrapper, EndElementHandlerWrapper);
-
-    const int BUFF_SIZE = 512;
-    while (mInitCheck == OK) {
-        void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
-        if (buff == NULL) {
-            ALOGE("failed in call to XML_GetBuffer()");
-            mInitCheck = UNKNOWN_ERROR;
-            break;
-        }
-
-        int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);
-        if (bytes_read < 0) {
-            ALOGE("failed in call to read");
-            mInitCheck = ERROR_IO;
-            break;
-        }
-
-        XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0);
-        if (status != XML_STATUS_OK) {
-            ALOGE("malformed (%s)", ::XML_ErrorString(::XML_GetErrorCode(parser)));
-            mInitCheck = ERROR_MALFORMED;
-            break;
-        }
-
-        if (bytes_read == 0) {
-            break;
-        }
-    }
-
-    ::XML_ParserFree(parser);
-
-    fclose(file);
-    file = NULL;
-}
-
-// static
-void MediaCodecsXmlParser::StartElementHandlerWrapper(
-        void *me, const char *name, const char **attrs) {
-    static_cast<MediaCodecsXmlParser *>(me)->startElementHandler(name, attrs);
-}
-
-// static
-void MediaCodecsXmlParser::EndElementHandlerWrapper(void *me, const char *name) {
-    static_cast<MediaCodecsXmlParser *>(me)->endElementHandler(name);
-}
-
-status_t MediaCodecsXmlParser::includeXMLFile(const char **attrs) {
-    const char *href = NULL;
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "href")) {
-            if (attrs[i + 1] == NULL) {
-                return -EINVAL;
-            }
-            href = attrs[i + 1];
-            ++i;
-        } else {
-            ALOGE("includeXMLFile: unrecognized attribute: %s", attrs[i]);
-            return -EINVAL;
-        }
-        ++i;
-    }
-
-    // For security reasons and for simplicity, file names can only contain
-    // [a-zA-Z0-9_.] and must start with  media_codecs_ and end with .xml
-    for (i = 0; href[i] != '\0'; i++) {
-        if (href[i] == '.' || href[i] == '_' ||
-                (href[i] >= '0' && href[i] <= '9') ||
-                (href[i] >= 'A' && href[i] <= 'Z') ||
-                (href[i] >= 'a' && href[i] <= 'z')) {
-            continue;
-        }
-        ALOGE("invalid include file name: %s", href);
-        return -EINVAL;
-    }
-
-    AString filename = href;
-    if (!filename.startsWith("media_codecs_") ||
-        !filename.endsWith(".xml")) {
-        ALOGE("invalid include file name: %s", href);
-        return -EINVAL;
-    }
-    filename.insert(mHrefBase, 0);
-
-    parseXMLFile(filename.c_str());
-    return mInitCheck;
-}
-
-void MediaCodecsXmlParser::startElementHandler(
-        const char *name, const char **attrs) {
-    if (mInitCheck != OK) {
-        return;
-    }
-
-    bool inType = true;
-
-    if (!strcmp(name, "Include")) {
-        mInitCheck = includeXMLFile(attrs);
-        if (mInitCheck == OK) {
-            mPastSections.push(mCurrentSection);
-            mCurrentSection = SECTION_INCLUDE;
-        }
-        ++mDepth;
-        return;
-    }
-
-    switch (mCurrentSection) {
-        case SECTION_TOPLEVEL:
-        {
-            if (!strcmp(name, "Decoders")) {
-                mCurrentSection = SECTION_DECODERS;
-            } else if (!strcmp(name, "Encoders")) {
-                mCurrentSection = SECTION_ENCODERS;
-            } else if (!strcmp(name, "Settings")) {
-                mCurrentSection = SECTION_SETTINGS;
-            }
-            break;
-        }
-
-        case SECTION_SETTINGS:
-        {
-            if (!strcmp(name, "Setting")) {
-                mInitCheck = addSettingFromAttributes(attrs);
-            }
-            break;
-        }
-
-        case SECTION_DECODERS:
-        {
-            if (!strcmp(name, "MediaCodec")) {
-                mInitCheck =
-                    addMediaCodecFromAttributes(false /* encoder */, attrs);
-
-                mCurrentSection = SECTION_DECODER;
-            }
-            break;
-        }
-
-        case SECTION_ENCODERS:
-        {
-            if (!strcmp(name, "MediaCodec")) {
-                mInitCheck =
-                    addMediaCodecFromAttributes(true /* encoder */, attrs);
-
-                mCurrentSection = SECTION_ENCODER;
-            }
-            break;
-        }
-
-        case SECTION_DECODER:
-        case SECTION_ENCODER:
-        {
-            if (!strcmp(name, "Quirk")) {
-                mInitCheck = addQuirk(attrs);
-            } else if (!strcmp(name, "Type")) {
-                mInitCheck = addTypeFromAttributes(attrs, (mCurrentSection == SECTION_ENCODER));
-                mCurrentSection =
-                    (mCurrentSection == SECTION_DECODER
-                            ? SECTION_DECODER_TYPE : SECTION_ENCODER_TYPE);
-            }
-        }
-        inType = false;
-        // fall through
-
-        case SECTION_DECODER_TYPE:
-        case SECTION_ENCODER_TYPE:
-        {
-            // ignore limits and features specified outside of type
-            bool outside = !inType && mCurrentType == mCodecInfos[mCurrentName].mTypes.end();
-            if (outside && (!strcmp(name, "Limit") || !strcmp(name, "Feature"))) {
-                ALOGW("ignoring %s specified outside of a Type", name);
-            } else if (!strcmp(name, "Limit")) {
-                mInitCheck = addLimit(attrs);
-            } else if (!strcmp(name, "Feature")) {
-                mInitCheck = addFeature(attrs);
-            }
-            break;
-        }
-
-        default:
-            break;
-    }
-
-    ++mDepth;
-}
-
-void MediaCodecsXmlParser::endElementHandler(const char *name) {
-    if (mInitCheck != OK) {
-        return;
-    }
-
-    switch (mCurrentSection) {
-        case SECTION_SETTINGS:
-        {
-            if (!strcmp(name, "Settings")) {
-                mCurrentSection = SECTION_TOPLEVEL;
-            }
-            break;
-        }
-
-        case SECTION_DECODERS:
-        {
-            if (!strcmp(name, "Decoders")) {
-                mCurrentSection = SECTION_TOPLEVEL;
-            }
-            break;
-        }
-
-        case SECTION_ENCODERS:
-        {
-            if (!strcmp(name, "Encoders")) {
-                mCurrentSection = SECTION_TOPLEVEL;
-            }
-            break;
-        }
-
-        case SECTION_DECODER_TYPE:
-        case SECTION_ENCODER_TYPE:
-        {
-            if (!strcmp(name, "Type")) {
-                mCurrentSection =
-                    (mCurrentSection == SECTION_DECODER_TYPE
-                            ? SECTION_DECODER : SECTION_ENCODER);
-
-                mCurrentType = mCodecInfos[mCurrentName].mTypes.end();
-            }
-            break;
-        }
-
-        case SECTION_DECODER:
-        {
-            if (!strcmp(name, "MediaCodec")) {
-                mCurrentSection = SECTION_DECODERS;
-                mCurrentName.clear();
-            }
-            break;
-        }
-
-        case SECTION_ENCODER:
-        {
-            if (!strcmp(name, "MediaCodec")) {
-                mCurrentSection = SECTION_ENCODERS;
-                mCurrentName.clear();
-            }
-            break;
-        }
-
-        case SECTION_INCLUDE:
-        {
-            if (!strcmp(name, "Include") && mPastSections.size() > 0) {
-                mCurrentSection = mPastSections.top();
-                mPastSections.pop();
-            }
-            break;
-        }
-
-        default:
-            break;
-    }
-
-    --mDepth;
-}
-
-status_t MediaCodecsXmlParser::addSettingFromAttributes(const char **attrs) {
-    const char *name = NULL;
-    const char *value = NULL;
-    const char *update = NULL;
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "name")) {
-            if (attrs[i + 1] == NULL) {
-                ALOGE("addSettingFromAttributes: name is null");
-                return -EINVAL;
-            }
-            name = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "value")) {
-            if (attrs[i + 1] == NULL) {
-                ALOGE("addSettingFromAttributes: value is null");
-                return -EINVAL;
-            }
-            value = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "update")) {
-            if (attrs[i + 1] == NULL) {
-                ALOGE("addSettingFromAttributes: update is null");
-                return -EINVAL;
-            }
-            update = attrs[i + 1];
-            ++i;
-        } else {
-            ALOGE("addSettingFromAttributes: unrecognized attribute: %s", attrs[i]);
-            return -EINVAL;
-        }
-
-        ++i;
-    }
-
-    if (name == NULL || value == NULL) {
-        ALOGE("addSettingFromAttributes: name or value unspecified");
-        return -EINVAL;
-    }
-
-    mUpdate = (update != NULL) && ParseBoolean(update);
-    if (mUpdate != (mGlobalSettings.count(name) > 0)) {
-        ALOGE("addSettingFromAttributes: updating non-existing setting");
-        return -EINVAL;
-    }
-    mGlobalSettings[name] = value;
-
-    return OK;
-}
-
-status_t MediaCodecsXmlParser::addMediaCodecFromAttributes(
-        bool encoder, const char **attrs) {
-    const char *name = NULL;
-    const char *type = NULL;
-    const char *update = NULL;
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "name")) {
-            if (attrs[i + 1] == NULL) {
-                ALOGE("addMediaCodecFromAttributes: name is null");
-                return -EINVAL;
-            }
-            name = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "type")) {
-            if (attrs[i + 1] == NULL) {
-                ALOGE("addMediaCodecFromAttributes: type is null");
-                return -EINVAL;
-            }
-            type = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "update")) {
-            if (attrs[i + 1] == NULL) {
-                ALOGE("addMediaCodecFromAttributes: update is null");
-                return -EINVAL;
-            }
-            update = attrs[i + 1];
-            ++i;
-        } else {
-            ALOGE("addMediaCodecFromAttributes: unrecognized attribute: %s", attrs[i]);
-            return -EINVAL;
-        }
-
-        ++i;
-    }
-
-    if (name == NULL) {
-        ALOGE("addMediaCodecFromAttributes: name not found");
-        return -EINVAL;
-    }
-
-    mUpdate = (update != NULL) && ParseBoolean(update);
-    if (mUpdate != (mCodecInfos.count(name) > 0)) {
-        ALOGE("addMediaCodecFromAttributes: updating non-existing codec or vice versa");
-        return -EINVAL;
-    }
-
-    CodecInfo *info = &mCodecInfos[name];
-    if (mUpdate) {
-        // existing codec
-        mCurrentName = name;
-        mCurrentType = info->mTypes.begin();
-        if (type != NULL) {
-            // existing type
-            mCurrentType = findTypeInfo(*info, type);
-            if (mCurrentType == info->mTypes.end()) {
-                ALOGE("addMediaCodecFromAttributes: updating non-existing type");
-                return -EINVAL;
-            }
-        }
-    } else {
-        // new codec
-        mCurrentName = name;
-        mQuirks[name].clear();
-        info->mTypes.clear();
-        info->mTypes.emplace_back();
-        mCurrentType = --info->mTypes.end();
-        mCurrentType->mName = type;
-        info->mIsEncoder = encoder;
-    }
-
-    return OK;
-}
-
-status_t MediaCodecsXmlParser::addQuirk(const char **attrs) {
-    const char *name = NULL;
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "name")) {
-            if (attrs[i + 1] == NULL) {
-                ALOGE("addQuirk: name is null");
-                return -EINVAL;
-            }
-            name = attrs[i + 1];
-            ++i;
-        } else {
-            ALOGE("addQuirk: unrecognized attribute: %s", attrs[i]);
-            return -EINVAL;
-        }
-
-        ++i;
-    }
-
-    if (name == NULL) {
-        ALOGE("addQuirk: name not found");
-        return -EINVAL;
-    }
-
-    mQuirks[mCurrentName].emplace_back(name);
-    return OK;
-}
-
-status_t MediaCodecsXmlParser::addTypeFromAttributes(const char **attrs, bool encoder) {
-    const char *name = NULL;
-    const char *update = NULL;
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (!strcmp(attrs[i], "name")) {
-            if (attrs[i + 1] == NULL) {
-                ALOGE("addTypeFromAttributes: name is null");
-                return -EINVAL;
-            }
-            name = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "update")) {
-            if (attrs[i + 1] == NULL) {
-                ALOGE("addTypeFromAttributes: update is null");
-                return -EINVAL;
-            }
-            update = attrs[i + 1];
-            ++i;
-        } else {
-            ALOGE("addTypeFromAttributes: unrecognized attribute: %s", attrs[i]);
-            return -EINVAL;
-        }
-
-        ++i;
-    }
-
-    if (name == NULL) {
-        return -EINVAL;
-    }
-
-    CodecInfo *info = &mCodecInfos[mCurrentName];
-    info->mIsEncoder = encoder;
-    mCurrentType = findTypeInfo(*info, name);
-    if (!mUpdate) {
-        if (mCurrentType != info->mTypes.end()) {
-            ALOGE("addTypeFromAttributes: re-defining existing type without update");
-            return -EINVAL;
-        }
-        info->mTypes.emplace_back();
-        mCurrentType = --info->mTypes.end();
-    } else if (mCurrentType == info->mTypes.end()) {
-        ALOGE("addTypeFromAttributes: updating non-existing type");
-        return -EINVAL;
-    }
-
-    return OK;
-}
-
-static status_t limitFoundMissingAttr(const AString &name, const char *attr, bool found = true) {
-    ALOGE("limit '%s' with %s'%s' attribute", name.c_str(),
-            (found ? "" : "no "), attr);
-    return -EINVAL;
-}
-
-static status_t limitError(const AString &name, const char *msg) {
-    ALOGE("limit '%s' %s", name.c_str(), msg);
-    return -EINVAL;
-}
-
-static status_t limitInvalidAttr(const AString &name, const char *attr, const AString &value) {
-    ALOGE("limit '%s' with invalid '%s' attribute (%s)", name.c_str(),
-            attr, value.c_str());
-    return -EINVAL;
-}
-
-status_t MediaCodecsXmlParser::addLimit(const char **attrs) {
-    sp<AMessage> msg = new AMessage();
-
-    size_t i = 0;
-    while (attrs[i] != NULL) {
-        if (attrs[i + 1] == NULL) {
-            ALOGE("addLimit: limit is not given");
-            return -EINVAL;
-        }
-
-        // attributes with values
-        if (!strcmp(attrs[i], "name")
-                || !strcmp(attrs[i], "default")
-                || !strcmp(attrs[i], "in")
-                || !strcmp(attrs[i], "max")
-                || !strcmp(attrs[i], "min")
-                || !strcmp(attrs[i], "range")
-                || !strcmp(attrs[i], "ranges")
-                || !strcmp(attrs[i], "scale")
-                || !strcmp(attrs[i], "value")) {
-            msg->setString(attrs[i], attrs[i + 1]);
-            ++i;
-        } else {
-            ALOGE("addLimit: unrecognized limit: %s", attrs[i]);
-            return -EINVAL;
-        }
-        ++i;
-    }
-
-    AString name;
-    if (!msg->findString("name", &name)) {
-        ALOGE("limit with no 'name' attribute");
-        return -EINVAL;
-    }
-
-    // size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio,
-    // measured-frame-rate, measured-blocks-per-second: range
-    // quality: range + default + [scale]
-    // complexity: range + default
-    bool found;
-    if (mCurrentType == mCodecInfos[mCurrentName].mTypes.end()) {
-        ALOGW("ignoring null type");
-        return OK;
-    }
-
-    if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
-            || name == "blocks-per-second" || name == "complexity"
-            || name == "frame-rate" || name == "quality" || name == "size"
-            || name == "measured-blocks-per-second" || name.startsWith("measured-frame-rate-")) {
-        AString min, max;
-        if (msg->findString("min", &min) && msg->findString("max", &max)) {
-            min.append("-");
-            min.append(max);
-            if (msg->contains("range") || msg->contains("value")) {
-                return limitError(name, "has 'min' and 'max' as well as 'range' or "
-                        "'value' attributes");
-            }
-            msg->setString("range", min);
-        } else if (msg->contains("min") || msg->contains("max")) {
-            return limitError(name, "has only 'min' or 'max' attribute");
-        } else if (msg->findString("value", &max)) {
-            min = max;
-            min.append("-");
-            min.append(max);
-            if (msg->contains("range")) {
-                return limitError(name, "has both 'range' and 'value' attributes");
-            }
-            msg->setString("range", min);
-        }
-
-        AString range, scale = "linear", def, in_;
-        if (!msg->findString("range", &range)) {
-            return limitError(name, "with no 'range', 'value' or 'min'/'max' attributes");
-        }
-
-        if ((name == "quality" || name == "complexity") ^
-                (found = msg->findString("default", &def))) {
-            return limitFoundMissingAttr(name, "default", found);
-        }
-        if (name != "quality" && msg->findString("scale", &scale)) {
-            return limitFoundMissingAttr(name, "scale");
-        }
-        if ((name == "aspect-ratio") ^ (found = msg->findString("in", &in_))) {
-            return limitFoundMissingAttr(name, "in", found);
-        }
-
-        if (name == "aspect-ratio") {
-            if (!(in_ == "pixels") && !(in_ == "blocks")) {
-                return limitInvalidAttr(name, "in", in_);
-            }
-            in_.erase(5, 1); // (pixel|block)-aspect-ratio
-            in_.append("-");
-            in_.append(name);
-            name = in_;
-        }
-        if (name == "quality") {
-            mCurrentType->mDetails["quality-scale"] = scale;
-        }
-        if (name == "quality" || name == "complexity") {
-            AString tag = name;
-            tag.append("-default");
-            mCurrentType->mDetails[tag] = def;
-        }
-        AString tag = name;
-        tag.append("-range");
-        mCurrentType->mDetails[tag] = range;
-    } else {
-        AString max, value, ranges;
-        if (msg->contains("default")) {
-            return limitFoundMissingAttr(name, "default");
-        } else if (msg->contains("in")) {
-            return limitFoundMissingAttr(name, "in");
-        } else if ((name == "channel-count" || name == "concurrent-instances") ^
-                (found = msg->findString("max", &max))) {
-            return limitFoundMissingAttr(name, "max", found);
-        } else if (msg->contains("min")) {
-            return limitFoundMissingAttr(name, "min");
-        } else if (msg->contains("range")) {
-            return limitFoundMissingAttr(name, "range");
-        } else if ((name == "sample-rate") ^
-                (found = msg->findString("ranges", &ranges))) {
-            return limitFoundMissingAttr(name, "ranges", found);
-        } else if (msg->contains("scale")) {
-            return limitFoundMissingAttr(name, "scale");
-        } else if ((name == "alignment" || name == "block-size") ^
-                (found = msg->findString("value", &value))) {
-            return limitFoundMissingAttr(name, "value", found);
-        }
-
-        if (max.size()) {
-            AString tag = "max-";
-            tag.append(name);
-            mCurrentType->mDetails[tag] = max;
-        } else if (value.size()) {
-            mCurrentType->mDetails[name] = value;
-        } else if (ranges.size()) {
-            AString tag = name;
-            tag.append("-ranges");
-            mCurrentType->mDetails[tag] = ranges;
-        } else {
-            ALOGW("Ignoring unrecognized limit '%s'", name.c_str());
-        }
-    }
-
-    return OK;
-}
-
-status_t MediaCodecsXmlParser::addFeature(const char **attrs) {
-    size_t i = 0;
-    const char *name = NULL;
-    int32_t optional = -1;
-    int32_t required = -1;
-    const char *value = NULL;
-
-    while (attrs[i] != NULL) {
-        if (attrs[i + 1] == NULL) {
-            ALOGE("addFeature: feature is not given");
-            return -EINVAL;
-        }
-
-        // attributes with values
-        if (!strcmp(attrs[i], "name")) {
-            name = attrs[i + 1];
-            ++i;
-        } else if (!strcmp(attrs[i], "optional") || !strcmp(attrs[i], "required")) {
-            int value = (int)ParseBoolean(attrs[i + 1]);
-            if (!strcmp(attrs[i], "optional")) {
-                optional = value;
-            } else {
-                required = value;
-            }
-            ++i;
-        } else if (!strcmp(attrs[i], "value")) {
-            value = attrs[i + 1];
-            ++i;
-        } else {
-            ALOGE("addFeature: unrecognized attribute: %s", attrs[i]);
-            return -EINVAL;
-        }
-        ++i;
-    }
-    if (name == NULL) {
-        ALOGE("feature with no 'name' attribute");
-        return -EINVAL;
-    }
-
-    if (optional == required && optional != -1) {
-        ALOGE("feature '%s' is both/neither optional and required", name);
-        return -EINVAL;
-    }
-
-    if (mCurrentType == mCodecInfos[mCurrentName].mTypes.end()) {
-        ALOGW("ignoring null type");
-        return OK;
-    }
-    if (value != NULL) {
-        mCurrentType->mStringFeatures[name] = value;
-    } else {
-        mCurrentType->mBoolFeatures[name] = (required == 1) || (optional == 0);
-    }
-    return OK;
-}
-
-void MediaCodecsXmlParser::getGlobalSettings(
-        std::map<AString, AString> *settings) const {
-    settings->clear();
-    settings->insert(mGlobalSettings.begin(), mGlobalSettings.end());
-}
-
-status_t MediaCodecsXmlParser::getCodecInfo(const char *name, CodecInfo *info) const {
-    if (mCodecInfos.count(name) == 0) {
-        ALOGE("Codec not found with name '%s'", name);
-        return NAME_NOT_FOUND;
-    }
-    *info = mCodecInfos.at(name);
-    return OK;
-}
-
-status_t MediaCodecsXmlParser::getQuirks(const char *name, std::vector<AString> *quirks) const {
-    if (mQuirks.count(name) == 0) {
-        ALOGE("Codec not found with name '%s'", name);
-        return NAME_NOT_FOUND;
-    }
-    quirks->clear();
-    quirks->insert(quirks->end(), mQuirks.at(name).begin(), mQuirks.at(name).end());
-    return OK;
-}
-
-}  // namespace android
diff --git a/radio/Android.bp b/radio/Android.bp
deleted file mode 100644
index 8e614f2..0000000
--- a/radio/Android.bp
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 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.
-
-cc_library_shared {
-    name: "libradio",
-
-    srcs: [
-        "Radio.cpp",
-        "IRadio.cpp",
-        "IRadioClient.cpp",
-        "IRadioService.cpp",
-    ],
-
-    shared_libs: [
-        "libcutils",
-        "libutils",
-        "liblog",
-        "libbinder",
-        "libradio_metadata",
-    ],
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-}
diff --git a/radio/IRadio.cpp b/radio/IRadio.cpp
deleted file mode 100644
index 72f3b68..0000000
--- a/radio/IRadio.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
-**
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "IRadio"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-#include <utils/Errors.h>
-#include <binder/IMemory.h>
-#include <radio/IRadio.h>
-#include <radio/IRadioService.h>
-#include <radio/IRadioClient.h>
-#include <system/radio.h>
-#include <system/RadioMetadataWrapper.h>
-
-namespace android {
-
-enum {
-    DETACH = IBinder::FIRST_CALL_TRANSACTION,
-    SET_CONFIGURATION,
-    GET_CONFIGURATION,
-    SET_MUTE,
-    GET_MUTE,
-    SCAN,
-    STEP,
-    TUNE,
-    CANCEL,
-    GET_PROGRAM_INFORMATION,
-    HAS_CONTROL
-};
-
-class BpRadio: public BpInterface<IRadio>
-{
-public:
-    explicit BpRadio(const sp<IBinder>& impl)
-        : BpInterface<IRadio>(impl)
-    {
-    }
-
-    void detach()
-    {
-        ALOGV("detach");
-        Parcel data, reply;
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        remote()->transact(DETACH, data, &reply);
-    }
-
-    virtual status_t setConfiguration(const struct radio_band_config *config)
-    {
-        Parcel data, reply;
-        if (config == NULL) {
-            return BAD_VALUE;
-        }
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        data.write(config, sizeof(struct radio_band_config));
-        status_t status = remote()->transact(SET_CONFIGURATION, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-    virtual status_t getConfiguration(struct radio_band_config *config)
-    {
-        Parcel data, reply;
-        if (config == NULL) {
-            return BAD_VALUE;
-        }
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        status_t status = remote()->transact(GET_CONFIGURATION, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            if (status == NO_ERROR) {
-                reply.read(config, sizeof(struct radio_band_config));
-            }
-        }
-        return status;
-    }
-
-    virtual status_t setMute(bool mute)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        data.writeInt32(mute ? 1 : 0);
-        status_t status = remote()->transact(SET_MUTE, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-    virtual status_t getMute(bool *mute)
-    {
-        Parcel data, reply;
-        if (mute == NULL) {
-            return BAD_VALUE;
-        }
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        status_t status = remote()->transact(GET_MUTE, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            if (status == NO_ERROR) {
-                int32_t muteread = reply.readInt32();
-                *mute = muteread != 0;
-            }
-        }
-        return status;
-    }
-
-    virtual status_t scan(radio_direction_t direction, bool skipSubChannel)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        data.writeInt32(direction);
-        data.writeInt32(skipSubChannel ? 1 : 0);
-        status_t status = remote()->transact(SCAN, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-    virtual status_t step(radio_direction_t direction, bool skipSubChannel)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        data.writeInt32(direction);
-        data.writeInt32(skipSubChannel ? 1 : 0);
-        status_t status = remote()->transact(STEP, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-    virtual status_t tune(uint32_t channel, uint32_t subChannel)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        data.writeUint32(channel);
-        data.writeUint32(subChannel);
-        status_t status = remote()->transact(TUNE, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-    virtual status_t cancel()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        status_t status = remote()->transact(CANCEL, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-    virtual status_t getProgramInformation(struct radio_program_info *info)
-    {
-        Parcel data, reply;
-        if (info == nullptr || info->metadata == nullptr) {
-            return BAD_VALUE;
-        }
-        radio_metadata_t *metadata = info->metadata;
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        status_t status = remote()->transact(GET_PROGRAM_INFORMATION, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            if (status == NO_ERROR) {
-                reply.read(info, sizeof(struct radio_program_info));
-                // restore local metadata pointer
-                info->metadata = metadata;
-
-                uint32_t metadataSize = reply.readUint32();
-                if (metadataSize != 0) {
-                    radio_metadata_t *newMetadata = (radio_metadata_t *)malloc(metadataSize);
-                    if (newMetadata == NULL) {
-                        return NO_MEMORY;
-                    }
-                    reply.read(newMetadata, metadataSize);
-                    status = radio_metadata_add_metadata(&info->metadata, newMetadata);
-                    free(newMetadata);
-                }
-            }
-        }
-        return status;
-    }
-
-    virtual status_t hasControl(bool *hasControl)
-    {
-        Parcel data, reply;
-        if (hasControl == NULL) {
-            return BAD_VALUE;
-        }
-        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
-        status_t status = remote()->transact(HAS_CONTROL, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            if (status == NO_ERROR) {
-                *hasControl = reply.readInt32() != 0;
-            }
-        }
-        return status;
-    }
-};
-
-IMPLEMENT_META_INTERFACE(Radio, "android.hardware.IRadio");
-
-// ----------------------------------------------------------------------
-
-status_t BnRadio::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case DETACH: {
-            ALOGV("DETACH");
-            CHECK_INTERFACE(IRadio, data, reply);
-            detach();
-            return NO_ERROR;
-        } break;
-        case SET_CONFIGURATION: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            struct radio_band_config config;
-            data.read(&config, sizeof(struct radio_band_config));
-            status_t status = setConfiguration(&config);
-            reply->writeInt32(status);
-            return NO_ERROR;
-        }
-        case GET_CONFIGURATION: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            struct radio_band_config config;
-            status_t status = getConfiguration(&config);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->write(&config, sizeof(struct radio_band_config));
-            }
-            return NO_ERROR;
-        }
-        case SET_MUTE: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            bool mute = data.readInt32() != 0;
-            status_t status = setMute(mute);
-            reply->writeInt32(status);
-            return NO_ERROR;
-        }
-        case GET_MUTE: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            bool mute;
-            status_t status = getMute(&mute);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->writeInt32(mute ? 1 : 0);
-            }
-            return NO_ERROR;
-        }
-        case SCAN: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            radio_direction_t direction = (radio_direction_t)data.readInt32();
-            bool skipSubChannel = data.readInt32() == 1;
-            status_t status = scan(direction, skipSubChannel);
-            reply->writeInt32(status);
-            return NO_ERROR;
-        }
-        case STEP: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            radio_direction_t direction = (radio_direction_t)data.readInt32();
-            bool skipSubChannel = data.readInt32() == 1;
-            status_t status = step(direction, skipSubChannel);
-            reply->writeInt32(status);
-            return NO_ERROR;
-        }
-        case TUNE: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            uint32_t channel = data.readUint32();
-            uint32_t subChannel = data.readUint32();
-            status_t status = tune(channel, subChannel);
-            reply->writeInt32(status);
-            return NO_ERROR;
-        }
-        case CANCEL: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            status_t status = cancel();
-            reply->writeInt32(status);
-            return NO_ERROR;
-        }
-        case GET_PROGRAM_INFORMATION: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            struct radio_program_info info;
-            RadioMetadataWrapper metadataWrapper(&info.metadata);
-
-            status_t status = getProgramInformation(&info);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->write(&info, sizeof(struct radio_program_info));
-                if (radio_metadata_get_count(info.metadata) > 0) {
-                    size_t size = radio_metadata_get_size(info.metadata);
-                    reply->writeUint32((uint32_t)size);
-                    reply->write(info.metadata, size);
-                } else {
-                    reply->writeUint32(0);
-                }
-            }
-            return NO_ERROR;
-        }
-        case HAS_CONTROL: {
-            CHECK_INTERFACE(IRadio, data, reply);
-            bool control;
-            status_t status = hasControl(&control);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->writeInt32(control ? 1 : 0);
-            }
-            return NO_ERROR;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/radio/IRadioClient.cpp b/radio/IRadioClient.cpp
deleted file mode 100644
index ca21949..0000000
--- a/radio/IRadioClient.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-**
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <radio/IRadioClient.h>
-
-namespace android {
-
-enum {
-    ON_EVENT = IBinder::FIRST_CALL_TRANSACTION,
-};
-
-class BpRadioClient: public BpInterface<IRadioClient>
-{
-
-public:
-    explicit BpRadioClient(const sp<IBinder>& impl)
-        : BpInterface<IRadioClient>(impl)
-    {
-    }
-
-    virtual void onEvent(const sp<IMemory>& eventMemory)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IRadioClient::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(eventMemory));
-        remote()->transact(ON_EVENT,
-                           data,
-                           &reply);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(RadioClient,
-                         "android.hardware.IRadioClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnRadioClient::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case ON_EVENT: {
-            CHECK_INTERFACE(IRadioClient, data, reply);
-            sp<IMemory> eventMemory = interface_cast<IMemory>(
-                data.readStrongBinder());
-            onEvent(eventMemory);
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }   return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/radio/IRadioService.cpp b/radio/IRadioService.cpp
deleted file mode 100644
index 72e3a61..0000000
--- a/radio/IRadioService.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
-**
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "BpRadioService"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <utils/Errors.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <radio/IRadioService.h>
-#include <radio/IRadio.h>
-#include <radio/IRadioClient.h>
-
-namespace android {
-
-enum {
-    LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
-    ATTACH,
-};
-
-#define MAX_ITEMS_PER_LIST 1024
-
-class BpRadioService: public BpInterface<IRadioService>
-{
-public:
-    explicit BpRadioService(const sp<IBinder>& impl)
-        : BpInterface<IRadioService>(impl)
-    {
-    }
-
-    virtual status_t listModules(struct radio_properties *properties,
-                                 uint32_t *numModules)
-    {
-        if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
-        uint32_t numModulesReq = (properties == NULL) ? 0 : *numModules;
-        data.writeInt32(numModulesReq);
-        status_t status = remote()->transact(LIST_MODULES, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            *numModules = (uint32_t)reply.readInt32();
-        }
-        ALOGV("listModules() status %d got *numModules %d", status, *numModules);
-        if (status == NO_ERROR) {
-            if (numModulesReq > *numModules) {
-                numModulesReq = *numModules;
-            }
-            if (numModulesReq > 0) {
-                reply.read(properties, numModulesReq * sizeof(struct radio_properties));
-            }
-        }
-        return status;
-    }
-
-    virtual status_t attach(radio_handle_t handle,
-                            const sp<IRadioClient>& client,
-                            const struct radio_band_config *config,
-                            bool withAudio,
-                            sp<IRadio>& radio)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
-        data.writeInt32(handle);
-        data.writeStrongBinder(IInterface::asBinder(client));
-        ALOGV("attach() config %p withAudio %d region %d type %d",
-              config == NULL ? 0 : config, withAudio,
-              config == NULL ? 0 : config->region,
-              config == NULL ? 0 : config->band.type);
-        if (config == NULL) {
-            data.writeInt32(0);
-        } else {
-            data.writeInt32(1);
-            data.write(config, sizeof(struct radio_band_config));
-        }
-        data.writeInt32(withAudio ? 1 : 0);
-        status_t status = remote()->transact(ATTACH, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = reply.readInt32();
-        if (reply.readInt32() != 0) {
-            radio = interface_cast<IRadio>(reply.readStrongBinder());
-        }
-        return status;
-    }
-};
-
-IMPLEMENT_META_INTERFACE(RadioService, "android.hardware.IRadioService");
-
-// ----------------------------------------------------------------------
-
-status_t BnRadioService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case LIST_MODULES: {
-            CHECK_INTERFACE(IRadioService, data, reply);
-            uint32_t numModulesReq = data.readInt32();
-            if (numModulesReq > MAX_ITEMS_PER_LIST) {
-                numModulesReq = MAX_ITEMS_PER_LIST;
-            }
-            uint32_t numModules = numModulesReq;
-            struct radio_properties *properties =
-                    (struct radio_properties *)calloc(numModulesReq,
-                                                      sizeof(struct radio_properties));
-            if (properties == NULL) {
-                reply->writeInt32(NO_MEMORY);
-                reply->writeInt32(0);
-                return NO_ERROR;
-            }
-
-            status_t status = listModules(properties, &numModules);
-            reply->writeInt32(status);
-            reply->writeInt32(numModules);
-            ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
-
-            if (status == NO_ERROR) {
-                if (numModulesReq > numModules) {
-                    numModulesReq = numModules;
-                }
-                reply->write(properties,
-                             numModulesReq * sizeof(struct radio_properties));
-            }
-            free(properties);
-            return NO_ERROR;
-        } break;
-
-        case ATTACH: {
-            CHECK_INTERFACE(IRadioService, data, reply);
-            radio_handle_t handle = data.readInt32();
-            sp<IRadioClient> client =
-                    interface_cast<IRadioClient>(data.readStrongBinder());
-            struct radio_band_config config;
-            struct radio_band_config *configPtr = NULL;
-            if (data.readInt32() != 0) {
-                data.read(&config, sizeof(struct radio_band_config));
-                configPtr = &config;
-            }
-            bool withAudio = data.readInt32() != 0;
-            ALOGV("ATTACH configPtr %p withAudio %d", configPtr, withAudio);
-            sp<IRadio> radio;
-            status_t status = attach(handle, client, configPtr, withAudio, radio);
-            reply->writeInt32(status);
-            if (radio != 0) {
-                reply->writeInt32(1);
-                reply->writeStrongBinder(IInterface::asBinder(radio));
-            } else {
-                reply->writeInt32(0);
-            }
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/radio/OWNERS b/radio/OWNERS
deleted file mode 100644
index 4b38a35..0000000
--- a/radio/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elaurent@google.com
-twasilczyk@google.com
diff --git a/radio/Radio.cpp b/radio/Radio.cpp
deleted file mode 100644
index 9ddd221..0000000
--- a/radio/Radio.cpp
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
-**
-** Copyright (C) 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "Radio"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/IMemory.h>
-
-#include <radio/Radio.h>
-#include <radio/IRadio.h>
-#include <radio/IRadioService.h>
-#include <radio/IRadioClient.h>
-#include <radio/RadioCallback.h>
-
-namespace android {
-
-namespace {
-    sp<IRadioService>          gRadioService;
-    const int                  kRadioServicePollDelay = 500000; // 0.5s
-    const char*                kRadioServiceName      = "media.radio";
-    Mutex                      gLock;
-
-    class DeathNotifier : public IBinder::DeathRecipient
-    {
-    public:
-        DeathNotifier() {
-        }
-
-        virtual void binderDied(const wp<IBinder>& who __unused) {
-            ALOGV("binderDied");
-            Mutex::Autolock _l(gLock);
-            gRadioService.clear();
-            ALOGW("Radio service died!");
-        }
-    };
-
-    sp<DeathNotifier>         gDeathNotifier;
-}; // namespace anonymous
-
-const sp<IRadioService> Radio::getRadioService()
-{
-    Mutex::Autolock _l(gLock);
-    if (gRadioService.get() == 0) {
-        sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder;
-        do {
-            binder = sm->getService(String16(kRadioServiceName));
-            if (binder != 0) {
-                break;
-            }
-            ALOGW("RadioService not published, waiting...");
-            usleep(kRadioServicePollDelay);
-        } while(true);
-        if (gDeathNotifier == NULL) {
-            gDeathNotifier = new DeathNotifier();
-        }
-        binder->linkToDeath(gDeathNotifier);
-        gRadioService = interface_cast<IRadioService>(binder);
-    }
-    ALOGE_IF(gRadioService == 0, "no RadioService!?");
-    return gRadioService;
-}
-
-// Static methods
-status_t Radio::listModules(struct radio_properties *properties,
-                            uint32_t *numModules)
-{
-    ALOGV("listModules()");
-    const sp<IRadioService> service = getRadioService();
-    if (service == 0) {
-        return NO_INIT;
-    }
-    return service->listModules(properties, numModules);
-}
-
-sp<Radio> Radio::attach(radio_handle_t handle,
-                        const struct radio_band_config *config,
-                        bool withAudio,
-                        const sp<RadioCallback>& callback)
-{
-    ALOGV("attach()");
-    sp<Radio> radio;
-    const sp<IRadioService> service = getRadioService();
-    if (service == 0) {
-        return radio;
-    }
-    radio = new Radio(handle, callback);
-    status_t status = service->attach(handle, radio, config, withAudio, radio->mIRadio);
-
-    if (status == NO_ERROR && radio->mIRadio != 0) {
-        IInterface::asBinder(radio->mIRadio)->linkToDeath(radio);
-    } else {
-        ALOGW("Error %d connecting to radio service", status);
-        radio.clear();
-    }
-    return radio;
-}
-
-
-
-// Radio
-Radio::Radio(radio_handle_t /*handle*/, const sp<RadioCallback>& callback)
-    : mCallback(callback)
-{
-}
-
-Radio::~Radio()
-{
-    if (mIRadio != 0) {
-        mIRadio->detach();
-    }
-}
-
-
-void Radio::detach() {
-    ALOGV("detach()");
-    Mutex::Autolock _l(mLock);
-    mCallback.clear();
-    if (mIRadio != 0) {
-        mIRadio->detach();
-        IInterface::asBinder(mIRadio)->unlinkToDeath(this);
-        mIRadio = 0;
-    }
-}
-
-status_t Radio::setConfiguration(const struct radio_band_config *config)
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->setConfiguration(config);
-}
-
-status_t Radio::getConfiguration(struct radio_band_config *config)
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->getConfiguration(config);
-}
-
-status_t Radio::setMute(bool mute)
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->setMute(mute);
-}
-
-status_t Radio::getMute(bool *mute)
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->getMute(mute);
-}
-
-status_t Radio::scan(radio_direction_t direction, bool skipSubchannel)
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->scan(direction, skipSubchannel);
-}
-
-status_t Radio::step(radio_direction_t direction, bool skipSubchannel)
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->step(direction, skipSubchannel);
-}
-
-status_t Radio::tune(unsigned int channel, unsigned int subChannel)
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->tune(channel, subChannel);
-}
-
-status_t Radio::cancel()
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->cancel();
-}
-
-status_t Radio::getProgramInformation(struct radio_program_info *info)
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->getProgramInformation(info);
-}
-
-status_t Radio::hasControl(bool *hasControl)
-{
-    Mutex::Autolock _l(mLock);
-    if (mIRadio == 0) {
-        return NO_INIT;
-    }
-    return mIRadio->hasControl(hasControl);
-}
-
-
-// BpRadioClient
-void Radio::onEvent(const sp<IMemory>& eventMemory)
-{
-    Mutex::Autolock _l(mLock);
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        return;
-    }
-
-    // The event layout in shared memory is:
-    // sizeof(struct radio_event) bytes : the event itself
-    // 4 bytes                          : metadata size or 0
-    // N bytes                          : metadata if present
-    struct radio_event *event = (struct radio_event *)eventMemory->pointer();
-    uint32_t metadataOffset = sizeof(struct radio_event) + sizeof(uint32_t);
-    uint32_t metadataSize = *(uint32_t *)((uint8_t *)event + metadataOffset - sizeof(uint32_t));
-
-    // restore local metadata pointer from offset
-    switch (event->type) {
-    case RADIO_EVENT_TUNED:
-    case RADIO_EVENT_AF_SWITCH:
-        if (metadataSize != 0) {
-            event->info.metadata =
-                    (radio_metadata_t *)((uint8_t *)event + metadataOffset);
-        } else {
-            event->info.metadata = 0;
-        }
-        break;
-    case RADIO_EVENT_METADATA:
-        if (metadataSize != 0) {
-            event->metadata =
-                    (radio_metadata_t *)((uint8_t *)event + metadataOffset);
-        } else {
-            event->metadata = 0;
-        }
-        break;
-    default:
-        break;
-    }
-
-    if (mCallback != 0) {
-        mCallback->onEvent(event);
-    }
-}
-
-
-//IBinder::DeathRecipient
-void Radio::binderDied(const wp<IBinder>& who __unused) {
-    Mutex::Autolock _l(mLock);
-    ALOGW("Radio server binder Died ");
-    mIRadio = 0;
-    struct radio_event event;
-    memset(&event, 0, sizeof(struct radio_event));
-    event.type = RADIO_EVENT_SERVER_DIED;
-    event.status = DEAD_OBJECT;
-    if (mCallback != 0) {
-        mCallback->onEvent(&event);
-    }
-}
-
-}; // namespace android
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0df9a39..39f04fb 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -326,9 +326,14 @@
     sp<MmapThread> thread = mMmapThreads.valueFor(io);
     if (thread != 0) {
         interface = new MmapThreadHandle(thread);
-        thread->configure(attr, streamType, sessionId, callback, portId);
+        thread->configure(attr, streamType, sessionId, callback, *deviceId, portId);
         *handle = portId;
     } else {
+        if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
+            AudioSystem::releaseOutput(io, streamType, sessionId);
+        } else {
+            AudioSystem::releaseInput(io, sessionId);
+        }
         ret = NO_INIT;
     }
 
@@ -1397,11 +1402,11 @@
     // the config change is always sent from playback or record threads to avoid deadlock
     // with AudioSystem::gLock
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_OPENED, pid);
+        mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_REGISTERED, pid);
     }
 
     for (size_t i = 0; i < mRecordThreads.size(); i++) {
-        mRecordThreads.valueAt(i)->sendIoConfigEvent(AUDIO_INPUT_OPENED, pid);
+        mRecordThreads.valueAt(i)->sendIoConfigEvent(AUDIO_INPUT_REGISTERED, pid);
     }
 }
 
@@ -2603,7 +2608,7 @@
             while (ec->mEffects.size()) {
                 sp<EffectModule> effect = ec->mEffects[0];
                 effect->unPin();
-                t->removeEffect_l(effect);
+                t->removeEffect_l(effect, /*release*/ true);
                 if (effect->purgeHandles()) {
                     t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
                 }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9023b2d..63898a0 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -604,7 +604,7 @@
         virtual status_t standby();
 
     private:
-        sp<MmapThread> mThread;
+        const sp<MmapThread> mThread;
     };
 
               ThreadBase *checkThread_l(audio_io_handle_t ioHandle) const;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index f2c1c4f..bd5f146 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -25,6 +25,7 @@
 #include <system/audio_effects/effect_ns.h>
 #include <system/audio_effects/effect_visualizer.h>
 #include <audio_utils/primitives.h>
+#include <media/AudioEffect.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
 
@@ -109,7 +110,10 @@
 {
     ALOGV("Destructor %p", this);
     if (mEffectInterface != 0) {
-        ALOGW("EffectModule %p destructor called with unreleased interface", this);
+        char uuidStr[64];
+        AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
+        ALOGW("EffectModule %p destructor called with unreleased interface, effect %s",
+                this, uuidStr);
         release_l();
     }
 
@@ -1081,18 +1085,12 @@
     result.append(buffer);
 
     result.append("\t\tDescriptor:\n");
-    snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
-            mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
-            mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],
-                    mDescriptor.uuid.node[2],
-            mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
+    char uuidStr[64];
+    AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
+    snprintf(buffer, SIZE, "\t\t- UUID: %s\n", uuidStr);
     result.append(buffer);
-    snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
-                mDescriptor.type.timeLow, mDescriptor.type.timeMid,
-                    mDescriptor.type.timeHiAndVersion,
-                mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],
-                    mDescriptor.type.node[2],
-                mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
+    AudioEffect::guidToString(&mDescriptor.type, uuidStr, sizeof(uuidStr));
+    snprintf(buffer, SIZE, "\t\t- TYPE: %s\n", uuidStr);
     result.append(buffer);
     snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X (%s)\n",
             mDescriptor.apiVersion,
@@ -1306,11 +1304,10 @@
     if (thread != 0) {
         thread->disconnectEffectHandle(this, unpinIfLast);
     } else {
-        ALOGW("%s Effect handle %p disconnected after thread destruction", __FUNCTION__, this);
         // try to cleanup as much as we can
         sp<EffectModule> effect = mEffect.promote();
-        if (effect != 0) {
-            effect->disconnectHandle(this, unpinIfLast);
+        if (effect != 0 && effect->disconnectHandle(this, unpinIfLast) > 0) {
+            ALOGW("%s Effect handle %p disconnected after thread destruction", __FUNCTION__, this);
         }
     }
 
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index c4f1af3..c10fa05 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -138,7 +138,8 @@
 
 void FastMixer::onStateChange()
 {
-    LOG_HIST_FLUSH();
+    // log that audio was turned on/off
+    LOG_AUDIO_STATE();
     const FastMixerState * const current = (const FastMixerState *) mCurrent;
     const FastMixerState * const previous = (const FastMixerState *) mPrevious;
     FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index 2a27dfd..366a164 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -28,6 +28,7 @@
                             audio_channel_mask_t channelMask,
                             audio_session_t sessionId,
                             uid_t uid,
+                            pid_t pid,
                             audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
     virtual             ~MmapTrack();
 
@@ -39,7 +40,7 @@
     virtual bool        isFastTrack() const { return false; }
 
      static void        appendDumpHeader(String8& result);
-            void        dump(char* buffer, size_t size);
+            void        appendDump(String8& result, bool active);
 
 private:
     friend class MmapThread;
@@ -55,5 +56,6 @@
     virtual int64_t framesReleased() const;
     virtual void onTimestamp(const ExtendedTimestamp &timestamp);
 
+    pid_t mPid;
 };  // end of Track
 
diff --git a/services/audioflinger/OWNERS b/services/audioflinger/OWNERS
new file mode 100644
index 0000000..703e4d2
--- /dev/null
+++ b/services/audioflinger/OWNERS
@@ -0,0 +1,3 @@
+hunga@google.com
+jmtrivi@google.com
+mnaganov@google.com
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index d7c0728..27c6d35 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -474,6 +474,7 @@
                                              format,
                                              frameCount,
                                              NULL,
+                                             (size_t)0 /* bufferSize */,
                                              AUDIO_INPUT_FLAG_NONE);
     if (patch->mPatchRecord == 0) {
         return NO_MEMORY;
@@ -494,6 +495,7 @@
                                            format,
                                            frameCount,
                                            patch->mPatchRecord->buffer(),
+                                           patch->mPatchRecord->bufferSize(),
                                            AUDIO_OUTPUT_FLAG_NONE);
     if (patch->mPatchTrack == 0) {
         return NO_MEMORY;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 3f1a0c0..1c1a989 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -30,6 +30,7 @@
                                 audio_channel_mask_t channelMask,
                                 size_t frameCount,
                                 void *buffer,
+                                size_t bufferSize,
                                 const sp<IMemory>& sharedBuffer,
                                 audio_session_t sessionId,
                                 uid_t uid,
@@ -40,7 +41,7 @@
     virtual status_t    initCheck() const;
 
     static  void        appendDumpHeader(String8& result);
-            void        dump(char* buffer, size_t size, bool active);
+            void        appendDump(String8& result, bool active);
     virtual status_t    start(AudioSystem::sync_event_t event =
                                     AudioSystem::SYNC_EVENT_NONE,
                              audio_session_t triggerSession = AUDIO_SESSION_NONE);
@@ -240,6 +241,7 @@
                                    audio_format_t format,
                                    size_t frameCount,
                                    void *buffer,
+                                   size_t bufferSize,
                                    audio_output_flags_t flags);
     virtual             ~PatchTrack();
 
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 3f83ca8..f8da780 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -29,6 +29,7 @@
                                 audio_channel_mask_t channelMask,
                                 size_t frameCount,
                                 void *buffer,
+                                size_t bufferSize,
                                 audio_session_t sessionId,
                                 uid_t uid,
                                 audio_input_flags_t flags,
@@ -50,7 +51,7 @@
                                                 return tmp; }
 
     static  void        appendDumpHeader(String8& result);
-            void        dump(char* buffer, size_t size, bool active);
+            void        appendDump(String8& result, bool active);
 
             void        handleSyncStartEvent(const sp<SyncEvent>& event);
             void        clearSyncStartEvent();
@@ -102,6 +103,7 @@
                 audio_format_t format,
                 size_t frameCount,
                 void *buffer,
+                size_t bufferSize,
                 audio_input_flags_t flags);
     virtual             ~PatchRecord();
 
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index 3c73543..c1044ef 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -113,10 +113,15 @@
     return ok;
 }
 
-bool captureHotwordAllowed() {
-    static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD");
-    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
-    bool ok = PermissionCache::checkCallingPermission(sCaptureHotwordAllowed);
+bool captureHotwordAllowed(pid_t pid, uid_t uid) {
+    // CAPTURE_AUDIO_HOTWORD permission implies RECORD_AUDIO permission
+    bool ok = recordingAllowed(String16(""), pid, uid);
+
+    if (ok) {
+        static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD");
+        // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
+        ok = PermissionCache::checkCallingPermission(sCaptureHotwordAllowed);
+    }
     if (!ok) ALOGE("android.permission.CAPTURE_AUDIO_HOTWORD");
     return ok;
 }
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index 8b1bc00..04cb9cd 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -22,7 +22,7 @@
 bool isTrustedCallingUid(uid_t uid);
 bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
 bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
-bool captureHotwordAllowed();
+bool captureHotwordAllowed(pid_t pid, uid_t uid);
 bool settingsAllowed();
 bool modifyAudioRoutingAllowed();
 bool dumpAllowed();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 4b8e542..e202ca4 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1544,6 +1544,7 @@
         ALOGW("ActiveTracks<T>::add track %p already there", track.get());
         return index;
     }
+    logTrack("add", track);
     mActiveTracksGeneration++;
     mLatestActiveTrack = track;
     ++mBatteryCounter[track->uid()].second;
@@ -1557,6 +1558,7 @@
         ALOGW("ActiveTracks<T>::remove nonexistent track %p", track.get());
         return index;
     }
+    logTrack("remove", track);
     mActiveTracksGeneration++;
     --mBatteryCounter[track->uid()].second;
     // mLatestActiveTrack is not cleared even if is the same as track.
@@ -1567,6 +1569,7 @@
 void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() {
     for (const sp<T> &track : mActiveTracks) {
         BatteryNotifier::getInstance().noteStopAudio(track->uid());
+        logTrack("clear", track);
     }
     mLastActiveTracksGeneration = mActiveTracksGeneration;
     mActiveTracks.clear();
@@ -1605,6 +1608,16 @@
     }
 }
 
+template <typename T>
+void AudioFlinger::ThreadBase::ActiveTracks<T>::logTrack(
+        const char *funcName, const sp<T> &track) const {
+    if (mLocalLog != nullptr) {
+        String8 result;
+        track->appendDump(result, false /* active */);
+        mLocalLog->log("AT::%-10s(%p) %s", funcName, track.get(), result.string());
+    }
+}
+
 void AudioFlinger::ThreadBase::broadcast_l()
 {
     // Thread could be blocked waiting for async
@@ -1640,6 +1653,7 @@
         mSuspended(0), mBytesWritten(0),
         mFramesWritten(0),
         mSuspendedFrames(0),
+        mActiveTracks(&this->mLocalLog),
         // mStreamTypes[] initialized in constructor body
         mOutput(output),
         mLastWriteTime(-1), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
@@ -1654,7 +1668,8 @@
         mScreenState(AudioFlinger::mScreenState),
         // index 0 is reserved for normal mixer's submix
         mFastTrackAvailMask(((1 << FastMixerState::sMaxFastTracks) - 1) & ~1),
-        mHwSupportsPause(false), mHwPaused(false), mFlushPending(false)
+        mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
+        mLeftVolFloat(-1.0), mRightVolFloat(-1.0)
 {
     snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
     mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
@@ -1707,8 +1722,6 @@
 
 void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args __unused)
 {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
     String8 result;
 
     result.appendFormat("  Stream volumes in dB: ");
@@ -1735,8 +1748,10 @@
     size_t numactive = mActiveTracks.size();
     dprintf(fd, "  %zu Tracks", numtracks);
     size_t numactiveseen = 0;
+    const char *prefix = "    ";
     if (numtracks) {
         dprintf(fd, " of which %zu are active\n", numactive);
+        result.append(prefix);
         Track::appendDumpHeader(result);
         for (size_t i = 0; i < numtracks; ++i) {
             sp<Track> track = mTracks[i];
@@ -1745,8 +1760,8 @@
                 if (active) {
                     numactiveseen++;
                 }
-                track->dump(buffer, SIZE, active);
-                result.append(buffer);
+                result.append(prefix);
+                track->appendDump(result, active);
             }
         }
     } else {
@@ -1754,15 +1769,15 @@
     }
     if (numactiveseen != numactive) {
         // some tracks in the active list were not in the tracks list
-        snprintf(buffer, SIZE, "  The following tracks are in the active list but"
+        result.append("  The following tracks are in the active list but"
                 " not in the track list\n");
-        result.append(buffer);
+        result.append(prefix);
         Track::appendDumpHeader(result);
         for (size_t i = 0; i < numactive; ++i) {
             sp<Track> track = mActiveTracks[i];
             if (mTracks.indexOf(track) < 0) {
-                track->dump(buffer, SIZE, true);
-                result.append(buffer);
+                result.append(prefix);
+                track->appendDump(result, true /* active */);
             }
         }
     }
@@ -2013,7 +2028,8 @@
         }
 
         track = new Track(this, client, streamType, sampleRate, format,
-                          channelMask, frameCount, NULL, sharedBuffer,
+                          channelMask, frameCount,
+                          nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
                           sessionId, uid, *flags, TrackBase::TYPE_DEFAULT, portId);
 
         lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
@@ -2172,10 +2188,6 @@
             chain->incActiveTrackCnt();
         }
 
-        char buffer[256];
-        track->dump(buffer, arraysize(buffer), false /* active */);
-        mLocalLog.log("addTrack_l    (%p) %s", track.get(), buffer + 4); // log for analysis
-
         status = NO_ERROR;
     }
 
@@ -2202,9 +2214,9 @@
 {
     track->triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
 
-    char buffer[256];
-    track->dump(buffer, arraysize(buffer), false /* active */);
-    mLocalLog.log("removeTrack_l (%p) %s", track.get(), buffer + 4); // log for analysis
+    String8 result;
+    track->appendDump(result, false /* active */);
+    mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.string());
 
     mTracks.remove(track);
     deleteTrackName_l(track->name());
@@ -2242,6 +2254,7 @@
 
     switch (event) {
     case AUDIO_OUTPUT_OPENED:
+    case AUDIO_OUTPUT_REGISTERED:
     case AUDIO_OUTPUT_CONFIG_CHANGED:
         desc->mPatch = mPatch;
         desc->mChannelMask = mChannelMask;
@@ -3404,10 +3417,6 @@
             }
             if (track->isTerminated()) {
                 removeTrack_l(track);
-            } else { // inactive but not terminated
-                char buffer[256];
-                track->dump(buffer, arraysize(buffer), false /* active */);
-                mLocalLog.log("removeTracks_l(%p) %s", track.get(), buffer + 4);
             }
         }
     }
@@ -4287,6 +4296,7 @@
                     param = AudioMixer::RAMP_VOLUME;
                 }
                 mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
+                mLeftVolFloat = -1.0;
             // FIXME should not make a decision based on mServer
             } else if (cblk->mServer != 0) {
                 // If the track is stopped before the first frame was mixed,
@@ -4297,6 +4307,10 @@
             // compute volume for this track
             uint32_t vl, vr;       // in U8.24 integer format
             float vlf, vrf, vaf;   // in [0.0, 1.0] float format
+            // read original volumes with volume control
+            float typeVolume = mStreamTypes[track->streamType()].volume;
+            float v = masterVolume * typeVolume;
+
             if (track->isPausing() || mStreamTypes[track->streamType()].mute) {
                 vl = vr = 0;
                 vlf = vrf = vaf = 0.;
@@ -4304,10 +4318,6 @@
                     track->setPaused();
                 }
             } else {
-
-                // read original volumes with volume control
-                float typeVolume = mStreamTypes[track->streamType()].volume;
-                float v = masterVolume * typeVolume;
                 sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
                 gain_minifloat_packed_t vlr = proxy->getVolumeLR();
                 vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
@@ -4359,6 +4369,25 @@
                 track->mHasVolumeController = false;
             }
 
+            // For dedicated VoIP outputs, let the HAL apply the stream volume. Track volume is
+            // still applied by the mixer.
+            if ((mOutput->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) != 0) {
+                v = mStreamTypes[track->streamType()].mute ? 0.0f : v;
+                if (v != mLeftVolFloat) {
+                    status_t result = mOutput->stream->setVolume(v, v);
+                    ALOGE_IF(result != OK, "Error when setting output stream volume: %d", result);
+                    if (result == OK) {
+                        mLeftVolFloat = v;
+                    }
+                }
+                // if stream volume was successfully sent to the HAL, mLeftVolFloat == v here and we
+                // remove stream volume contribution from software volume.
+                if (v != 0.0f && mLeftVolFloat == v) {
+                   vlf = min(1.0f, vlf / v);
+                   vrf = min(1.0f, vrf / v);
+                   vaf = min(1.0f, vaf / v);
+               }
+            }
             // XXX: these things DON'T need to be done each time
             mAudioMixer->setBufferProvider(name, track);
             mAudioMixer->enable(name);
@@ -4800,7 +4829,6 @@
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
         AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady)
     :   PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady)
-        // mLeftVolFloat, mRightVolFloat
 {
 }
 
@@ -4808,7 +4836,6 @@
         AudioStreamOut* output, audio_io_handle_t id, uint32_t device,
         ThreadBase::type_t type, bool systemReady)
     :   PlaybackThread(audioFlinger, output, id, device, type, systemReady)
-        // mLeftVolFloat, mRightVolFloat
         , mVolumeShaperActive(false)
 {
 }
@@ -5925,7 +5952,9 @@
 #endif
                                          ) :
     ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady),
-    mInput(input), mRsmpInBuffer(NULL),
+    mInput(input),
+    mActiveTracks(&this->mLocalLog),
+    mRsmpInBuffer(NULL),
     // mRsmpInFrames, mRsmpInFramesP2, and mRsmpInFramesOA are set by readInputParameters_l()
     mRsmpInRear(0)
 #ifdef TEE_SINK
@@ -6696,7 +6725,8 @@
         Mutex::Autolock _l(mLock);
 
         track = new RecordTrack(this, client, sampleRate,
-                      format, channelMask, frameCount, NULL, sessionId, uid,
+                      format, channelMask, frameCount,
+                      nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, uid,
                       *flags, TrackBase::TYPE_DEFAULT, portId);
 
         lStatus = track->initCheck();
@@ -6888,6 +6918,10 @@
 
 void AudioFlinger::RecordThread::removeTrack_l(const sp<RecordTrack>& track)
 {
+    String8 result;
+    track->appendDump(result, false /* active */);
+    mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.string());
+
     mTracks.remove(track);
     // need anything related to effects here?
     if (track->isFastTrack()) {
@@ -6901,6 +6935,8 @@
     dumpInternals(fd, args);
     dumpTracks(fd, args);
     dumpEffectChains(fd, args);
+    dprintf(fd, "  Local log:\n");
+    mLocalLog.dump(fd, "   " /* prefix */, 40 /* lines */);
 }
 
 void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& args)
@@ -6914,6 +6950,12 @@
     if (mActiveTracks.size() == 0) {
         dprintf(fd, "  No active record clients\n");
     }
+
+    if (input != nullptr) {
+        dprintf(fd, "  Hal stream dump:\n");
+        (void)input->stream->dump(fd);
+    }
+
     dprintf(fd, "  Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no");
     dprintf(fd, "  Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
 
@@ -6928,16 +6970,15 @@
 
 void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args __unused)
 {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
     String8 result;
-
     size_t numtracks = mTracks.size();
     size_t numactive = mActiveTracks.size();
     size_t numactiveseen = 0;
     dprintf(fd, "  %zu Tracks", numtracks);
+    const char *prefix = "    ";
     if (numtracks) {
         dprintf(fd, " of which %zu are active\n", numactive);
+        result.append(prefix);
         RecordTrack::appendDumpHeader(result);
         for (size_t i = 0; i < numtracks ; ++i) {
             sp<RecordTrack> track = mTracks[i];
@@ -6946,8 +6987,8 @@
                 if (active) {
                     numactiveseen++;
                 }
-                track->dump(buffer, SIZE, active);
-                result.append(buffer);
+                result.append(prefix);
+                track->appendDump(result, active);
             }
         }
     } else {
@@ -6955,15 +6996,15 @@
     }
 
     if (numactiveseen != numactive) {
-        snprintf(buffer, SIZE, "  The following tracks are in the active list but"
+        result.append("  The following tracks are in the active list but"
                 " not in the track list\n");
-        result.append(buffer);
+        result.append(prefix);
         RecordTrack::appendDumpHeader(result);
         for (size_t i = 0; i < numactive; ++i) {
             sp<RecordTrack> track = mActiveTracks[i];
             if (mTracks.indexOf(track) < 0) {
-                track->dump(buffer, SIZE, true);
-                result.append(buffer);
+                result.append(prefix);
+                track->appendDump(result, true /* active */);
             }
         }
 
@@ -7221,6 +7262,7 @@
 
     switch (event) {
     case AUDIO_INPUT_OPENED:
+    case AUDIO_INPUT_REGISTERED:
     case AUDIO_INPUT_CONFIG_CHANGED:
         desc->mPatch = mPatch;
         desc->mChannelMask = mChannelMask;
@@ -7482,34 +7524,22 @@
 AudioFlinger::MmapThreadHandle::MmapThreadHandle(const sp<MmapThread>& thread)
     : mThread(thread)
 {
+    assert(thread != 0); // thread must start non-null and stay non-null
 }
 
 AudioFlinger::MmapThreadHandle::~MmapThreadHandle()
 {
-    MmapThread *thread = mThread.get();
-    // clear our strong reference before disconnecting the thread: the last strong reference
-    // will be removed when closeInput/closeOutput is executed upon call from audio policy manager
-    // and the thread removed from mMMapThreads list causing the thread destruction.
-    mThread.clear();
-    if (thread != nullptr) {
-        thread->disconnect();
-    }
+    mThread->disconnect();
 }
 
 status_t AudioFlinger::MmapThreadHandle::createMmapBuffer(int32_t minSizeFrames,
                                   struct audio_mmap_buffer_info *info)
 {
-    if (mThread == 0) {
-        return NO_INIT;
-    }
     return mThread->createMmapBuffer(minSizeFrames, info);
 }
 
 status_t AudioFlinger::MmapThreadHandle::getMmapPosition(struct audio_mmap_position *position)
 {
-    if (mThread == 0) {
-        return NO_INIT;
-    }
     return mThread->getMmapPosition(position);
 }
 
@@ -7517,25 +7547,16 @@
         audio_port_handle_t *handle)
 
 {
-    if (mThread == 0) {
-        return NO_INIT;
-    }
     return mThread->start(client, handle);
 }
 
 status_t AudioFlinger::MmapThreadHandle::stop(audio_port_handle_t handle)
 {
-    if (mThread == 0) {
-        return NO_INIT;
-    }
     return mThread->stop(handle);
 }
 
 status_t AudioFlinger::MmapThreadHandle::standby()
 {
-    if (mThread == 0) {
-        return NO_INIT;
-    }
     return mThread->standby();
 }
 
@@ -7545,7 +7566,10 @@
         AudioHwDevice *hwDev, sp<StreamHalInterface> stream,
         audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
     : ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
-      mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev)
+      mSessionId(AUDIO_SESSION_NONE),
+      mDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE),
+      mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
+      mActiveTracks(&this->mLocalLog)
 {
     mStandby = true;
     readHalParameters_l();
@@ -7566,7 +7590,7 @@
     for (const sp<MmapTrack> &t : mActiveTracks) {
         stop(t->portId());
     }
-    // this will cause the destruction of this thread.
+    // This will decrement references and may cause the destruction of this thread.
     if (isOutput()) {
         AudioSystem::releaseOutput(mId, streamType(), mSessionId);
     } else {
@@ -7579,11 +7603,13 @@
                                                 audio_stream_type_t streamType __unused,
                                                 audio_session_t sessionId,
                                                 const sp<MmapStreamCallback>& callback,
+                                                audio_port_handle_t deviceId,
                                                 audio_port_handle_t portId)
 {
     mAttr = *attr;
     mSessionId = sessionId;
     mCallback = callback;
+    mDeviceId = deviceId;
     mPortId = portId;
 }
 
@@ -7628,6 +7654,10 @@
         return NO_ERROR;
     }
 
+    if (!isOutput() && !recordingAllowed(client.packageName, client.clientPid, client.clientUid)) {
+        return PERMISSION_DENIED;
+    }
+
     audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
 
     audio_io_handle_t io = mId;
@@ -7639,7 +7669,7 @@
         audio_stream_type_t stream = streamType();
         audio_output_flags_t flags =
                 (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
-        audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
+        audio_port_handle_t deviceId = mDeviceId;
         ret = AudioSystem::getOutputForAttr(&mAttr, &io,
                                             mSessionId,
                                             &stream,
@@ -7653,7 +7683,7 @@
         config.sample_rate = mSampleRate;
         config.channel_mask = mChannelMask;
         config.format = mFormat;
-        audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
+        audio_port_handle_t deviceId = mDeviceId;
         ret = AudioSystem::getInputForAttr(&mAttr, &io,
                                               mSessionId,
                                               client.clientPid,
@@ -7693,7 +7723,7 @@
     }
 
     sp<MmapTrack> track = new MmapTrack(this, mSampleRate, mFormat, mChannelMask, mSessionId,
-                                        client.clientUid, portId);
+                                        client.clientUid, client.clientPid, portId);
 
     mActiveTracks.add(track);
     sp<EffectChain> chain = getEffectChain_l(mSessionId);
@@ -7904,8 +7934,10 @@
 
     switch (event) {
     case AUDIO_INPUT_OPENED:
+    case AUDIO_INPUT_REGISTERED:
     case AUDIO_INPUT_CONFIG_CHANGED:
     case AUDIO_OUTPUT_OPENED:
+    case AUDIO_OUTPUT_REGISTERED:
     case AUDIO_OUTPUT_CONFIG_CHANGED:
         desc->mPatch = mPatch;
         desc->mChannelMask = mChannelMask;
@@ -7990,17 +8022,19 @@
         mPrevOutDevice = type;
         sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
         sp<MmapStreamCallback> callback = mCallback.promote();
-        if (callback != 0) {
+        if (mDeviceId != deviceId && callback != 0) {
             callback->onRoutingChanged(deviceId);
         }
+        mDeviceId = deviceId;
     }
     if (!isOutput() && mPrevInDevice != mInDevice) {
         mPrevInDevice = type;
         sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
         sp<MmapStreamCallback> callback = mCallback.promote();
-        if (callback != 0) {
+        if (mDeviceId != deviceId && callback != 0) {
             callback->onRoutingChanged(deviceId);
         }
+        mDeviceId = deviceId;
     }
     return status;
 }
@@ -8114,10 +8148,8 @@
 
 void AudioFlinger::MmapThread::threadLoop_exit()
 {
-    sp<MmapStreamCallback> callback = mCallback.promote();
-    if (callback != 0) {
-        callback->onTearDown();
-    }
+    // Do not call callback->onTearDown() because it is redundant for thread exit
+    // and because it can cause a recursive mutex lock on stop().
 }
 
 status_t AudioFlinger::MmapThread::setSyncEvent(const sp<SyncEvent>& event __unused)
@@ -8178,6 +8210,8 @@
     dumpInternals(fd, args);
     dumpTracks(fd, args);
     dumpEffectChains(fd, args);
+    dprintf(fd, "  Local log:\n");
+    mLocalLog.dump(fd, "   " /* prefix */, 40 /* lines */);
 }
 
 void AudioFlinger::MmapThread::dumpInternals(int fd, const Vector<String16>& args)
@@ -8194,18 +8228,17 @@
 
 void AudioFlinger::MmapThread::dumpTracks(int fd, const Vector<String16>& args __unused)
 {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
     String8 result;
-
     size_t numtracks = mActiveTracks.size();
-    dprintf(fd, "  %zu Tracks", numtracks);
+    dprintf(fd, "  %zu Tracks\n", numtracks);
+    const char *prefix = "    ";
     if (numtracks) {
+        result.append(prefix);
         MmapTrack::appendDumpHeader(result);
         for (size_t i = 0; i < numtracks ; ++i) {
             sp<MmapTrack> track = mActiveTracks[i];
-            track->dump(buffer, SIZE);
-            result.append(buffer);
+            result.append(prefix);
+            track->appendDump(result, true /* active */);
         }
     } else {
         dprintf(fd, "\n");
@@ -8240,9 +8273,10 @@
                                                 audio_stream_type_t streamType,
                                                 audio_session_t sessionId,
                                                 const sp<MmapStreamCallback>& callback,
+                                                audio_port_handle_t deviceId,
                                                 audio_port_handle_t portId)
 {
-    MmapThread::configure(attr, streamType, sessionId, callback, portId);
+    MmapThread::configure(attr, streamType, sessionId, callback, deviceId, portId);
     mStreamType = streamType;
 }
 
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 062bad6..dd2b89b 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -508,9 +508,10 @@
                 template <typename T>
                 class ActiveTracks {
                 public:
-                    ActiveTracks()
+                    explicit ActiveTracks(SimpleLog *localLog = nullptr)
                         : mActiveTracksGeneration(0)
                         , mLastActiveTracksGeneration(0)
+                        , mLocalLog(localLog)
                     { }
 
                     ~ActiveTracks() {
@@ -562,6 +563,8 @@
                     void            updatePowerState(sp<ThreadBase> thread, bool force = false);
 
                 private:
+                    void            logTrack(const char *funcName, const sp<T> &track) const;
+
                     SortedVector<uid_t> getWakeLockUids() {
                         SortedVector<uid_t> wakeLockUids;
                         for (const sp<T> &track : mActiveTracks) {
@@ -576,6 +579,7 @@
                     int                 mActiveTracksGeneration;
                     int                 mLastActiveTracksGeneration;
                     wp<T>               mLatestActiveTrack; // latest track added to ActiveTracks
+                    SimpleLog * const   mLocalLog;
                 };
 
                 SimpleLog mLocalLog;
@@ -995,6 +999,9 @@
                 bool        mHwSupportsPause;
                 bool        mHwPaused;
                 bool        mFlushPending;
+                // volumes last sent to audio HAL with stream->setVolume()
+                float mLeftVolFloat;
+                float mRightVolFloat;
 };
 
 class MixerThread : public PlaybackThread {
@@ -1112,9 +1119,6 @@
 
     virtual     void        onAddNewTrack_l();
 
-    // volumes last sent to audio HAL with stream->set_volume()
-    float mLeftVolFloat;
-    float mRightVolFloat;
     bool mVolumeShaperActive;
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
@@ -1475,6 +1479,7 @@
                                       audio_stream_type_t streamType,
                                       audio_session_t sessionId,
                                       const sp<MmapStreamCallback>& callback,
+                                      audio_port_handle_t deviceId,
                                       audio_port_handle_t portId);
 
                 void        disconnect();
@@ -1536,6 +1541,7 @@
 
                 audio_attributes_t      mAttr;
                 audio_session_t         mSessionId;
+                audio_port_handle_t     mDeviceId;
                 audio_port_handle_t     mPortId;
 
                 wp<MmapStreamCallback>  mCallback;
@@ -1558,6 +1564,7 @@
                                       audio_stream_type_t streamType,
                                       audio_session_t sessionId,
                                       const sp<MmapStreamCallback>& callback,
+                                      audio_port_handle_t deviceId,
                                       audio_port_handle_t portId);
 
                 AudioStreamOut* clearOutput();
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index cb540ca..d4ce0b4 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -61,6 +61,7 @@
                                 audio_channel_mask_t channelMask,
                                 size_t frameCount,
                                 void *buffer,
+                                size_t bufferSize,
                                 audio_session_t sessionId,
                                 uid_t uid,
                                 bool isOut,
@@ -82,6 +83,7 @@
 
             sp<IMemory> getBuffers() const { return mBufferMemory; }
             void*       buffer() const { return mBuffer; }
+            size_t      bufferSize() const { return mBufferSize; }
     virtual bool        isFastTrack() const = 0;
             bool        isOutputTrack() const { return (mType == TYPE_OUTPUT); }
             bool        isPatchTrack() const { return (mType == TYPE_PATCH); }
@@ -133,6 +135,40 @@
         mTerminated = true;
     }
 
+    // Upper case characters are final states.
+    // Lower case characters are transitory.
+    const char *getTrackStateString() const {
+        if (isTerminated()) {
+            return "T ";
+        }
+        switch (mState) {
+        case IDLE:
+            return "I ";
+        case STOPPING_1: // for Fast and Offload
+            return "s1";
+        case STOPPING_2: // for Fast and Offload
+            return "s2";
+        case STOPPED:
+            return "S ";
+        case RESUMING:
+            return "r ";
+        case ACTIVE:
+            return "A ";
+        case PAUSING:
+            return "p ";
+        case PAUSED:
+            return "P ";
+        case FLUSHED:
+            return "F ";
+        case STARTING_1: // for RecordTrack
+            return "r1";
+        case STARTING_2: // for RecordTrack
+            return "r2";
+        default:
+            return "? ";
+        }
+    }
+
     bool isOut() const { return mIsOut; }
                                     // true for Track, false for RecordTrack,
                                     // this could be a track type if needed later
@@ -144,6 +180,7 @@
     sp<IMemory>         mBufferMemory;  // currently non-0 for fast RecordTrack only
     void*               mBuffer;    // start of track buffer, typically in shared memory
                                     // except for OutputTrack when it is in local memory
+    size_t              mBufferSize; // size of mBuffer in bytes
     // we don't really need a lock for these
     track_state         mState;
     const uint32_t      mSampleRate;    // initial sample rate only; for tracks which
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 9763bf2..0f25153 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -50,10 +50,6 @@
 #define ALOGVV(a...) do { } while(0)
 #endif
 
-// TODO move to a common header  (Also shared with AudioTrack.cpp)
-#define NANOS_PER_SECOND    1000000000
-#define TIME_TO_NANOS(time) ((uint64_t)(time).tv_sec * NANOS_PER_SECOND + (time).tv_nsec)
-
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -71,6 +67,7 @@
             audio_channel_mask_t channelMask,
             size_t frameCount,
             void *buffer,
+            size_t bufferSize,
             audio_session_t sessionId,
             uid_t clientUid,
             bool isOut,
@@ -81,7 +78,7 @@
         mThread(thread),
         mClient(client),
         mCblk(NULL),
-        // mBuffer
+        // mBuffer, mBufferSize
         mState(IDLE),
         mSampleRate(sampleRate),
         mFormat(format),
@@ -113,15 +110,22 @@
 
     // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
 
-    size_t bufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
+    size_t minBufferSize = buffer == NULL ? roundup(frameCount) : frameCount;
     // check overflow when computing bufferSize due to multiplication by mFrameSize.
-    if (bufferSize < frameCount  // roundup rounds down for values above UINT_MAX / 2
+    if (minBufferSize < frameCount  // roundup rounds down for values above UINT_MAX / 2
             || mFrameSize == 0   // format needs to be correct
-            || bufferSize > SIZE_MAX / mFrameSize) {
+            || minBufferSize > SIZE_MAX / mFrameSize) {
         android_errorWriteLog(0x534e4554, "34749571");
         return;
     }
-    bufferSize *= mFrameSize;
+    minBufferSize *= mFrameSize;
+
+    if (buffer == nullptr) {
+        bufferSize = minBufferSize; // allocated here.
+    } else if (minBufferSize > bufferSize) {
+        android_errorWriteLog(0x534e4554, "38340117");
+        return;
+    }
 
     size_t size = sizeof(audio_track_cblk_t);
     if (buffer == NULL && alloc == ALLOC_CBLK) {
@@ -177,6 +181,7 @@
             // It should references the buffer via the pipe.
             // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
             mBuffer = NULL;
+            bufferSize = 0;
             break;
         case ALLOC_CBLK:
             // clear all buffers
@@ -196,7 +201,10 @@
         case ALLOC_NONE:
             mBuffer = buffer;
             break;
+        default:
+            LOG_ALWAYS_FATAL("invalid allocation type: %d", (int)alloc);
         }
+        mBufferSize = bufferSize;
 
 #ifdef TEE_SINK
         if (mTeeSinkTrackEnabled) {
@@ -368,6 +376,7 @@
             audio_channel_mask_t channelMask,
             size_t frameCount,
             void *buffer,
+            size_t bufferSize,
             const sp<IMemory>& sharedBuffer,
             audio_session_t sessionId,
             uid_t uid,
@@ -376,6 +385,7 @@
             audio_port_handle_t portId)
     :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount,
                   (sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
+                  (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
                   sessionId, uid, true /*isOut*/,
                   (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
                   type, portId),
@@ -411,21 +421,6 @@
         mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
                 mFrameSize, !isExternalTrack(), sampleRate);
     } else {
-        // Is the shared buffer of sufficient size?
-        // (frameCount * mFrameSize) is <= SIZE_MAX, checked in TrackBase.
-        if (sharedBuffer->size() < frameCount * mFrameSize) {
-            // Workaround: clear out mCblk to indicate track hasn't been properly created.
-            mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
-            if (mClient == 0) {
-                free(mCblk);
-            }
-            mCblk = NULL;
-
-            mSharedBuffer.clear(); // release shared buffer early
-            android_errorWriteLog(0x534e4554, "38340117");
-            return;
-        }
-
         mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
                 mFrameSize);
     }
@@ -503,58 +498,40 @@
 
 /*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
 {
-    result.append("    Name Active Client Type      Fmt Chn mask Session fCount S F SRate  "
-                  "L dB  R dB  VS dB    Server Main buf  Aux buf Flags UndFrmCnt  Flushed\n");
+    result.append("T Name Active Client Session S  Flags "
+                  "  Format Chn mask  SRate "
+                  "ST  L dB  R dB  VS dB "
+                  "  Server FrmCnt  FrmRdy F Underruns  Flushed "
+                  "Main Buf  Aux Buf\n");
 }
 
-void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool active)
+void AudioFlinger::PlaybackThread::Track::appendDump(String8& result, bool active)
 {
-    gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
-    if (isFastTrack()) {
-        sprintf(buffer, "    F %2d", mFastIndex);
-    } else if (mName >= AudioMixer::TRACK0) {
-        sprintf(buffer, "    %4d", mName - AudioMixer::TRACK0);
-    } else {
-        sprintf(buffer, "    none");
-    }
-    track_state state = mState;
-    char stateChar;
-    if (isTerminated()) {
-        stateChar = 'T';
-    } else {
-        switch (state) {
-        case IDLE:
-            stateChar = 'I';
-            break;
-        case STOPPING_1:
-            stateChar = 's';
-            break;
-        case STOPPING_2:
-            stateChar = '5';
-            break;
-        case STOPPED:
-            stateChar = 'S';
-            break;
-        case RESUMING:
-            stateChar = 'R';
-            break;
-        case ACTIVE:
-            stateChar = 'A';
-            break;
-        case PAUSING:
-            stateChar = 'p';
-            break;
-        case PAUSED:
-            stateChar = 'P';
-            break;
-        case FLUSHED:
-            stateChar = 'F';
-            break;
-        default:
-            stateChar = '?';
-            break;
+    char trackType;
+    switch (mType) {
+    case TYPE_DEFAULT:
+    case TYPE_OUTPUT:
+        if (mSharedBuffer.get() != nullptr) {
+            trackType = 'S'; // static
+        } else {
+            trackType = ' '; // normal
         }
+        break;
+    case TYPE_PATCH:
+        trackType = 'P';
+        break;
+    default:
+        trackType = '?';
     }
+
+    if (isFastTrack()) {
+        result.appendFormat("F%c %3d", trackType, mFastIndex);
+    } else if (mName >= AudioMixer::TRACK0) {
+        result.appendFormat("%c %4d", trackType, mName - AudioMixer::TRACK0);
+    } else {
+        result.appendFormat("%c none", trackType);
+    }
+
     char nowInUnderrun;
     switch (mObservedUnderruns.mBitFields.mMostRecent) {
     case UNDERRUN_FULL:
@@ -571,31 +548,75 @@
         break;
     }
 
-    std::pair<float /* volume */, bool /* active */> vsVolume = mVolumeHandler->getLastVolume();
-    snprintf(&buffer[8], size - 8, " %6s %6u %4u %08X %08X %7u %6zu %1c %1d %5u "
-                                   "%5.2g %5.2g %5.2g%c  "
-                                   "%08X %08zX %08zX 0x%03X %9u%c %7u\n",
+    char fillingStatus;
+    switch (mFillingUpStatus) {
+    case FS_INVALID:
+        fillingStatus = 'I';
+        break;
+    case FS_FILLING:
+        fillingStatus = 'f';
+        break;
+    case FS_FILLED:
+        fillingStatus = 'F';
+        break;
+    case FS_ACTIVE:
+        fillingStatus = 'A';
+        break;
+    default:
+        fillingStatus = '?';
+        break;
+    }
+
+    // clip framesReadySafe to max representation in dump
+    const size_t framesReadySafe =
+            std::min(mAudioTrackServerProxy->framesReadySafe(), (size_t)99999999);
+
+    // obtain volumes
+    const gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR();
+    const std::pair<float /* volume */, bool /* active */> vsVolume =
+            mVolumeHandler->getLastVolume();
+
+    // Our effective frame count is obtained by ServerProxy::getBufferSizeInFrames()
+    // as it may be reduced by the application.
+    const size_t bufferSizeInFrames = (size_t)mAudioTrackServerProxy->getBufferSizeInFrames();
+    // Check whether the buffer size has been modified by the app.
+    const char modifiedBufferChar = bufferSizeInFrames < mFrameCount
+            ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
+                    ? 'e' /* error */ : ' ' /* identical */;
+
+    result.appendFormat("%7s %6u %7u %2s 0x%03X "
+                           "%08X %08X %6u "
+                           "%2u %5.2g %5.2g %5.2g%c "
+                           "%08X %6zu%c %6zu %c %9u%c %7u "
+                           "%08zX %08zX\n",
             active ? "yes" : "no",
             (mClient == 0) ? getpid_cached : mClient->pid(),
-            mStreamType,
+            mSessionId,
+            getTrackStateString(),
+            mCblk->mFlags,
+
             mFormat,
             mChannelMask,
-            mSessionId,
-            mFrameCount,
-            stateChar,
-            mFillingUpStatus,
             mAudioTrackServerProxy->getSampleRate(),
+
+            mStreamType,
             20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))),
             20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
             20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
             vsVolume.second ? 'A' : ' ',  // if any VolumeShapers active
+
             mCblk->mServer,
-            (size_t)mMainBuffer, // use %zX as %p appends 0x
-            (size_t)mAuxBuffer,  // use %zX as %p appends 0x
-            mCblk->mFlags,
+            bufferSizeInFrames,
+            modifiedBufferChar,
+            framesReadySafe,
+            fillingStatus,
             mAudioTrackServerProxy->getUnderrunFrames(),
             nowInUnderrun,
-            (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000); // 7 digits
+            (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
+
+            (size_t)mMainBuffer, // use %zX as %p appends 0x
+            (size_t)mAuxBuffer   // use %zX as %p appends 0x
+            );
 }
 
 uint32_t AudioFlinger::PlaybackThread::Track::sampleRate() const {
@@ -1235,7 +1256,8 @@
             uid_t uid)
     :   Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
               sampleRate, format, channelMask, frameCount,
-              NULL, 0, AUDIO_SESSION_NONE, uid, AUDIO_OUTPUT_FLAG_NONE,
+              nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
+              AUDIO_SESSION_NONE, uid, AUDIO_OUTPUT_FLAG_NONE,
               TYPE_OUTPUT),
     mActive(false), mSourceThread(sourceThread)
 {
@@ -1351,7 +1373,9 @@
             if (mBufferQueue.size()) {
                 mBufferQueue.removeAt(0);
                 free(pInBuffer->mBuffer);
-                delete pInBuffer;
+                if (pInBuffer != &inBuffer) {
+                    delete pInBuffer;
+                }
                 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %zu", this,
                         mThread.unsafe_get(), mBufferQueue.size());
             } else {
@@ -1430,10 +1454,12 @@
                                                      audio_format_t format,
                                                      size_t frameCount,
                                                      void *buffer,
+                                                     size_t bufferSize,
                                                      audio_output_flags_t flags)
     :   Track(playbackThread, NULL, streamType,
               sampleRate, format, channelMask, frameCount,
-              buffer, 0, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
+              buffer, bufferSize, nullptr /* sharedBuffer */,
+              AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
               mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true))
 {
     uint64_t mixBufferNs = ((uint64_t)2 * playbackThread->frameCount() * 1000000000) /
@@ -1567,13 +1593,14 @@
             audio_channel_mask_t channelMask,
             size_t frameCount,
             void *buffer,
+            size_t bufferSize,
             audio_session_t sessionId,
             uid_t uid,
             audio_input_flags_t flags,
             track_type type,
             audio_port_handle_t portId)
     :   TrackBase(thread, client, sampleRate, format,
-                  channelMask, frameCount, buffer, sessionId, uid, false /*isOut*/,
+                  channelMask, frameCount, buffer, bufferSize, sessionId, uid, false /*isOut*/,
                   (type == TYPE_DEFAULT) ?
                           ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
                           ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
@@ -1701,22 +1728,28 @@
 
 /*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result)
 {
-    result.append("    Active Client Fmt Chn mask Session S   Server fCount SRate\n");
+    result.append("Active Client Session S  Flags   Format Chn mask  SRate   Server FrmCnt\n");
 }
 
-void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size, bool active)
+void AudioFlinger::RecordThread::RecordTrack::appendDump(String8& result, bool active)
 {
-    snprintf(buffer, size, "    %6s %6u %3u %08X %7u %1d %08X %6zu %5u\n",
+    result.appendFormat("%c%5s %6u %7u %2s 0x%03X "
+            "%08X %08X %6u "
+            "%08X %6zu\n",
+            isFastTrack() ? 'F' : ' ',
             active ? "yes" : "no",
             (mClient == 0) ? getpid_cached : mClient->pid(),
+            mSessionId,
+            getTrackStateString(),
+            mCblk->mFlags,
+
             mFormat,
             mChannelMask,
-            mSessionId,
-            mState,
-            mCblk->mServer,
-            mFrameCount,
-            mSampleRate);
+            mSampleRate,
 
+            mCblk->mServer,
+            mFrameCount
+            );
 }
 
 void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(const sp<SyncEvent>& event)
@@ -1767,9 +1800,10 @@
                                                      audio_format_t format,
                                                      size_t frameCount,
                                                      void *buffer,
+                                                     size_t bufferSize,
                                                      audio_input_flags_t flags)
     :   RecordTrack(recordThread, NULL, sampleRate, format, channelMask, frameCount,
-                buffer, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
+                buffer, bufferSize, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
                 mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true))
 {
     uint64_t mixBufferNs = ((uint64_t)2 * recordThread->frameCount() * 1000000000) /
@@ -1834,11 +1868,15 @@
         audio_channel_mask_t channelMask,
         audio_session_t sessionId,
         uid_t uid,
+        pid_t pid,
         audio_port_handle_t portId)
     :   TrackBase(thread, NULL, sampleRate, format,
-                  channelMask, 0, NULL, sessionId, uid, false,
+                  channelMask, (size_t)0 /* frameCount */,
+                  nullptr /* buffer */, (size_t)0 /* bufferSize */,
+                  sessionId, uid, false /* isOut */,
                   ALLOC_NONE,
-                  TYPE_DEFAULT, portId)
+                  TYPE_DEFAULT, portId),
+        mPid(pid)
 {
 }
 
@@ -1885,17 +1923,17 @@
 
 /*static*/ void AudioFlinger::MmapThread::MmapTrack::appendDumpHeader(String8& result)
 {
-    result.append("    Client Fmt Chn mask  SRate\n");
+    result.append("Client Session   Format Chn mask  SRate\n");
 }
 
-void AudioFlinger::MmapThread::MmapTrack::dump(char* buffer, size_t size)
+void AudioFlinger::MmapThread::MmapTrack::appendDump(String8& result, bool active __unused)
 {
-    snprintf(buffer, size, "            %6u %3u    %08X %5u\n",
-            mUid,
+    result.appendFormat("%6u %7u %08X %08X %6u\n",
+            mPid,
+            mSessionId,
             mFormat,
             mChannelMask,
             mSampleRate);
-
 }
 
 } // namespace android
diff --git a/services/audioflinger/TypedLogger.h b/services/audioflinger/TypedLogger.h
index 2d84028..909af09 100644
--- a/services/audioflinger/TypedLogger.h
+++ b/services/audioflinger/TypedLogger.h
@@ -88,11 +88,11 @@
 
 // Write histogram timestamp entry
 #define LOG_HIST_TS() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
-                                x->logHistTS(hash(__FILE__, __LINE__)); } while(0)
+        x->logEventHistTs(NBLog::EVENT_HISTOGRAM_ENTRY_TS, hash(__FILE__, __LINE__)); } while(0)
 
-// flush all histogram
-#define LOG_HIST_FLUSH() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
-                                x->logHistFlush(hash(__FILE__, __LINE__)); } while(0)
+// Record that audio was turned on/off
+#define LOG_AUDIO_STATE() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+        x->logEventHistTs(NBLog::EVENT_AUDIO_STATE, hash(__FILE__, __LINE__)); } while(0)
 
 namespace android {
 extern "C" {
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index ad340e5..65571f9 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -24,7 +24,8 @@
     libhardware_legacy \
     libserviceutility \
     libaudiopolicymanager \
-    libmedia_helper
+    libmedia_helper \
+    libeffectsconfig
 
 LOCAL_STATIC_LIBRARIES := \
     libaudiopolicycomponents
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index c868206..7b19f58 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -349,8 +349,8 @@
 
     virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
 
-    virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
-                    audio_source_t source,
+    virtual void onRecordingConfigurationUpdate(int event,
+                    const record_client_info_t *clientInfo,
                     const struct audio_config_base *clientConfig,
                     const struct audio_config_base *deviceConfig,
                     audio_patch_handle_t patchHandle) = 0;
diff --git a/services/audiopolicy/OWNERS b/services/audiopolicy/OWNERS
new file mode 100644
index 0000000..a8483fa
--- /dev/null
+++ b/services/audiopolicy/OWNERS
@@ -0,0 +1,3 @@
+jmtrivi@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
index ca070cf..cedf22d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
@@ -22,6 +22,7 @@
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <media/AudioPolicy.h>
+#include <media/IAudioPolicyServiceClient.h>
 #include "AudioSessionInfoProvider.h"
 
 namespace android {
@@ -44,14 +45,14 @@
 
     status_t dump(int fd, int spaces, int index) const;
 
-    audio_session_t session() const { return mSession; }
-    audio_source_t inputSource()const { return mInputSource; }
+    audio_session_t session() const { return mRecordClientInfo.session; }
+    audio_source_t inputSource()const { return mRecordClientInfo.source; }
     audio_format_t format() const { return mConfig.format; }
     uint32_t sampleRate() const { return mConfig.sample_rate; }
     audio_channel_mask_t channelMask() const { return mConfig.channel_mask; }
     audio_input_flags_t flags() const { return mFlags; }
-    uid_t uid() const { return mUid; }
-    void setUid(uid_t uid) { mUid = uid; }
+    uid_t uid() const { return mRecordClientInfo.uid; }
+    void setUid(uid_t uid) { mRecordClientInfo.uid = uid; }
     bool matches(const sp<AudioSession> &other) const;
     bool isSoundTrigger() const { return mIsSoundTrigger; }
     uint32_t openCount() const { return mOpenCount; } ;
@@ -65,11 +66,9 @@
     virtual void onSessionInfoUpdate() const;
 
 private:
-    const audio_session_t mSession;
-    const audio_source_t mInputSource;
+    record_client_info_t mRecordClientInfo;
     const struct audio_config_base mConfig;
     const audio_input_flags_t mFlags;
-    uid_t mUid;
     bool  mIsSoundTrigger;
     uint32_t  mOpenCount;
     uint32_t  mActiveCount;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
index bea9f4f..5b57d3d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
@@ -38,9 +38,9 @@
                            bool isSoundTrigger,
                            AudioMix* policyMix,
                            AudioPolicyClientInterface *clientInterface) :
-    mSession(session), mInputSource(inputSource),
+    mRecordClientInfo({ .uid = uid, .session = session, .source = inputSource}),
     mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
-    mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger),
+    mFlags(flags), mIsSoundTrigger(isSoundTrigger),
     mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface),
     mInfoProvider(NULL)
 {
@@ -92,7 +92,7 @@
         const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
                 AUDIO_PATCH_HANDLE_NONE;
         if (patchHandle != AUDIO_PATCH_HANDLE_NONE) {
-            mClientInterface->onRecordingConfigurationUpdate(event, mSession, mInputSource,
+            mClientInterface->onRecordingConfigurationUpdate(event, &mRecordClientInfo,
                     &mConfig, &deviceConfig, patchHandle);
         }
     }
@@ -102,13 +102,13 @@
 
 bool AudioSession::matches(const sp<AudioSession> &other) const
 {
-    if (other->session() == mSession &&
-        other->inputSource() == mInputSource &&
+    if (other->session() == mRecordClientInfo.session &&
+        other->inputSource() == mRecordClientInfo.source &&
         other->format() == mConfig.format &&
         other->sampleRate() == mConfig.sample_rate &&
         other->channelMask() == mConfig.channel_mask &&
         other->flags() == mFlags &&
-        other->uid() == mUid) {
+        other->uid() == mRecordClientInfo.uid) {
         return true;
     }
     return false;
@@ -130,8 +130,7 @@
                 AUDIO_PATCH_HANDLE_NONE;
         if (patchHandle != AUDIO_PATCH_HANDLE_NONE) {
             mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
-                    mSession, mInputSource,
-                    &mConfig, &deviceConfig, patchHandle);
+                    &mRecordClientInfo, &mConfig, &deviceConfig, patchHandle);
         }
     }
 }
@@ -144,11 +143,11 @@
 
     snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1);
     result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mSession);
+    snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mRecordClientInfo.session);
     result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
+    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mRecordClientInfo.uid);
     result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mInputSource);
+    snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mRecordClientInfo.source);
     result.append(buffer);
     snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mConfig.format);
     result.append(buffer);
diff --git a/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp b/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp
index 8ca3ae0..0383b0e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp
@@ -34,7 +34,7 @@
 {
     ssize_t index = indexOfKey(session);
     if (index < 0) {
-        ALOGW("acquireSoundTriggerSession() session %d not registered", session);
+        ALOGW("releaseSession() session %d not registered", session);
         return BAD_VALUE;
     }
 
diff --git a/services/audiopolicy/config/primary_audio_policy_configuration.xml b/services/audiopolicy/config/primary_audio_policy_configuration.xml
index bf508ac..5b7ae7f 100644
--- a/services/audiopolicy/config/primary_audio_policy_configuration.xml
+++ b/services/audiopolicy/config/primary_audio_policy_configuration.xml
@@ -13,7 +13,7 @@
         </mixPort>
         <mixPort name="primary input" role="sink">
             <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
-                     samplingRates="8000, 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                     samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
         </mixPort>
    </mixPorts>
    <devicePorts>
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 78f195d..bdfaf2f 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1320,9 +1320,9 @@
 
         // apply volume rules for current stream and device if necessary
         checkAndSetVolume(stream,
-                          mVolumeCurves->getVolumeIndex(stream, device),
+                          mVolumeCurves->getVolumeIndex(stream, outputDesc->device()),
                           outputDesc,
-                          device);
+                          outputDesc->device());
 
         // update the outputs if starting an output with a stream that can affect notification
         // routing
@@ -1499,62 +1499,13 @@
             "session %d, flags %#x",
           attr->source, config->sample_rate, config->format, config->channel_mask, session, flags);
 
-    // special case for mmap capture: if an input IO handle is specified, we reuse this input if
-    // possible
-    if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ &&
-            *input != AUDIO_IO_HANDLE_NONE) {
-        ssize_t index = mInputs.indexOfKey(*input);
-        if (index < 0) {
-            ALOGW("getInputForAttr() unknown MMAP input %d", *input);
-            return BAD_VALUE;
-        }
-        sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
-        sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
-        if (audioSession == 0) {
-            ALOGW("getInputForAttr() unknown session %d on input %d", session, *input);
-            return BAD_VALUE;
-        }
-        // For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger.
-        // The second call is for the first active client and sets the UID. Any further call
-        // corresponds to a new client and is only permitted from the same UId.
-        if (audioSession->openCount() == 1) {
-            audioSession->setUid(uid);
-        } else if (audioSession->uid() != uid) {
-            ALOGW("getInputForAttr() bad uid %d for session %d uid %d",
-                  uid, session, audioSession->uid());
-            return INVALID_OPERATION;
-        }
-        audioSession->changeOpenCount(1);
-        *inputType = API_INPUT_LEGACY;
-        if (*portId == AUDIO_PORT_HANDLE_NONE) {
-            *portId = AudioPort::getNextUniqueId();
-        }
-        DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(inputDesc->mDevice);
-        *selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
-                : AUDIO_PORT_HANDLE_NONE;
-        ALOGI("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
-        return NO_ERROR;
-    }
-
-    *input = AUDIO_IO_HANDLE_NONE;
-    *inputType = API_INPUT_INVALID;
-
-    audio_devices_t device;
+    status_t status = NO_ERROR;
     // handle legacy remote submix case where the address was not always specified
     String8 address = String8("");
-    audio_source_t inputSource = attr->source;
     audio_source_t halInputSource;
+    audio_source_t inputSource = attr->source;
     AudioMix *policyMix = NULL;
-
-    if (inputSource == AUDIO_SOURCE_DEFAULT) {
-        inputSource = AUDIO_SOURCE_MIC;
-    }
-    halInputSource = inputSource;
-
-    // TODO: check for existing client for this port ID
-    if (*portId == AUDIO_PORT_HANDLE_NONE) {
-        *portId = AudioPort::getNextUniqueId();
-    }
+    DeviceVector inputDevices;
 
     // Explicit routing?
     sp<DeviceDescriptor> deviceDesc;
@@ -1568,11 +1519,67 @@
     }
     mInputRoutes.addRoute(session, SessionRoute::STREAM_TYPE_NA, inputSource, deviceDesc, uid);
 
+    // special case for mmap capture: if an input IO handle is specified, we reuse this input if
+    // possible
+    if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ &&
+            *input != AUDIO_IO_HANDLE_NONE) {
+        ssize_t index = mInputs.indexOfKey(*input);
+        if (index < 0) {
+            ALOGW("getInputForAttr() unknown MMAP input %d", *input);
+            status = BAD_VALUE;
+            goto error;
+        }
+        sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
+        sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
+        if (audioSession == 0) {
+            ALOGW("getInputForAttr() unknown session %d on input %d", session, *input);
+            status = BAD_VALUE;
+            goto error;
+        }
+        // For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger.
+        // The second call is for the first active client and sets the UID. Any further call
+        // corresponds to a new client and is only permitted from the same UId.
+        if (audioSession->openCount() == 1) {
+            audioSession->setUid(uid);
+        } else if (audioSession->uid() != uid) {
+            ALOGW("getInputForAttr() bad uid %d for session %d uid %d",
+                  uid, session, audioSession->uid());
+            status = INVALID_OPERATION;
+            goto error;
+        }
+        audioSession->changeOpenCount(1);
+        *inputType = API_INPUT_LEGACY;
+        if (*portId == AUDIO_PORT_HANDLE_NONE) {
+            *portId = AudioPort::getNextUniqueId();
+        }
+        inputDevices = mAvailableInputDevices.getDevicesFromType(inputDesc->mDevice);
+        *selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
+                : AUDIO_PORT_HANDLE_NONE;
+        ALOGI("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
+
+        return NO_ERROR;
+    }
+
+    *input = AUDIO_IO_HANDLE_NONE;
+    *inputType = API_INPUT_INVALID;
+
+    if (inputSource == AUDIO_SOURCE_DEFAULT) {
+        inputSource = AUDIO_SOURCE_MIC;
+    }
+    halInputSource = inputSource;
+
+    // TODO: check for existing client for this port ID
+    if (*portId == AUDIO_PORT_HANDLE_NONE) {
+        *portId = AudioPort::getNextUniqueId();
+    }
+
+    audio_devices_t device;
+
     if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX &&
             strncmp(attr->tags, "addr=", strlen("addr=")) == 0) {
-        status_t ret = mPolicyMixes.getInputMixForAttr(*attr, &policyMix);
-        if (ret != NO_ERROR) {
-            return ret;
+        status = mPolicyMixes.getInputMixForAttr(*attr, &policyMix);
+        if (status != NO_ERROR) {
+            goto error;
         }
         *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
         device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
@@ -1581,7 +1588,8 @@
         device = getDeviceAndMixForInputSource(inputSource, &policyMix);
         if (device == AUDIO_DEVICE_NONE) {
             ALOGW("getInputForAttr() could not find device for source %d", inputSource);
-            return BAD_VALUE;
+            status = BAD_VALUE;
+            goto error;
         }
         if (policyMix != NULL) {
             address = policyMix->mDeviceAddress;
@@ -1610,11 +1618,11 @@
                                config->sample_rate, config->format, config->channel_mask, flags,
                                policyMix);
     if (*input == AUDIO_IO_HANDLE_NONE) {
-        mInputRoutes.removeRoute(session);
-        return INVALID_OPERATION;
+        status = INVALID_OPERATION;
+        goto error;
     }
 
-    DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(device);
+    inputDevices = mAvailableInputDevices.getDevicesFromType(device);
     *selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
             : AUDIO_PORT_HANDLE_NONE;
 
@@ -1622,6 +1630,10 @@
             *input, *inputType, *selectedDeviceId);
 
     return NO_ERROR;
+
+error:
+    mInputRoutes.removeRoute(session);
+    return status;
 }
 
 
@@ -4721,10 +4733,10 @@
     //      use device for strategy enforced audible
     // 2: we are in call or the strategy phone is active on the output:
     //      use device for strategy phone
-    // 3: the strategy for enforced audible is active but not enforced on the output:
-    //      use the device for strategy enforced audible
-    // 4: the strategy sonification is active on the output:
+    // 3: the strategy sonification is active on the output:
     //      use device for strategy sonification
+    // 4: the strategy for enforced audible is active but not enforced on the output:
+    //      use the device for strategy enforced audible
     // 5: the strategy accessibility is active on the output:
     //      use device for strategy accessibility
     // 6: the strategy "respectful" sonification is active on the output:
@@ -4741,10 +4753,10 @@
     } else if (isInCall() ||
                     isStrategyActive(outputDesc, STRATEGY_PHONE)) {
         device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
-    } else if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE)) {
-        device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
     } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION)) {
         device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
+    } else if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE)) {
+        device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
     } else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
         device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
     } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL)) {
@@ -4926,12 +4938,13 @@
     // scan the whole RouteMap, for each entry, convert the stream type to a strategy
     // (getStrategy(stream)).
     // if the strategy from the stream type in the RouteMap is the same as the argument above,
-    // and activity count is non-zero
-    // the device = the device from the descriptor in the RouteMap, and exit.
+    // and activity count is non-zero and the device in the route descriptor is available
+    // then select this device.
     for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
         sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
         routing_strategy routeStrategy = getStrategy(route->mStreamType);
-        if ((routeStrategy == strategy) && route->isActive()) {
+        if ((routeStrategy == strategy) && route->isActive() &&
+                (mAvailableOutputDevices.indexOf(route->mDeviceDescriptor) >= 0)) {
             return route->mDeviceDescriptor->type();
         }
     }
@@ -5326,9 +5339,15 @@
 
 audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
 {
+    // Routing
+    // Scan the whole RouteMap to see if we have an explicit route:
+    // if the input source in the RouteMap is the same as the argument above,
+    // and activity count is non-zero and the device in the route descriptor is available
+    // then select this device.
     for (size_t routeIndex = 0; routeIndex < mInputRoutes.size(); routeIndex++) {
          sp<SessionRoute> route = mInputRoutes.valueAt(routeIndex);
-         if (inputSource == route->mSource && route->isActive()) {
+         if ((inputSource == route->mSource) && route->isActive() &&
+                 (mAvailableInputDevices.indexOf(route->mDeviceDescriptor) >= 0)) {
              return route->mDeviceDescriptor->type();
          }
      }
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index dbcc070..31c9575 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -220,11 +220,11 @@
 }
 
 void AudioPolicyService::AudioPolicyClient::onRecordingConfigurationUpdate(
-        int event, audio_session_t session, audio_source_t source,
+        int event, const record_client_info_t *clientInfo,
         const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
         audio_patch_handle_t patchHandle)
 {
-    mAudioPolicyService->onRecordingConfigurationUpdate(event, session, source,
+    mAudioPolicyService->onRecordingConfigurationUpdate(event, clientInfo,
             clientConfig, deviceConfig, patchHandle);
 }
 
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 654465d..84b1073 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -20,8 +20,10 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <memory>
 #include <cutils/misc.h>
 #include <media/AudioEffect.h>
+#include <media/EffectsConfig.h>
 #include <system/audio.h>
 #include <system/audio_effects/audio_effects_conf.h>
 #include <utils/Vector.h>
@@ -39,11 +41,17 @@
 
 AudioPolicyEffects::AudioPolicyEffects()
 {
-    // load automatic audio effect modules
-    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
-        loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
-    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
-        loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+    status_t loadResult = loadAudioEffectXmlConfig();
+    if (loadResult < 0) {
+        ALOGW("Failed to load XML effect configuration, fallback to .conf");
+        // load automatic audio effect modules
+        if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
+            loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+        } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
+            loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+        }
+    } else if (loadResult > 0) {
+        ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
     }
 }
 
@@ -685,6 +693,28 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
+    auto result = effectsConfig::parse();
+    if (result.parsedConfig == nullptr) {
+        return -ENOENT;
+    }
+
+    auto loadProcessingChain = [](auto& processingChain, auto& streams) {
+        for (auto& stream : processingChain) {
+            auto effectDescs = std::make_unique<EffectDescVector>();
+            for (auto& effect : stream.effects) {
+                effectDescs->mEffects.add(
+                        new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
+            }
+            streams.add(stream.type, effectDescs.release());
+        }
+    };
+    loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
+    loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
+    // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
+    return result.nbSkippedElement;
+}
+
 status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
 {
     cnode *root;
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 0c74d87..59d5d14 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -155,7 +155,8 @@
     audio_stream_type_t streamNameToEnum(const char *name);
 
     // Parse audio_effects.conf
-    status_t loadAudioEffectConfig(const char *path);
+    status_t loadAudioEffectConfig(const char *path); // TODO: add legacy in the name
+    status_t loadAudioEffectXmlConfig(); // TODO: remove "Xml" in the name
 
     // Load all effects descriptors in configuration file
     status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 7d7cd93..b7bce55 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -289,13 +289,6 @@
         return BAD_VALUE;
     }
 
-    if ((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) {
-        return BAD_VALUE;
-    }
-    sp<AudioPolicyEffects>audioPolicyEffects;
-    status_t status;
-    AudioPolicyInterface::input_type_t inputType;
-
     bool updatePid = (pid == -1);
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
     if (!isTrustedCallingUid(callingUid)) {
@@ -313,7 +306,15 @@
         pid = callingPid;
     }
 
+    if ((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed(pid, uid)) {
+        return BAD_VALUE;
+    }
+
+    sp<AudioPolicyEffects>audioPolicyEffects;
     {
+        status_t status;
+        AudioPolicyInterface::input_type_t inputType;
+
         Mutex::Autolock _l(mLock);
         // the audio_in_acoustics_t parameter is ignored by get_input()
         status = mAudioPolicyManager->getInputForAttr(attr, input, session, uid,
@@ -693,6 +694,7 @@
                                        audio_io_handle_t *ioHandle,
                                        audio_devices_t *device)
 {
+    Mutex::Autolock _l(mLock);
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
@@ -702,6 +704,7 @@
 
 status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
 {
+    Mutex::Autolock _l(mLock);
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index c4f6367..b417631 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -185,21 +185,21 @@
     }
 }
 
-void AudioPolicyService::onRecordingConfigurationUpdate(int event, audio_session_t session,
-        audio_source_t source, const audio_config_base_t *clientConfig,
+void AudioPolicyService::onRecordingConfigurationUpdate(int event,
+        const record_client_info_t *clientInfo, const audio_config_base_t *clientConfig,
         const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle)
 {
-    mOutputCommandThread->recordingConfigurationUpdateCommand(event, session, source,
+    mOutputCommandThread->recordingConfigurationUpdateCommand(event, clientInfo,
             clientConfig, deviceConfig, patchHandle);
 }
 
-void AudioPolicyService::doOnRecordingConfigurationUpdate(int event, audio_session_t session,
-        audio_source_t source, const audio_config_base_t *clientConfig,
+void AudioPolicyService::doOnRecordingConfigurationUpdate(int event,
+        const record_client_info_t *clientInfo, const audio_config_base_t *clientConfig,
         const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle)
 {
     Mutex::Autolock _l(mNotificationClientsLock);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
-        mNotificationClients.valueAt(i)->onRecordingConfigurationUpdate(event, session, source,
+        mNotificationClients.valueAt(i)->onRecordingConfigurationUpdate(event, clientInfo,
                 clientConfig, deviceConfig, patchHandle);
     }
 }
@@ -267,12 +267,12 @@
 }
 
 void AudioPolicyService::NotificationClient::onRecordingConfigurationUpdate(
-        int event, audio_session_t session, audio_source_t source,
+        int event, const record_client_info_t *clientInfo,
         const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
         audio_patch_handle_t patchHandle)
 {
     if (mAudioPolicyServiceClient != 0) {
-        mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, session, source,
+        mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, clientInfo,
                 clientConfig, deviceConfig, patchHandle);
     }
 }
@@ -544,8 +544,8 @@
                         break;
                     }
                     mLock.unlock();
-                    svc->doOnRecordingConfigurationUpdate(data->mEvent, data->mSession,
-                            data->mSource, &data->mClientConfig, &data->mDeviceConfig,
+                    svc->doOnRecordingConfigurationUpdate(data->mEvent, &data->mClientInfo,
+                            &data->mClientConfig, &data->mDeviceConfig,
                             data->mPatchHandle);
                     mLock.lock();
                     } break;
@@ -810,7 +810,7 @@
 }
 
 void AudioPolicyService::AudioCommandThread::recordingConfigurationUpdateCommand(
-        int event, audio_session_t session, audio_source_t source,
+        int event, const record_client_info_t *clientInfo,
         const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
         audio_patch_handle_t patchHandle)
 {
@@ -818,14 +818,13 @@
     command->mCommand = RECORDING_CONFIGURATION_UPDATE;
     RecordingConfigurationUpdateData *data = new RecordingConfigurationUpdateData();
     data->mEvent = event;
-    data->mSession = session;
-    data->mSource = source;
+    data->mClientInfo = *clientInfo;
     data->mClientConfig = *clientConfig;
     data->mDeviceConfig = *deviceConfig;
     data->mPatchHandle = patchHandle;
     command->mParam = data;
-    ALOGV("AudioCommandThread() adding recording configuration update event %d, source %d",
-            event, source);
+    ALOGV("AudioCommandThread() adding recording configuration update event %d, source %d uid %u",
+            event, clientInfo->source, clientInfo->uid);
     sendCommand(command);
 }
 
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 35542f1..38d4b17 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -228,11 +228,11 @@
 
             void onDynamicPolicyMixStateUpdate(const String8& regId, int32_t state);
             void doOnDynamicPolicyMixStateUpdate(const String8& regId, int32_t state);
-            void onRecordingConfigurationUpdate(int event, audio_session_t session,
-                    audio_source_t source, const audio_config_base_t *clientConfig,
+            void onRecordingConfigurationUpdate(int event, const record_client_info_t *clientInfo,
+                    const audio_config_base_t *clientConfig,
                     const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
-            void doOnRecordingConfigurationUpdate(int event, audio_session_t session,
-                    audio_source_t source, const audio_config_base_t *clientConfig,
+            void doOnRecordingConfigurationUpdate(int event, const record_client_info_t *clientInfo,
+                    const audio_config_base_t *clientConfig,
                     const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
 
 private:
@@ -306,8 +306,8 @@
                                                           int delayMs);
                     void        dynamicPolicyMixStateUpdateCommand(const String8& regId, int32_t state);
                     void        recordingConfigurationUpdateCommand(
-                                                        int event, audio_session_t session,
-                                                        audio_source_t source,
+                                                        int event,
+                                                        const record_client_info_t *clientInfo,
                                                         const audio_config_base_t *clientConfig,
                                                         const audio_config_base_t *deviceConfig,
                                                         audio_patch_handle_t patchHandle);
@@ -404,8 +404,7 @@
         class RecordingConfigurationUpdateData : public AudioCommandData {
         public:
             int mEvent;
-            audio_session_t mSession;
-            audio_source_t mSource;
+            record_client_info_t mClientInfo;
             struct audio_config_base mClientConfig;
             struct audio_config_base mDeviceConfig;
             audio_patch_handle_t mPatchHandle;
@@ -518,7 +517,7 @@
         virtual void onAudioPatchListUpdate();
         virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
         virtual void onRecordingConfigurationUpdate(int event,
-                        audio_session_t session, audio_source_t source,
+                        const record_client_info_t *clientInfo,
                         const audio_config_base_t *clientConfig,
                         const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
 
@@ -540,8 +539,7 @@
                             void      onAudioPatchListUpdate();
                             void      onDynamicPolicyMixStateUpdate(const String8& regId, int32_t state);
                             void      onRecordingConfigurationUpdate(
-                                        int event, audio_session_t session,
-                                        audio_source_t source,
+                                        int event, const record_client_info_t *clientInfo,
                                         const audio_config_base_t *clientConfig,
                                         const audio_config_base_t *deviceConfig,
                                         audio_patch_handle_t patchHandle);
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 01f033a..1fbba58 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -77,7 +77,8 @@
     android.hardware.camera.common@1.0 \
     android.hardware.camera.provider@2.4 \
     android.hardware.camera.device@1.0 \
-    android.hardware.camera.device@3.2
+    android.hardware.camera.device@3.2 \
+    android.hardware.camera.device@3.3
 
 LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder libcamera_client libfmq
 
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index a28518e..2cf648f 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -72,6 +72,20 @@
     return initializeImpl(manager);
 }
 
+bool Camera2Client::isZslEnabledInStillTemplate() {
+    bool zslEnabled = false;
+    CameraMetadata stillTemplate;
+    status_t res = mDevice->createDefaultRequest(CAMERA2_TEMPLATE_STILL_CAPTURE, &stillTemplate);
+    if (res == OK) {
+        camera_metadata_entry_t enableZsl = stillTemplate.find(ANDROID_CONTROL_ENABLE_ZSL);
+        if (enableZsl.count == 1) {
+            zslEnabled = (enableZsl.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE);
+        }
+    }
+
+    return zslEnabled;
+}
+
 template<typename TProviderPtr>
 status_t Camera2Client::initializeImpl(TProviderPtr providerPtr)
 {
@@ -93,6 +107,8 @@
                     __FUNCTION__, mCameraId, strerror(-res), res);
             return NO_INIT;
         }
+
+        l.mParameters.isDeviceZslSupported = isZslEnabledInStillTemplate();
     }
 
     String8 threadName;
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 72315d4..5af74eb 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -224,6 +224,8 @@
 
     template<typename TProviderPtr>
     status_t initializeImpl(TProviderPtr providerPtr);
+
+    bool isZslEnabledInStillTemplate();
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index 3f4017f..0d2dba1 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -121,18 +121,17 @@
 
     if (mCallbackStreamId != NO_STREAM) {
         // Check if stream parameters have to change
-        uint32_t currentWidth, currentHeight, currentFormat;
-        res = device->getStreamInfo(mCallbackStreamId,
-                &currentWidth, &currentHeight, &currentFormat, 0);
+        CameraDeviceBase::StreamInfo streamInfo;
+        res = device->getStreamInfo(mCallbackStreamId, &streamInfo);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying callback output stream info: "
                     "%s (%d)", __FUNCTION__, mId,
                     strerror(-res), res);
             return res;
         }
-        if (currentWidth != (uint32_t)params.previewWidth ||
-                currentHeight != (uint32_t)params.previewHeight ||
-                currentFormat != (uint32_t)callbackFormat) {
+        if (streamInfo.width != (uint32_t)params.previewWidth ||
+                streamInfo.height != (uint32_t)params.previewHeight ||
+                !streamInfo.matchFormat((uint32_t)callbackFormat)) {
             // Since size should only change while preview is not running,
             // assuming that all existing use of old callback stream is
             // completed.
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index d6d8dde..d8b7af2 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -136,17 +136,16 @@
 
     if (mCaptureStreamId != NO_STREAM) {
         // Check if stream parameters have to change
-        uint32_t currentWidth, currentHeight;
-        res = device->getStreamInfo(mCaptureStreamId,
-                &currentWidth, &currentHeight, 0, 0);
+        CameraDeviceBase::StreamInfo streamInfo;
+        res = device->getStreamInfo(mCaptureStreamId, &streamInfo);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying capture output stream info: "
                     "%s (%d)", __FUNCTION__,
                     mId, strerror(-res), res);
             return res;
         }
-        if (currentWidth != (uint32_t)params.pictureWidth ||
-                currentHeight != (uint32_t)params.pictureHeight) {
+        if (streamInfo.width != (uint32_t)params.pictureWidth ||
+                streamInfo.height != (uint32_t)params.pictureHeight) {
             ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
                 __FUNCTION__, mId, mCaptureStreamId);
             res = device->deleteStream(mCaptureStreamId);
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 1addcdd..02a7616 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -954,7 +954,8 @@
         }
     }
 
-    if (slowJpegMode || property_get_bool("camera.disable_zsl_mode", false)) {
+    if (isDeviceZslSupported || slowJpegMode ||
+            property_get_bool("camera.disable_zsl_mode", false)) {
         ALOGI("Camera %d: Disabling ZSL mode", cameraId);
         allowZslMode = false;
     } else {
@@ -1997,7 +1998,8 @@
     if (previewFpsRange[1] > 1e9/minFrameDurationNs + FPS_MARGIN) {
         slowJpegMode = true;
     }
-    if (slowJpegMode || property_get_bool("camera.disable_zsl_mode", false)) {
+    if (isDeviceZslSupported || slowJpegMode ||
+            property_get_bool("camera.disable_zsl_mode", false)) {
         allowZslMode = false;
     } else {
         allowZslMode = isZslReprocessPresent;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index bea867a..17e3d75 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -175,6 +175,8 @@
     bool slowJpegMode;
     // Whether ZSL reprocess is supported by the device.
     bool isZslReprocessPresent;
+    // Whether the device supports enableZsl.
+    bool isDeviceZslSupported;
 
     // Overall camera state
     enum State {
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index d79e430..73dca73 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -161,18 +161,17 @@
 
     if (mPreviewStreamId != NO_STREAM) {
         // Check if stream parameters have to change
-        uint32_t currentWidth, currentHeight;
-        res = device->getStreamInfo(mPreviewStreamId,
-                &currentWidth, &currentHeight, 0, 0);
+        CameraDeviceBase::StreamInfo streamInfo;
+        res = device->getStreamInfo(mPreviewStreamId, &streamInfo);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying preview stream info: "
                     "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
             return res;
         }
-        if (currentWidth != (uint32_t)params.previewWidth ||
-                currentHeight != (uint32_t)params.previewHeight) {
+        if (streamInfo.width != (uint32_t)params.previewWidth ||
+                streamInfo.height != (uint32_t)params.previewHeight) {
             ALOGV("%s: Camera %d: Preview size switch: %d x %d -> %d x %d",
-                    __FUNCTION__, mId, currentWidth, currentHeight,
+                    __FUNCTION__, mId, streamInfo.width, streamInfo.height,
                     params.previewWidth, params.previewHeight);
             res = device->waitUntilDrained();
             if (res != OK) {
@@ -312,10 +311,8 @@
         return INVALID_OPERATION;
     }
 
-    uint32_t currentWidth, currentHeight, currentFormat;
-    android_dataspace currentDataSpace;
-    res = device->getStreamInfo(mRecordingStreamId,
-            &currentWidth, &currentHeight, &currentFormat, &currentDataSpace);
+    CameraDeviceBase::StreamInfo streamInfo;
+    res = device->getStreamInfo(mRecordingStreamId, &streamInfo);
     if (res != OK) {
         ALOGE("%s: Camera %d: Error querying recording output stream info: "
                 "%s (%d)", __FUNCTION__, mId,
@@ -324,10 +321,10 @@
     }
 
     if (mRecordingWindow == nullptr ||
-            currentWidth != (uint32_t)params.videoWidth ||
-            currentHeight != (uint32_t)params.videoHeight ||
-            currentFormat != (uint32_t)params.videoFormat ||
-            currentDataSpace != params.videoDataSpace) {
+            streamInfo.width != (uint32_t)params.videoWidth ||
+            streamInfo.height != (uint32_t)params.videoHeight ||
+            !streamInfo.matchFormat((uint32_t)params.videoFormat) ||
+            !streamInfo.matchDataSpace(params.videoDataSpace)) {
         *needsUpdate = true;
         return res;
     }
@@ -348,22 +345,18 @@
 
     if (mRecordingStreamId != NO_STREAM) {
         // Check if stream parameters have to change
-        uint32_t currentWidth, currentHeight;
-        uint32_t currentFormat;
-        android_dataspace currentDataSpace;
-        res = device->getStreamInfo(mRecordingStreamId,
-                &currentWidth, &currentHeight,
-                &currentFormat, &currentDataSpace);
+        CameraDeviceBase::StreamInfo streamInfo;
+        res = device->getStreamInfo(mRecordingStreamId, &streamInfo);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying recording output stream info: "
                     "%s (%d)", __FUNCTION__, mId,
                     strerror(-res), res);
             return res;
         }
-        if (currentWidth != (uint32_t)params.videoWidth ||
-                currentHeight != (uint32_t)params.videoHeight ||
-                currentFormat != (uint32_t)params.videoFormat ||
-                currentDataSpace != params.videoDataSpace) {
+        if (streamInfo.width != (uint32_t)params.videoWidth ||
+                streamInfo.height != (uint32_t)params.videoHeight ||
+                !streamInfo.matchFormat((uint32_t)params.videoFormat) ||
+                !streamInfo.matchDataSpace(params.videoDataSpace)) {
             // TODO: Should wait to be sure previous recording has finished
             res = device->deleteStream(mRecordingStreamId);
 
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 9bc31b9..b0607fb 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -233,17 +233,16 @@
 
     if ((mZslStreamId != NO_STREAM) || (mInputStreamId != NO_STREAM)) {
         // Check if stream parameters have to change
-        uint32_t currentWidth, currentHeight;
-        res = device->getStreamInfo(mZslStreamId,
-                &currentWidth, &currentHeight, 0, 0);
+        CameraDeviceBase::StreamInfo streamInfo;
+        res = device->getStreamInfo(mZslStreamId, &streamInfo);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying capture output stream info: "
                     "%s (%d)", __FUNCTION__,
                     client->getCameraId(), strerror(-res), res);
             return res;
         }
-        if (currentWidth != (uint32_t)params.fastInfo.arrayWidth ||
-                currentHeight != (uint32_t)params.fastInfo.arrayHeight) {
+        if (streamInfo.width != (uint32_t)params.fastInfo.arrayWidth ||
+                streamInfo.height != (uint32_t)params.fastInfo.arrayHeight) {
             if (mZslStreamId != NO_STREAM) {
                 ALOGV("%s: Camera %d: Deleting stream %d since the buffer "
                       "dimensions changed",
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 0429e7f..c03e8a2 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -313,11 +313,13 @@
 
 binder::Status CameraDeviceClient::beginConfigure() {
     // TODO: Implement this.
+    ATRACE_CALL();
     ALOGV("%s: Not implemented yet.", __FUNCTION__);
     return binder::Status::ok();
 }
 
 binder::Status CameraDeviceClient::endConfigure(int operatingMode) {
+    ATRACE_CALL();
     ALOGV("%s: ending configure (%d input stream, %zu output surfaces)",
             __FUNCTION__, mInputStream.configured ? 1 : 0,
             mStreamMap.size());
@@ -568,7 +570,7 @@
         /*out*/
         int* newStreamId) {
     int width, height, format, surfaceType;
-    int32_t consumerUsage;
+    uint64_t consumerUsage;
     android_dataspace dataSpace;
     status_t err;
     binder::Status res;
@@ -764,24 +766,23 @@
     // Query consumer usage bits to set async operation mode for
     // GLConsumer using controlledByApp parameter.
     bool useAsync = false;
-    int32_t consumerUsage;
+    uint64_t consumerUsage = 0;
     status_t err;
-    if ((err = gbp->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS,
-            &consumerUsage)) != OK) {
+    if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
                 mCameraIdStr.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
     if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
-        ALOGW("%s: Camera %s with consumer usage flag: 0x%x: Forcing asynchronous mode for stream",
+        ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for stream",
                 __FUNCTION__, mCameraIdStr.string(), consumerUsage);
         useAsync = true;
     }
 
-    int32_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
+    uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
                               GRALLOC_USAGE_RENDERSCRIPT;
-    int32_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
+    uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
                            GraphicBuffer::USAGE_HW_TEXTURE |
                            GraphicBuffer::USAGE_HW_COMPOSER;
     bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
@@ -874,7 +875,7 @@
         //surface class type. Use usage flag to approximate the comparison.
         if (consumerUsage != streamInfo.consumerUsage) {
             String8 msg = String8::format(
-                    "Camera %s:Surface usage flag doesn't match 0x%x vs 0x%x",
+                    "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
                     mCameraIdStr.string(), consumerUsage, streamInfo.consumerUsage);
             ALOGE("%s: %s", __FUNCTION__, msg.string());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
@@ -1353,7 +1354,7 @@
     sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
 
     if (remoteCb != 0) {
-        remoteCb->onRepeatingRequestError(lastFrameNumber);
+        remoteCb->onRepeatingRequestError(lastFrameNumber, mStreamingRequestId);
     }
 
     Mutex::Autolock idLock(mStreamingRequestIdLock);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index e8fc080..50661cb 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -213,13 +213,13 @@
         int height;
         int format;
         android_dataspace dataSpace;
-        int32_t consumerUsage;
+        uint64_t consumerUsage;
         bool finalized = false;
         OutputStreamInfo() :
                 width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
                 consumerUsage(0) {}
         OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
-                int32_t _consumerUsage) :
+                uint64_t _consumerUsage) :
                     width(_width), height(_height), format(_format),
                     dataSpace(_dataSpace), consumerUsage(_consumerUsage) {}
     };
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index d9059f3..3919bfa 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -119,7 +119,7 @@
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
-            bool isShared = false, uint32_t consumerUsage = 0) = 0;
+            bool isShared = false, uint64_t consumerUsage = 0) = 0;
 
     /**
      * Create an output stream of the requested size, format, rotation and
@@ -132,7 +132,7 @@
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
-            bool isShared = false, uint32_t consumerUsage = 0) = 0;
+            bool isShared = false, uint64_t consumerUsage = 0) = 0;
 
     /**
      * Create an input stream of width, height, and format.
@@ -142,12 +142,51 @@
     virtual status_t createInputStream(uint32_t width, uint32_t height,
             int32_t format, /*out*/ int32_t *id) = 0;
 
+    struct StreamInfo {
+        uint32_t width;
+        uint32_t height;
+
+        uint32_t format;
+        bool formatOverridden;
+        uint32_t originalFormat;
+
+        android_dataspace dataSpace;
+        bool dataSpaceOverridden;
+        android_dataspace originalDataSpace;
+
+        StreamInfo() : width(0), height(0), format(0), formatOverridden(false), originalFormat(0),
+                dataSpace(HAL_DATASPACE_UNKNOWN), dataSpaceOverridden(false),
+                originalDataSpace(HAL_DATASPACE_UNKNOWN) {}
+        /**
+         * Check whether the format matches the current or the original one in case
+         * it got overridden.
+         */
+        bool matchFormat(uint32_t clientFormat) const {
+            if ((formatOverridden && (originalFormat == clientFormat)) ||
+                    (format == clientFormat)) {
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Check whether the dataspace matches the current or the original one in case
+         * it got overridden.
+         */
+        bool matchDataSpace(android_dataspace clientDataSpace) const {
+            if ((dataSpaceOverridden && (originalDataSpace == clientDataSpace)) ||
+                    (dataSpace == clientDataSpace)) {
+                return true;
+            }
+            return false;
+        }
+
+    };
+
     /**
      * Get information about a given stream.
      */
-    virtual status_t getStreamInfo(int id,
-            uint32_t *width, uint32_t *height,
-            uint32_t *format, android_dataspace *dataSpace) = 0;
+    virtual status_t getStreamInfo(int id, StreamInfo *streamInfo) = 0;
 
     /**
      * Set stream gralloc buffer transform
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index a02090b..ae3bbc1 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -202,12 +202,17 @@
     for (auto& provider : mProviders) {
         auto deviceInfo = findDeviceInfoLocked(id);
         if (deviceInfo != nullptr) {
-            provider->mInterface->isSetTorchModeSupported(
+            auto ret = provider->mInterface->isSetTorchModeSupported(
                 [&support](auto status, bool supported) {
                     if (status == Status::OK) {
                         support = supported;
                     }
                 });
+            if (!ret.isOk()) {
+                ALOGE("%s: Transaction error checking torch mode support '%s': %s",
+                        __FUNCTION__, provider->mProviderName.c_str(), ret.description().c_str());
+            }
+            break;
         }
     }
     return support;
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 0fae598..522d521 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -29,11 +29,6 @@
 CameraHardwareInterface::~CameraHardwareInterface()
 {
     ALOGI("Destroying camera %s", mName.string());
-    if (mDevice) {
-        int rc = mDevice->common.close(&mDevice->common);
-        if (rc != OK)
-            ALOGE("Could not close camera %s: %d", mName.string(), rc);
-    }
     if (mHidlDevice != nullptr) {
         mHidlDevice->close();
         mHidlDevice.clear();
@@ -42,12 +37,6 @@
 }
 
 status_t CameraHardwareInterface::initialize(sp<CameraProviderManager> manager) {
-    if (mDevice) {
-        ALOGE("%s: camera hardware interface has been initialized to libhardware path!",
-                __FUNCTION__);
-        return INVALID_OPERATION;
-    }
-
     ALOGI("Opening camera %s", mName.string());
 
     status_t ret = manager->openSession(mName.string(), this, &mHidlDevice);
@@ -393,7 +382,7 @@
         ALOGE("%s: preview window is null", __FUNCTION__);
         return s;
     }
-    mPreviewUsage = (int) usage;
+    mPreviewUsage = static_cast<uint64_t> (usage);
     int rc = native_window_set_usage(a, mPreviewUsage);
     if (rc == OK) {
         cleanupCirculatingBuffers();
@@ -465,23 +454,6 @@
         }
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->setPreviewWindow(buf.get() ? this : nullptr));
-    } else if (mDevice) {
-        if (mDevice->ops->set_preview_window) {
-            mPreviewWindow = buf;
-            if (buf != nullptr) {
-                if (mPreviewScalingMode != NOT_SET) {
-                    setPreviewScalingMode(mPreviewScalingMode);
-                }
-                if (mPreviewTransform != NOT_SET) {
-                    setPreviewTransform(mPreviewTransform);
-                }
-            }
-            mHalPreviewWindow.user = this;
-            ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p",__FUNCTION__,
-                    &mHalPreviewWindow, mHalPreviewWindow.user);
-            return mDevice->ops->set_preview_window(mDevice,
-                    buf.get() ? &mHalPreviewWindow.nw : 0);
-        }
     }
     return INVALID_OPERATION;
 }
@@ -499,15 +471,6 @@
     mCbUser = user;
 
     ALOGV("%s(%s)", __FUNCTION__, mName.string());
-
-    if (mDevice && mDevice->ops->set_callbacks) {
-        mDevice->ops->set_callbacks(mDevice,
-                               sNotifyCb,
-                               sDataCb,
-                               sDataCbTimestamp,
-                               sGetMemory,
-                               this);
-    }
 }
 
 void CameraHardwareInterface::enableMsgType(int32_t msgType)
@@ -515,8 +478,6 @@
     ALOGV("%s(%s)", __FUNCTION__, mName.string());
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         mHidlDevice->enableMsgType(msgType);
-    } else if (mDevice && mDevice->ops->enable_msg_type) {
-        mDevice->ops->enable_msg_type(mDevice, msgType);
     }
 }
 
@@ -525,8 +486,6 @@
     ALOGV("%s(%s)", __FUNCTION__, mName.string());
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         mHidlDevice->disableMsgType(msgType);
-    } else if (mDevice && mDevice->ops->disable_msg_type) {
-        mDevice->ops->disable_msg_type(mDevice, msgType);
     }
 }
 
@@ -535,8 +494,6 @@
     ALOGV("%s(%s)", __FUNCTION__, mName.string());
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return mHidlDevice->msgTypeEnabled(msgType);
-    } else if (mDevice && mDevice->ops->msg_type_enabled) {
-        return mDevice->ops->msg_type_enabled(mDevice, msgType);
     }
     return false;
 }
@@ -547,8 +504,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->startPreview());
-    } else if (mDevice && mDevice->ops->start_preview) {
-        return mDevice->ops->start_preview(mDevice);
     }
     return INVALID_OPERATION;
 }
@@ -558,8 +513,6 @@
     ALOGV("%s(%s)", __FUNCTION__, mName.string());
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         mHidlDevice->stopPreview();
-    } else if (mDevice && mDevice->ops->stop_preview) {
-        mDevice->ops->stop_preview(mDevice);
     }
 }
 
@@ -568,8 +521,6 @@
     ALOGV("%s(%s)", __FUNCTION__, mName.string());
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return mHidlDevice->previewEnabled();
-    } else if (mDevice && mDevice->ops->preview_enabled) {
-        return mDevice->ops->preview_enabled(mDevice);
     }
     return false;
 }
@@ -580,8 +531,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->storeMetaDataInBuffers(enable));
-    } else if (mDevice && mDevice->ops->store_meta_data_in_buffers) {
-        return mDevice->ops->store_meta_data_in_buffers(mDevice, enable);
     }
     return enable ? INVALID_OPERATION: OK;
 }
@@ -592,8 +541,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->startRecording());
-    } else if (mDevice && mDevice->ops->start_recording) {
-        return mDevice->ops->start_recording(mDevice);
     }
     return INVALID_OPERATION;
 }
@@ -606,8 +553,6 @@
     ALOGV("%s(%s)", __FUNCTION__, mName.string());
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         mHidlDevice->stopRecording();
-    } else if (mDevice && mDevice->ops->stop_recording) {
-        mDevice->ops->stop_recording(mDevice);
     }
 }
 
@@ -619,8 +564,6 @@
     ALOGV("%s(%s)", __FUNCTION__, mName.string());
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return mHidlDevice->recordingEnabled();
-    } else if (mDevice && mDevice->ops->recording_enabled) {
-        return mDevice->ops->recording_enabled(mDevice);
     }
     return false;
 }
@@ -645,9 +588,6 @@
         } else {
             mHidlDevice->releaseRecordingFrame(heapId, bufferIndex);
         }
-    } else if (mDevice && mDevice->ops->release_recording_frame) {
-        void *data = ((uint8_t *)heap->base()) + offset;
-        return mDevice->ops->release_recording_frame(mDevice, data);
     }
 }
 
@@ -674,9 +614,6 @@
                 ALOGE("%s only supports VideoNativeHandleMetadata mode", __FUNCTION__);
                 return;
             }
-        } else {
-            ALOGE("Non HIDL mode do not support %s", __FUNCTION__);
-            return;
         }
     }
 
@@ -695,8 +632,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->autoFocus());
-    } else if (mDevice && mDevice->ops->auto_focus) {
-        return mDevice->ops->auto_focus(mDevice);
     }
     return INVALID_OPERATION;
 }
@@ -707,8 +642,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->cancelAutoFocus());
-    } else if (mDevice && mDevice->ops->cancel_auto_focus) {
-        return mDevice->ops->cancel_auto_focus(mDevice);
     }
     return INVALID_OPERATION;
 }
@@ -719,8 +652,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->takePicture());
-    } else if (mDevice && mDevice->ops->take_picture) {
-        return mDevice->ops->take_picture(mDevice);
     }
     return INVALID_OPERATION;
 }
@@ -731,8 +662,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->cancelPicture());
-    } else if (mDevice && mDevice->ops->cancel_picture) {
-        return mDevice->ops->cancel_picture(mDevice);
     }
     return INVALID_OPERATION;
 }
@@ -743,8 +672,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->setParameters(params.flatten().string()));
-    } else if (mDevice && mDevice->ops->set_parameters) {
-        return mDevice->ops->set_parameters(mDevice, params.flatten().string());
     }
     return INVALID_OPERATION;
 }
@@ -761,14 +688,6 @@
                 });
         String8 tmp(outParam.c_str());
         parms.unflatten(tmp);
-    } else if (mDevice && mDevice->ops->get_parameters) {
-        char *temp = mDevice->ops->get_parameters(mDevice);
-        String8 str_parms(temp);
-        if (mDevice->ops->put_parameters)
-            mDevice->ops->put_parameters(mDevice, temp);
-        else
-            free(temp);
-        parms.unflatten(str_parms);
     }
     return parms;
 }
@@ -779,8 +698,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         return CameraProviderManager::mapToStatusT(
                 mHidlDevice->sendCommand((CommandType) cmd, arg1, arg2));
-    } else if (mDevice && mDevice->ops->send_command) {
-        return mDevice->ops->send_command(mDevice, cmd, arg1, arg2);
     }
     return INVALID_OPERATION;
 }
@@ -794,8 +711,6 @@
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         mHidlDevice->close();
         mHidlDevice.clear();
-    } else if (mDevice && mDevice->ops->release) {
-        mDevice->ops->release(mDevice);
     }
 }
 
@@ -811,15 +726,10 @@
         Status s = mHidlDevice->dumpState(handle);
         native_handle_delete(handle);
         return CameraProviderManager::mapToStatusT(s);
-    } else if (mDevice && mDevice->ops->dump) {
-        return mDevice->ops->dump(mDevice, fd);
     }
     return OK; // It's fine if the HAL doesn't implement dump()
 }
 
-/**
- * Methods for legacy (non-HIDL) path follows
- */
 void CameraHardwareInterface::sNotifyCb(int32_t msg_type, int32_t ext1,
                         int32_t ext2, void *user)
 {
@@ -889,177 +799,4 @@
     mem->decStrong(mem);
 }
 
-ANativeWindow* CameraHardwareInterface::sToAnw(void *user)
-{
-    CameraHardwareInterface *object =
-            reinterpret_cast<CameraHardwareInterface *>(user);
-    return object->mPreviewWindow.get();
-}
-#define anw(n) sToAnw(((struct camera_preview_window *)(n))->user)
-#define hwi(n) reinterpret_cast<CameraHardwareInterface *>(\
-    ((struct camera_preview_window *)(n))->user)
-
-int CameraHardwareInterface::sDequeueBuffer(struct preview_stream_ops* w,
-                            buffer_handle_t** buffer, int *stride)
-{
-    int rc;
-    ANativeWindow *a = anw(w);
-    ANativeWindowBuffer* anb;
-    rc = native_window_dequeue_buffer_and_wait(a, &anb);
-    if (rc == OK) {
-        *buffer = &anb->handle;
-        *stride = anb->stride;
-    }
-    return rc;
-}
-
-#ifndef container_of
-#define container_of(ptr, type, member) ({                      \
-    const __typeof__(((type *) 0)->member) *__mptr = (ptr);     \
-    (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
-#endif
-
-int CameraHardwareInterface::sLockBuffer(struct preview_stream_ops* w,
-                  buffer_handle_t* /*buffer*/)
-{
-    ANativeWindow *a = anw(w);
-    (void)a;
-    return 0;
-}
-
-int CameraHardwareInterface::sEnqueueBuffer(struct preview_stream_ops* w,
-                  buffer_handle_t* buffer)
-{
-    ANativeWindow *a = anw(w);
-    return a->queueBuffer(a,
-              container_of(buffer, ANativeWindowBuffer, handle), -1);
-}
-
-int CameraHardwareInterface::sCancelBuffer(struct preview_stream_ops* w,
-                  buffer_handle_t* buffer)
-{
-    ANativeWindow *a = anw(w);
-    return a->cancelBuffer(a,
-              container_of(buffer, ANativeWindowBuffer, handle), -1);
-}
-
-int CameraHardwareInterface::sSetBufferCount(struct preview_stream_ops* w, int count)
-{
-    ANativeWindow *a = anw(w);
-
-    if (a != nullptr) {
-        // Workaround for b/27039775
-        // Previously, setting the buffer count would reset the buffer
-        // queue's flag that allows for all buffers to be dequeued on the
-        // producer side, instead of just the producer's declared max count,
-        // if no filled buffers have yet been queued by the producer.  This
-        // reset no longer happens, but some HALs depend on this behavior,
-        // so it needs to be maintained for HAL backwards compatibility.
-        // Simulate the prior behavior by disconnecting/reconnecting to the
-        // window and setting the values again.  This has the drawback of
-        // actually causing memory reallocation, which may not have happened
-        // in the past.
-        CameraHardwareInterface *hw = hwi(w);
-        native_window_api_disconnect(a, NATIVE_WINDOW_API_CAMERA);
-        native_window_api_connect(a, NATIVE_WINDOW_API_CAMERA);
-        if (hw->mPreviewScalingMode != NOT_SET) {
-            native_window_set_scaling_mode(a, hw->mPreviewScalingMode);
-        }
-        if (hw->mPreviewTransform != NOT_SET) {
-            native_window_set_buffers_transform(a, hw->mPreviewTransform);
-        }
-        if (hw->mPreviewWidth != NOT_SET) {
-            native_window_set_buffers_dimensions(a,
-                    hw->mPreviewWidth, hw->mPreviewHeight);
-            native_window_set_buffers_format(a, hw->mPreviewFormat);
-        }
-        if (hw->mPreviewUsage != 0) {
-            native_window_set_usage(a, hw->mPreviewUsage);
-        }
-        if (hw->mPreviewSwapInterval != NOT_SET) {
-            a->setSwapInterval(a, hw->mPreviewSwapInterval);
-        }
-        if (hw->mPreviewCrop.left != NOT_SET) {
-            native_window_set_crop(a, &(hw->mPreviewCrop));
-        }
-    }
-
-    return native_window_set_buffer_count(a, count);
-}
-
-int CameraHardwareInterface::sSetBuffersGeometry(struct preview_stream_ops* w,
-                  int width, int height, int format)
-{
-    int rc;
-    ANativeWindow *a = anw(w);
-    CameraHardwareInterface *hw = hwi(w);
-    hw->mPreviewWidth = width;
-    hw->mPreviewHeight = height;
-    hw->mPreviewFormat = format;
-    rc = native_window_set_buffers_dimensions(a, width, height);
-    if (rc == OK) {
-        rc = native_window_set_buffers_format(a, format);
-    }
-    return rc;
-}
-
-int CameraHardwareInterface::sSetCrop(struct preview_stream_ops *w,
-                  int left, int top, int right, int bottom)
-{
-    ANativeWindow *a = anw(w);
-    CameraHardwareInterface *hw = hwi(w);
-    hw->mPreviewCrop.left = left;
-    hw->mPreviewCrop.top = top;
-    hw->mPreviewCrop.right = right;
-    hw->mPreviewCrop.bottom = bottom;
-    return native_window_set_crop(a, &(hw->mPreviewCrop));
-}
-
-int CameraHardwareInterface::sSetTimestamp(struct preview_stream_ops *w,
-                           int64_t timestamp) {
-    ANativeWindow *a = anw(w);
-    return native_window_set_buffers_timestamp(a, timestamp);
-}
-
-int CameraHardwareInterface::sSetUsage(struct preview_stream_ops* w, int usage)
-{
-    ANativeWindow *a = anw(w);
-    CameraHardwareInterface *hw = hwi(w);
-    hw->mPreviewUsage = usage;
-    return native_window_set_usage(a, usage);
-}
-
-int CameraHardwareInterface::sSetSwapInterval(struct preview_stream_ops *w, int interval)
-{
-    ANativeWindow *a = anw(w);
-    CameraHardwareInterface *hw = hwi(w);
-    hw->mPreviewSwapInterval = interval;
-    return a->setSwapInterval(a, interval);
-}
-
-int CameraHardwareInterface::sGetMinUndequeuedBufferCount(
-                  const struct preview_stream_ops *w,
-                  int *count)
-{
-    ANativeWindow *a = anw(w);
-    return a->query(a, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, count);
-}
-
-void CameraHardwareInterface::initHalPreviewWindow()
-{
-    mHalPreviewWindow.nw.cancel_buffer = sCancelBuffer;
-    mHalPreviewWindow.nw.lock_buffer = sLockBuffer;
-    mHalPreviewWindow.nw.dequeue_buffer = sDequeueBuffer;
-    mHalPreviewWindow.nw.enqueue_buffer = sEnqueueBuffer;
-    mHalPreviewWindow.nw.set_buffer_count = sSetBufferCount;
-    mHalPreviewWindow.nw.set_buffers_geometry = sSetBuffersGeometry;
-    mHalPreviewWindow.nw.set_crop = sSetCrop;
-    mHalPreviewWindow.nw.set_timestamp = sSetTimestamp;
-    mHalPreviewWindow.nw.set_usage = sSetUsage;
-    mHalPreviewWindow.nw.set_swap_interval = sSetSwapInterval;
-
-    mHalPreviewWindow.nw.get_min_undequeued_buffer_count =
-            sGetMinUndequeuedBufferCount;
-}
-
 }; // namespace android
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 2f1e2e9..e519b04 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -90,7 +90,6 @@
 
 public:
     explicit CameraHardwareInterface(const char *name):
-            mDevice(nullptr),
             mHidlDevice(nullptr),
             mName(name),
             mPreviewScalingMode(NOT_SET),
@@ -299,7 +298,6 @@
     status_t dump(int fd, const Vector<String16>& /*args*/) const;
 
 private:
-    camera_device_t *mDevice;
     sp<hardware::camera::device::V1_0::ICameraDevice> mHidlDevice;
     String8 mName;
 
@@ -369,41 +367,6 @@
 
     static void sPutMemory(camera_memory_t *data);
 
-    static ANativeWindow *sToAnw(void *user);
-
-    static int sDequeueBuffer(struct preview_stream_ops* w,
-                                buffer_handle_t** buffer, int *stride);
-
-    static int sLockBuffer(struct preview_stream_ops* w,
-                      buffer_handle_t* /*buffer*/);
-
-    static int sEnqueueBuffer(struct preview_stream_ops* w,
-                      buffer_handle_t* buffer);
-
-    static int sCancelBuffer(struct preview_stream_ops* w,
-                      buffer_handle_t* buffer);
-
-    static int sSetBufferCount(struct preview_stream_ops* w, int count);
-
-    static int sSetBuffersGeometry(struct preview_stream_ops* w,
-                      int width, int height, int format);
-
-    static int sSetCrop(struct preview_stream_ops *w,
-                      int left, int top, int right, int bottom);
-
-    static int sSetTimestamp(struct preview_stream_ops *w,
-                               int64_t timestamp);
-
-    static int sSetUsage(struct preview_stream_ops* w, int usage);
-
-    static int sSetSwapInterval(struct preview_stream_ops *w, int interval);
-
-    static int sGetMinUndequeuedBufferCount(
-                      const struct preview_stream_ops *w,
-                      int *count);
-
-    void initHalPreviewWindow();
-
     std::pair<bool, uint64_t> getBufferId(ANativeWindowBuffer* anb);
     void cleanupCirculatingBuffers();
 
@@ -459,13 +422,6 @@
 
     sp<ANativeWindow>        mPreviewWindow;
 
-    struct camera_preview_window {
-        struct preview_stream_ops nw;
-        void *user;
-    };
-
-    struct camera_preview_window mHalPreviewWindow;
-
     notify_callback               mNotifyCb;
     data_callback                 mDataCb;
     data_callback_timestamp       mDataCbTimestamp;
@@ -479,7 +435,7 @@
     int mPreviewWidth;
     int mPreviewHeight;
     int mPreviewFormat;
-    int mPreviewUsage;
+    uint64_t mPreviewUsage;
     int mPreviewSwapInterval;
     android_native_rect_t mPreviewCrop;
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 69b1d7d..ced1d3a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -154,6 +154,15 @@
                 resultQueueRet.description().c_str());
         return DEAD_OBJECT;
     }
+    IF_ALOGV() {
+        session->interfaceChain([](
+            ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+                ALOGV("Session interface chain:");
+                for (auto iface : interfaceChain) {
+                    ALOGV("  %s", iface.c_str());
+                }
+            });
+    }
 
     mInterface = new HalInterface(session, queue);
     std::string providerType;
@@ -407,7 +416,7 @@
 }
 
 BufferUsageFlags Camera3Device::mapToConsumerUsage(
-        uint32_t usage) {
+        uint64_t usage) {
     return usage;
 }
 
@@ -460,12 +469,17 @@
     return static_cast<uint32_t>(pixelFormat);
 }
 
-uint32_t Camera3Device::mapConsumerToFrameworkUsage(
+android_dataspace Camera3Device::mapToFrameworkDataspace(
+        DataspaceFlags dataSpace) {
+    return static_cast<android_dataspace>(dataSpace);
+}
+
+uint64_t Camera3Device::mapConsumerToFrameworkUsage(
         BufferUsageFlags usage) {
     return usage;
 }
 
-uint32_t Camera3Device::mapProducerToFrameworkUsage(
+uint64_t Camera3Device::mapProducerToFrameworkUsage(
         BufferUsageFlags usage) {
     return usage;
 }
@@ -1208,7 +1222,7 @@
 status_t Camera3Device::createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
-            int streamSetId, bool isShared, uint32_t consumerUsage) {
+            int streamSetId, bool isShared, uint64_t consumerUsage) {
     ATRACE_CALL();
 
     if (consumer == nullptr) {
@@ -1226,13 +1240,13 @@
 status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
         bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
         android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
-        int streamSetId, bool isShared, uint32_t consumerUsage) {
+        int streamSetId, bool isShared, uint64_t consumerUsage) {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
     Mutex::Autolock l(mLock);
     ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
-            " consumer usage 0x%x, isShared %d", mId.string(), mNextStreamId, width, height, format,
+            " consumer usage %" PRIu64 ", isShared %d", mId.string(), mNextStreamId, width, height, format,
             dataSpace, rotation, consumerUsage, isShared);
 
     status_t res;
@@ -1345,10 +1359,11 @@
     return OK;
 }
 
-status_t Camera3Device::getStreamInfo(int id,
-        uint32_t *width, uint32_t *height,
-        uint32_t *format, android_dataspace *dataSpace) {
+status_t Camera3Device::getStreamInfo(int id, StreamInfo *streamInfo) {
     ATRACE_CALL();
+    if (nullptr == streamInfo) {
+        return BAD_VALUE;
+    }
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
@@ -1375,10 +1390,14 @@
         return idx;
     }
 
-    if (width) *width  = mOutputStreams[idx]->getWidth();
-    if (height) *height = mOutputStreams[idx]->getHeight();
-    if (format) *format = mOutputStreams[idx]->getFormat();
-    if (dataSpace) *dataSpace = mOutputStreams[idx]->getDataSpace();
+    streamInfo->width  = mOutputStreams[idx]->getWidth();
+    streamInfo->height = mOutputStreams[idx]->getHeight();
+    streamInfo->format = mOutputStreams[idx]->getFormat();
+    streamInfo->dataSpace = mOutputStreams[idx]->getDataSpace();
+    streamInfo->formatOverridden = mOutputStreams[idx]->isFormatOverridden();
+    streamInfo->originalFormat = mOutputStreams[idx]->getOriginalFormat();
+    streamInfo->dataSpaceOverridden = mOutputStreams[idx]->isDataSpaceOverridden();
+    streamInfo->originalDataSpace = mOutputStreams[idx]->getOriginalDataSpace();
     return OK;
 }
 
@@ -1478,6 +1497,7 @@
 
 status_t Camera3Device::getInputBufferProducer(
         sp<IGraphicBufferProducer> *producer) {
+    ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
@@ -1691,6 +1711,7 @@
 }
 
 status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
+    ATRACE_CALL();
     status_t res;
     Mutex::Autolock l(mOutputLock);
 
@@ -1884,6 +1905,7 @@
  */
 
 void Camera3Device::notifyStatus(bool idle) {
+    ATRACE_CALL();
     {
         // Need mLock to safely update state and synchronize to current
         // state of methods in flight.
@@ -2317,6 +2339,7 @@
 }
 
 void Camera3Device::setErrorState(const char *fmt, ...) {
+    ATRACE_CALL();
     Mutex::Autolock l(mLock);
     va_list args;
     va_start(args, fmt);
@@ -2327,6 +2350,7 @@
 }
 
 void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
+    ATRACE_CALL();
     Mutex::Autolock l(mLock);
     setErrorStateLockedV(fmt, args);
 }
@@ -2411,6 +2435,7 @@
 }
 
 void Camera3Device::removeInFlightMapEntryLocked(int idx) {
+    ATRACE_CALL();
     nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
     mInFlightMap.removeItemsAt(idx, 1);
 
@@ -2433,25 +2458,6 @@
     nsecs_t sensorTimestamp = request.sensorTimestamp;
     nsecs_t shutterTimestamp = request.shutterTimestamp;
 
-    bool skipResultMetadata = false;
-    if (request.requestStatus != OK) {
-        switch (request.requestStatus) {
-            case CAMERA3_MSG_ERROR_DEVICE:
-            case CAMERA3_MSG_ERROR_REQUEST:
-            case CAMERA3_MSG_ERROR_RESULT:
-                skipResultMetadata = true;
-                break;
-            case CAMERA3_MSG_ERROR_BUFFER:
-                //Result metadata should return in this case.
-                skipResultMetadata = false;
-                break;
-            default:
-                SET_ERR("Unknown error message: %d", request.requestStatus);
-                skipResultMetadata = false;
-                break;
-        }
-    }
-
     // Check if it's okay to remove the request from InFlightMap:
     // In the case of a successful request:
     //      all input and output buffers, all result metadata, shutter callback
@@ -2459,7 +2465,7 @@
     // In the case of a unsuccessful request:
     //      all input and output buffers arrived.
     if (request.numBuffersLeft == 0 &&
-            (skipResultMetadata ||
+            (request.skipResultMetadata ||
             (request.haveResultMetadata && shutterTimestamp != 0))) {
         ATRACE_ASYNC_END("frame capture", frameNumber);
 
@@ -2495,6 +2501,7 @@
 }
 
 void Camera3Device::flushInflightRequests() {
+    ATRACE_CALL();
     { // First return buffers cached in mInFlightMap
         Mutex::Autolock l(mInFlightLock);
         for (size_t idx = 0; idx < mInFlightMap.size(); idx++) {
@@ -2621,6 +2628,7 @@
 
 void Camera3Device::sendPartialCaptureResult(const camera_metadata_t * partialResult,
         const CaptureResultExtras &resultExtras, uint32_t frameNumber) {
+    ATRACE_CALL();
     Mutex::Autolock l(mOutputLock);
 
     CaptureResult captureResult;
@@ -2636,6 +2644,7 @@
         CameraMetadata &collectedPartialResult,
         uint32_t frameNumber,
         bool reprocess) {
+    ATRACE_CALL();
     if (pendingMetadata.isEmpty())
         return;
 
@@ -2884,7 +2893,7 @@
 
 void Camera3Device::notifyError(const camera3_error_msg_t &msg,
         sp<NotificationListener> listener) {
-
+    ATRACE_CALL();
     // Map camera HAL error codes to ICameraDeviceCallback error codes
     // Index into this with the HAL error code
     static const int32_t halErrorMap[CAMERA3_MSG_NUM_ERRORS] = {
@@ -2932,6 +2941,11 @@
                     InFlightRequest &r = mInFlightMap.editValueAt(idx);
                     r.requestStatus = msg.error_code;
                     resultExtras = r.resultExtras;
+                    if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT == errorCode
+                            ||  hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST ==
+                            errorCode) {
+                        r.skipResultMetadata = true;
+                    }
                     if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT ==
                             errorCode) {
                         // In case of missing result check whether the buffers
@@ -2962,6 +2976,7 @@
 
 void Camera3Device::notifyShutter(const camera3_shutter_msg_t &msg,
         sp<NotificationListener> listener) {
+    ATRACE_CALL();
     ssize_t idx;
 
     // Set timestamp for the request in the in-flight tracking
@@ -3048,24 +3063,20 @@
 Camera3Device::HalInterface::HalInterface(
             sp<ICameraDeviceSession> &session,
             std::shared_ptr<RequestMetadataQueue> queue) :
-        mHal3Device(nullptr),
         mHidlSession(session),
         mRequestMetadataQueue(queue) {}
 
-Camera3Device::HalInterface::HalInterface() :
-        mHal3Device(nullptr) {}
+Camera3Device::HalInterface::HalInterface() {}
 
 Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
-        mHal3Device(other.mHal3Device),
         mHidlSession(other.mHidlSession),
         mRequestMetadataQueue(other.mRequestMetadataQueue) {}
 
 bool Camera3Device::HalInterface::valid() {
-    return (mHal3Device != nullptr) || (mHidlSession != nullptr);
+    return (mHidlSession != nullptr);
 }
 
 void Camera3Device::HalInterface::clear() {
-    mHal3Device = nullptr;
     mHidlSession.clear();
 }
 
@@ -3080,72 +3091,60 @@
     if (!valid()) return INVALID_OPERATION;
     status_t res = OK;
 
-    if (mHal3Device != nullptr) {
-        const camera_metadata *r;
-        r = mHal3Device->ops->construct_default_request_settings(
-                mHal3Device, templateId);
-        if (r == nullptr) return BAD_VALUE;
-        *requestTemplate = clone_camera_metadata(r);
-        if (requestTemplate == nullptr) {
-            ALOGE("%s: Unable to clone camera metadata received from HAL",
-                    __FUNCTION__);
-            return INVALID_OPERATION;
-        }
-    } else {
-        common::V1_0::Status status;
-        RequestTemplate id;
-        switch (templateId) {
-            case CAMERA3_TEMPLATE_PREVIEW:
-                id = RequestTemplate::PREVIEW;
-                break;
-            case CAMERA3_TEMPLATE_STILL_CAPTURE:
-                id = RequestTemplate::STILL_CAPTURE;
-                break;
-            case CAMERA3_TEMPLATE_VIDEO_RECORD:
-                id = RequestTemplate::VIDEO_RECORD;
-                break;
-            case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
-                id = RequestTemplate::VIDEO_SNAPSHOT;
-                break;
-            case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
-                id = RequestTemplate::ZERO_SHUTTER_LAG;
-                break;
-            case CAMERA3_TEMPLATE_MANUAL:
-                id = RequestTemplate::MANUAL;
-                break;
-            default:
-                // Unknown template ID
-                return BAD_VALUE;
-        }
-        auto err = mHidlSession->constructDefaultRequestSettings(id,
-                [&status, &requestTemplate]
-                (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
-                    status = s;
-                    if (status == common::V1_0::Status::OK) {
-                        const camera_metadata *r =
-                                reinterpret_cast<const camera_metadata_t*>(request.data());
-                        size_t expectedSize = request.size();
-                        int ret = validate_camera_metadata_structure(r, &expectedSize);
-                        if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
-                            *requestTemplate = clone_camera_metadata(r);
-                            if (*requestTemplate == nullptr) {
-                                ALOGE("%s: Unable to clone camera metadata received from HAL",
-                                        __FUNCTION__);
-                                status = common::V1_0::Status::INTERNAL_ERROR;
-                            }
-                        } else {
-                            ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+    common::V1_0::Status status;
+    RequestTemplate id;
+    switch (templateId) {
+        case CAMERA3_TEMPLATE_PREVIEW:
+            id = RequestTemplate::PREVIEW;
+            break;
+        case CAMERA3_TEMPLATE_STILL_CAPTURE:
+            id = RequestTemplate::STILL_CAPTURE;
+            break;
+        case CAMERA3_TEMPLATE_VIDEO_RECORD:
+            id = RequestTemplate::VIDEO_RECORD;
+            break;
+        case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
+            id = RequestTemplate::VIDEO_SNAPSHOT;
+            break;
+        case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+            id = RequestTemplate::ZERO_SHUTTER_LAG;
+            break;
+        case CAMERA3_TEMPLATE_MANUAL:
+            id = RequestTemplate::MANUAL;
+            break;
+        default:
+            // Unknown template ID
+            return BAD_VALUE;
+    }
+    auto err = mHidlSession->constructDefaultRequestSettings(id,
+            [&status, &requestTemplate]
+            (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
+                status = s;
+                if (status == common::V1_0::Status::OK) {
+                    const camera_metadata *r =
+                            reinterpret_cast<const camera_metadata_t*>(request.data());
+                    size_t expectedSize = request.size();
+                    int ret = validate_camera_metadata_structure(r, &expectedSize);
+                    if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
+                        *requestTemplate = clone_camera_metadata(r);
+                        if (*requestTemplate == nullptr) {
+                            ALOGE("%s: Unable to clone camera metadata received from HAL",
+                                    __FUNCTION__);
                             status = common::V1_0::Status::INTERNAL_ERROR;
                         }
+                    } else {
+                        ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+                        status = common::V1_0::Status::INTERNAL_ERROR;
                     }
-                });
-        if (!err.isOk()) {
-            ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
-            res = DEAD_OBJECT;
-        } else {
-            res = CameraProviderManager::mapToStatusT(status);
-        }
+                }
+            });
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+        res = DEAD_OBJECT;
+    } else {
+        res = CameraProviderManager::mapToStatusT(status);
     }
+
     return res;
 }
 
@@ -3154,145 +3153,191 @@
     if (!valid()) return INVALID_OPERATION;
     status_t res = OK;
 
-    if (mHal3Device != nullptr) {
-        res = mHal3Device->ops->configure_streams(mHal3Device, config);
+    // Convert stream config to HIDL
+    std::set<int> activeStreams;
+    StreamConfiguration requestedConfiguration;
+    requestedConfiguration.streams.resize(config->num_streams);
+    for (size_t i = 0; i < config->num_streams; i++) {
+        Stream &dst = requestedConfiguration.streams[i];
+        camera3_stream_t *src = config->streams[i];
+
+        Camera3Stream* cam3stream = Camera3Stream::cast(src);
+        cam3stream->setBufferFreedListener(this);
+        int streamId = cam3stream->getId();
+        StreamType streamType;
+        switch (src->stream_type) {
+            case CAMERA3_STREAM_OUTPUT:
+                streamType = StreamType::OUTPUT;
+                break;
+            case CAMERA3_STREAM_INPUT:
+                streamType = StreamType::INPUT;
+                break;
+            default:
+                ALOGE("%s: Stream %d: Unsupported stream type %d",
+                        __FUNCTION__, streamId, config->streams[i]->stream_type);
+                return BAD_VALUE;
+        }
+        dst.id = streamId;
+        dst.streamType = streamType;
+        dst.width = src->width;
+        dst.height = src->height;
+        dst.format = mapToPixelFormat(src->format);
+        dst.usage = mapToConsumerUsage(cam3stream->getUsage());
+        dst.dataSpace = mapToHidlDataspace(src->data_space);
+        dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+
+        activeStreams.insert(streamId);
+        // Create Buffer ID map if necessary
+        if (mBufferIdMaps.count(streamId) == 0) {
+            mBufferIdMaps.emplace(streamId, BufferIdMap{});
+        }
+    }
+    // remove BufferIdMap for deleted streams
+    for(auto it = mBufferIdMaps.begin(); it != mBufferIdMaps.end();) {
+        int streamId = it->first;
+        bool active = activeStreams.count(streamId) > 0;
+        if (!active) {
+            it = mBufferIdMaps.erase(it);
+        } else {
+            ++it;
+        }
+    }
+
+    res = mapToStreamConfigurationMode(
+            (camera3_stream_configuration_mode_t) config->operation_mode,
+            /*out*/ &requestedConfiguration.operationMode);
+    if (res != OK) {
+        return res;
+    }
+
+    // Invoke configureStreams
+
+    device::V3_3::HalStreamConfiguration finalConfiguration;
+    common::V1_0::Status status;
+
+    // See if we have v3.3 HAL
+    sp<device::V3_3::ICameraDeviceSession> hidlSession_3_3;
+    auto castResult = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
+    if (castResult.isOk()) {
+        hidlSession_3_3 = castResult;
     } else {
-        // Convert stream config to HIDL
-        std::set<int> activeStreams;
-        StreamConfiguration requestedConfiguration;
-        requestedConfiguration.streams.resize(config->num_streams);
-        for (size_t i = 0; i < config->num_streams; i++) {
-            Stream &dst = requestedConfiguration.streams[i];
-            camera3_stream_t *src = config->streams[i];
-
-            Camera3Stream* cam3stream = Camera3Stream::cast(src);
-            cam3stream->setBufferFreedListener(this);
-            int streamId = cam3stream->getId();
-            StreamType streamType;
-            switch (src->stream_type) {
-                case CAMERA3_STREAM_OUTPUT:
-                    streamType = StreamType::OUTPUT;
-                    break;
-                case CAMERA3_STREAM_INPUT:
-                    streamType = StreamType::INPUT;
-                    break;
-                default:
-                    ALOGE("%s: Stream %d: Unsupported stream type %d",
-                            __FUNCTION__, streamId, config->streams[i]->stream_type);
-                    return BAD_VALUE;
-            }
-            dst.id = streamId;
-            dst.streamType = streamType;
-            dst.width = src->width;
-            dst.height = src->height;
-            dst.format = mapToPixelFormat(src->format);
-            dst.usage = mapToConsumerUsage(src->usage);
-            dst.dataSpace = mapToHidlDataspace(src->data_space);
-            dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
-
-            activeStreams.insert(streamId);
-            // Create Buffer ID map if necessary
-            if (mBufferIdMaps.count(streamId) == 0) {
-                mBufferIdMaps.emplace(streamId, BufferIdMap{});
-            }
+        ALOGE("%s: Transaction error when casting ICameraDeviceSession: %s", __FUNCTION__,
+                castResult.description().c_str());
+    }
+    if (hidlSession_3_3 != nullptr) {
+        // We do; use v3.3 for the call
+        ALOGV("%s: v3.3 device found", __FUNCTION__);
+        auto err = hidlSession_3_3->configureStreams_3_3(requestedConfiguration,
+            [&status, &finalConfiguration]
+            (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
+                finalConfiguration = halConfiguration;
+                status = s;
+            });
+        if (!err.isOk()) {
+            ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+            return DEAD_OBJECT;
         }
-        // remove BufferIdMap for deleted streams
-        for(auto it = mBufferIdMaps.begin(); it != mBufferIdMaps.end();) {
-            int streamId = it->first;
-            bool active = activeStreams.count(streamId) > 0;
-            if (!active) {
-                it = mBufferIdMaps.erase(it);
-            } else {
-                ++it;
-            }
-        }
-
-        res = mapToStreamConfigurationMode(
-                (camera3_stream_configuration_mode_t) config->operation_mode,
-                /*out*/ &requestedConfiguration.operationMode);
-        if (res != OK) {
-            return res;
-        }
-
-        // Invoke configureStreams
-
-        HalStreamConfiguration finalConfiguration;
-        common::V1_0::Status status;
+    } else {
+        // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
+        ALOGV("%s: v3.2 device found", __FUNCTION__);
+        HalStreamConfiguration finalConfiguration_3_2;
         auto err = mHidlSession->configureStreams(requestedConfiguration,
-                [&status, &finalConfiguration]
+                [&status, &finalConfiguration_3_2]
                 (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
-                    finalConfiguration = halConfiguration;
+                    finalConfiguration_3_2 = halConfiguration;
                     status = s;
                 });
         if (!err.isOk()) {
             ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
             return DEAD_OBJECT;
         }
+        finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
+        for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
+            finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
+            finalConfiguration.streams[i].overrideDataSpace =
+                    requestedConfiguration.streams[i].dataSpace;
+        }
+    }
 
-        if (status != common::V1_0::Status::OK ) {
-            return CameraProviderManager::mapToStatusT(status);
+    if (status != common::V1_0::Status::OK ) {
+        return CameraProviderManager::mapToStatusT(status);
+    }
+
+    // And convert output stream configuration from HIDL
+
+    for (size_t i = 0; i < config->num_streams; i++) {
+        camera3_stream_t *dst = config->streams[i];
+        int streamId = Camera3Stream::cast(dst)->getId();
+
+        // Start scan at i, with the assumption that the stream order matches
+        size_t realIdx = i;
+        bool found = false;
+        for (size_t idx = 0; idx < finalConfiguration.streams.size(); idx++) {
+            if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
+                found = true;
+                break;
+            }
+            realIdx = (realIdx >= finalConfiguration.streams.size()) ? 0 : realIdx + 1;
+        }
+        if (!found) {
+            ALOGE("%s: Stream %d not found in stream configuration response from HAL",
+                    __FUNCTION__, streamId);
+            return INVALID_OPERATION;
+        }
+        device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
+
+        Camera3Stream* dstStream = Camera3Stream::cast(dst);
+        dstStream->setFormatOverride(false);
+        dstStream->setDataSpaceOverride(false);
+        int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
+        android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
+
+        if (dst->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+            if (dst->format != overrideFormat) {
+                ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
+                        streamId, dst->format);
+            }
+            if (dst->data_space != overrideDataSpace) {
+                ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
+                        streamId, dst->format);
+            }
+        } else {
+            dstStream->setFormatOverride((dst->format != overrideFormat) ? true : false);
+            dstStream->setDataSpaceOverride((dst->data_space != overrideDataSpace) ? true : false);
+
+            // Override allowed with IMPLEMENTATION_DEFINED
+            dst->format = overrideFormat;
+            dst->data_space = overrideDataSpace;
         }
 
-        // And convert output stream configuration from HIDL
-
-        for (size_t i = 0; i < config->num_streams; i++) {
-            camera3_stream_t *dst = config->streams[i];
-            int streamId = Camera3Stream::cast(dst)->getId();
-
-            // Start scan at i, with the assumption that the stream order matches
-            size_t realIdx = i;
-            bool found = false;
-            for (size_t idx = 0; idx < finalConfiguration.streams.size(); idx++) {
-                if (finalConfiguration.streams[realIdx].id == streamId) {
-                    found = true;
-                    break;
-                }
-                realIdx = (realIdx >= finalConfiguration.streams.size()) ? 0 : realIdx + 1;
-            }
-            if (!found) {
-                ALOGE("%s: Stream %d not found in stream configuration response from HAL",
+        if (dst->stream_type == CAMERA3_STREAM_INPUT) {
+            if (src.v3_2.producerUsage != 0) {
+                ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
                         __FUNCTION__, streamId);
                 return INVALID_OPERATION;
             }
-            HalStream &src = finalConfiguration.streams[realIdx];
-
-            int overrideFormat = mapToFrameworkFormat(src.overrideFormat);
-            if (dst->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
-                if (dst->format != overrideFormat) {
-                    ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
-                            streamId, dst->format);
-                }
-            } else {
-                // Override allowed with IMPLEMENTATION_DEFINED
-                dst->format = overrideFormat;
+            dstStream->setUsage(
+                    mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
+        } else {
+            // OUTPUT
+            if (src.v3_2.consumerUsage != 0) {
+                ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
+                        __FUNCTION__, streamId);
+                return INVALID_OPERATION;
             }
-
-            if (dst->stream_type == CAMERA3_STREAM_INPUT) {
-                if (src.producerUsage != 0) {
-                    ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
-                            __FUNCTION__, streamId);
-                    return INVALID_OPERATION;
-                }
-                dst->usage = mapConsumerToFrameworkUsage(src.consumerUsage);
-            } else {
-                // OUTPUT
-                if (src.consumerUsage != 0) {
-                    ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
-                            __FUNCTION__, streamId);
-                    return INVALID_OPERATION;
-                }
-                dst->usage = mapProducerToFrameworkUsage(src.producerUsage);
-            }
-            dst->max_buffers = src.maxBuffers;
+            dstStream->setUsage(
+                    mapProducerToFrameworkUsage(src.v3_2.producerUsage));
         }
+        dst->max_buffers = src.v3_2.maxBuffers;
     }
+
     return res;
 }
 
 void Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
         /*out*/device::V3_2::CaptureRequest* captureRequest,
         /*out*/std::vector<native_handle_t*>* handlesCreated) {
-
+    ATRACE_CALL();
     if (captureRequest == nullptr || handlesCreated == nullptr) {
         ALOGE("%s: captureRequest (%p) and handlesCreated (%p) must not be null",
                 __FUNCTION__, captureRequest, handlesCreated);
@@ -3441,14 +3486,11 @@
     if (!valid()) return INVALID_OPERATION;
     status_t res = OK;
 
-    if (mHal3Device != nullptr) {
-        res = mHal3Device->ops->process_capture_request(mHal3Device, request);
-    } else {
-        uint32_t numRequestProcessed = 0;
-        std::vector<camera3_capture_request_t*> requests(1);
-        requests[0] = request;
-        res = processBatchCaptureRequests(requests, &numRequestProcessed);
-    }
+    uint32_t numRequestProcessed = 0;
+    std::vector<camera3_capture_request_t*> requests(1);
+    requests[0] = request;
+    res = processBatchCaptureRequests(requests, &numRequestProcessed);
+
     return res;
 }
 
@@ -3457,31 +3499,24 @@
     if (!valid()) return INVALID_OPERATION;
     status_t res = OK;
 
-    if (mHal3Device != nullptr) {
-        res = mHal3Device->ops->flush(mHal3Device);
+    auto err = mHidlSession->flush();
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+        res = DEAD_OBJECT;
     } else {
-        auto err = mHidlSession->flush();
-        if (!err.isOk()) {
-            ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
-            res = DEAD_OBJECT;
-        } else {
-            res = CameraProviderManager::mapToStatusT(err);
-        }
+        res = CameraProviderManager::mapToStatusT(err);
     }
+
     return res;
 }
 
-status_t Camera3Device::HalInterface::dump(int fd) {
+status_t Camera3Device::HalInterface::dump(int /*fd*/) {
     ATRACE_NAME("CameraHal::dump");
     if (!valid()) return INVALID_OPERATION;
-    status_t res = OK;
 
-    if (mHal3Device != nullptr) {
-        mHal3Device->ops->dump(mHal3Device, fd);
-    } else {
-        // Handled by CameraProviderManager::dump
-    }
-    return res;
+    // Handled by CameraProviderManager::dump
+
+    return OK;
 }
 
 status_t Camera3Device::HalInterface::close() {
@@ -3489,15 +3524,12 @@
     if (!valid()) return INVALID_OPERATION;
     status_t res = OK;
 
-    if (mHal3Device != nullptr) {
-        mHal3Device->common.close(&mHal3Device->common);
-    } else {
-        auto err = mHidlSession->close();
-        // Interface will be dead shortly anyway, so don't log errors
-        if (!err.isOk()) {
-            res = DEAD_OBJECT;
-        }
+    auto err = mHidlSession->close();
+    // Interface will be dead shortly anyway, so don't log errors
+    if (!err.isOk()) {
+        res = DEAD_OBJECT;
     }
+
     return res;
 }
 
@@ -3614,11 +3646,13 @@
 
 void Camera3Device::RequestThread::setNotificationListener(
         wp<NotificationListener> listener) {
+    ATRACE_CALL();
     Mutex::Autolock l(mRequestLock);
     mListener = listener;
 }
 
 void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed) {
+    ATRACE_CALL();
     Mutex::Autolock l(mRequestLock);
     mReconfigured = true;
     // Prepare video stream for high speed recording.
@@ -3629,6 +3663,7 @@
         List<sp<CaptureRequest> > &requests,
         /*out*/
         int64_t *lastFrameNumber) {
+    ATRACE_CALL();
     Mutex::Autolock l(mRequestLock);
     for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
             ++it) {
@@ -3651,7 +3686,7 @@
 status_t Camera3Device::RequestThread::queueTrigger(
         RequestTrigger trigger[],
         size_t count) {
-
+    ATRACE_CALL();
     Mutex::Autolock l(mTriggerMutex);
     status_t ret;
 
@@ -3708,6 +3743,7 @@
         const RequestList &requests,
         /*out*/
         int64_t *lastFrameNumber) {
+    ATRACE_CALL();
     Mutex::Autolock l(mRequestLock);
     if (lastFrameNumber != NULL) {
         *lastFrameNumber = mRepeatingLastFrameNumber;
@@ -3734,6 +3770,7 @@
 }
 
 status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
+    ATRACE_CALL();
     Mutex::Autolock l(mRequestLock);
     return clearRepeatingRequestsLocked(lastFrameNumber);
 
@@ -3750,6 +3787,7 @@
 
 status_t Camera3Device::RequestThread::clear(
         /*out*/int64_t *lastFrameNumber) {
+    ATRACE_CALL();
     Mutex::Autolock l(mRequestLock);
     ALOGV("RequestThread::%s:", __FUNCTION__);
 
@@ -3805,6 +3843,7 @@
 }
 
 void Camera3Device::RequestThread::setPaused(bool paused) {
+    ATRACE_CALL();
     Mutex::Autolock l(mPauseLock);
     mDoPause = paused;
     mDoPauseSignal.signal();
@@ -3812,6 +3851,7 @@
 
 status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
         int32_t requestId, nsecs_t timeout) {
+    ATRACE_CALL();
     Mutex::Autolock l(mLatestRequestMutex);
     status_t res;
     while (mLatestRequestId != requestId) {
@@ -3838,6 +3878,7 @@
 }
 
 void Camera3Device::RequestThread::checkAndStopRepeatingRequest() {
+    ATRACE_CALL();
     bool surfaceAbandoned = false;
     int64_t lastFrameNumber = 0;
     sp<NotificationListener> listener;
@@ -3866,6 +3907,7 @@
 }
 
 bool Camera3Device::RequestThread::sendRequestsBatch() {
+    ATRACE_CALL();
     status_t res;
     size_t batchSize = mNextRequests.size();
     std::vector<camera3_capture_request_t*> requests(batchSize);
@@ -4261,6 +4303,7 @@
 }
 
 CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
+    ATRACE_CALL();
     Mutex::Autolock al(mLatestRequestMutex);
 
     ALOGV("RequestThread::%s", __FUNCTION__);
@@ -4270,6 +4313,7 @@
 
 bool Camera3Device::RequestThread::isStreamPending(
         sp<Camera3StreamInterface>& stream) {
+    ATRACE_CALL();
     Mutex::Autolock l(mRequestLock);
 
     for (const auto& nextRequest : mNextRequests) {
@@ -4299,6 +4343,7 @@
 }
 
 nsecs_t Camera3Device::getExpectedInFlightDuration() {
+    ATRACE_CALL();
     Mutex::Autolock al(mInFlightLock);
     return mExpectedInflightDuration > kMinInflightDuration ?
             mExpectedInflightDuration : kMinInflightDuration;
@@ -4370,6 +4415,7 @@
 }
 
 void Camera3Device::RequestThread::waitForNextRequestBatch() {
+    ATRACE_CALL();
     // Optimized a bit for the simple steady-state case (single repeating
     // request), to avoid putting that request in the queue temporarily.
     Mutex::Autolock l(mRequestLock);
@@ -4519,6 +4565,7 @@
 }
 
 bool Camera3Device::RequestThread::waitIfPaused() {
+    ATRACE_CALL();
     status_t res;
     Mutex::Autolock l(mPauseLock);
     while (mDoPause) {
@@ -4543,6 +4590,7 @@
 }
 
 void Camera3Device::RequestThread::unpauseForNewRequests() {
+    ATRACE_CALL();
     // With work to do, mark thread as unpaused.
     // If paused by request (setPaused), don't resume, to avoid
     // extra signaling/waiting overhead to waitUntilPaused
@@ -4574,7 +4622,7 @@
 
 status_t Camera3Device::RequestThread::insertTriggers(
         const sp<CaptureRequest> &request) {
-
+    ATRACE_CALL();
     Mutex::Autolock al(mTriggerMutex);
 
     sp<Camera3Device> parent = mParent.promote();
@@ -4663,6 +4711,7 @@
 
 status_t Camera3Device::RequestThread::removeTriggers(
         const sp<CaptureRequest> &request) {
+    ATRACE_CALL();
     Mutex::Autolock al(mTriggerMutex);
 
     CameraMetadata &metadata = request->mSettings;
@@ -4779,6 +4828,7 @@
 }
 
 status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
+    ATRACE_CALL();
     status_t res;
 
     Mutex::Autolock l(mLock);
@@ -4822,6 +4872,7 @@
 }
 
 status_t Camera3Device::PreparerThread::clear() {
+    ATRACE_CALL();
     Mutex::Autolock l(mLock);
 
     for (const auto& stream : mPendingStreams) {
@@ -4834,6 +4885,7 @@
 }
 
 void Camera3Device::PreparerThread::setNotificationListener(wp<NotificationListener> listener) {
+    ATRACE_CALL();
     Mutex::Autolock l(mLock);
     mListener = listener;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d700e03..fbbbd08 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -30,6 +30,7 @@
 
 #include <android/hardware/camera/device/3.2/ICameraDevice.h>
 #include <android/hardware/camera/device/3.2/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
 #include <fmq/MessageQueue.h>
 #include <hardware/camera3.h>
@@ -117,20 +118,18 @@
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
-            bool isShared = false, uint32_t consumerUsage = 0) override;
+            bool isShared = false, uint64_t consumerUsage = 0) override;
     status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
-            bool isShared = false, uint32_t consumerUsage = 0) override;
+            bool isShared = false, uint64_t consumerUsage = 0) override;
 
     status_t createInputStream(
             uint32_t width, uint32_t height, int format,
             int *id) override;
 
-    status_t getStreamInfo(int id,
-            uint32_t *width, uint32_t *height,
-            uint32_t *format, android_dataspace *dataSpace) override;
+    status_t getStreamInfo(int id, StreamInfo *streamInfo) override;
     status_t setStreamTransform(int id, int transform) override;
 
     status_t deleteStream(int id) override;
@@ -271,7 +270,6 @@
         void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out);
 
       private:
-        camera3_device_t *mHal3Device;
         sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
         std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
 
@@ -590,7 +588,7 @@
     static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
     static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
             android_dataspace dataSpace);
-    static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint32_t usage);
+    static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
     static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
             camera3_stream_rotation_t rotation);
     // Returns a negative error code if the passed-in operation mode is not valid.
@@ -598,9 +596,11 @@
             /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
     static camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status);
     static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
-    static uint32_t mapConsumerToFrameworkUsage(
+    static android_dataspace mapToFrameworkDataspace(
+            hardware::camera::device::V3_2::DataspaceFlags);
+    static uint64_t mapConsumerToFrameworkUsage(
             hardware::camera::device::V3_2::BufferUsageFlags usage);
-    static uint32_t mapProducerToFrameworkUsage(
+    static uint64_t mapProducerToFrameworkUsage(
             hardware::camera::device::V3_2::BufferUsageFlags usage);
 
     struct RequestTrigger {
@@ -886,6 +886,11 @@
         // For auto-exposure modes, equal to 1/(lower end of target FPS range)
         nsecs_t maxExpectedDuration;
 
+        // Whether the result metadata for this request is to be skipped. The
+        // result metadata should be skipped in the case of
+        // REQUEST/RESULT error.
+        bool skipResultMetadata;
+
         // Default constructor needed by KeyedVector
         InFlightRequest() :
                 shutterTimestamp(0),
@@ -895,7 +900,8 @@
                 numBuffersLeft(0),
                 hasInputBuffer(false),
                 hasCallback(true),
-                maxExpectedDuration(kDefaultExpectedDuration) {
+                maxExpectedDuration(kDefaultExpectedDuration),
+                skipResultMetadata(false) {
         }
 
         InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
@@ -908,7 +914,8 @@
                 resultExtras(extras),
                 hasInputBuffer(hasInput),
                 hasCallback(hasAppCallback),
-                maxExpectedDuration(maxDuration) {
+                maxExpectedDuration(maxDuration),
+                skipResultMetadata(false) {
         }
     };
 
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 9c951b7..6e2978f 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -95,7 +95,7 @@
     return OK;
 }
 
-status_t Camera3DummyStream::getEndpointUsage(uint32_t *usage) const {
+status_t Camera3DummyStream::getEndpointUsage(uint64_t *usage) const {
     *usage = DUMMY_USAGE;
     return OK;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 35a6a18..492fb49 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -94,7 +94,7 @@
     static const int DUMMY_FORMAT = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
     static const android_dataspace DUMMY_DATASPACE = HAL_DATASPACE_UNKNOWN;
     static const camera3_stream_rotation_t DUMMY_ROTATION = CAMERA3_STREAM_ROTATION_0;
-    static const uint32_t DUMMY_USAGE = GRALLOC_USAGE_HW_COMPOSER;
+    static const uint64_t DUMMY_USAGE = GRALLOC_USAGE_HW_COMPOSER;
 
     /**
      * Internal Camera3Stream interface
@@ -107,7 +107,7 @@
 
     virtual status_t configureQueueLocked();
 
-    virtual status_t getEndpointUsage(uint32_t *usage) const;
+    virtual status_t getEndpointUsage(uint64_t *usage) const;
 
 }; // class Camera3DummyStream
 
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index 7ad2300..a52422d 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -69,7 +69,7 @@
     (void) args;
     String8 lines;
 
-    uint32_t consumerUsage = 0;
+    uint64_t consumerUsage = 0;
     status_t res = getEndpointUsage(&consumerUsage);
     if (res != OK) consumerUsage = 0;
 
@@ -78,8 +78,8 @@
             camera3_stream::width, camera3_stream::height,
             camera3_stream::format, camera3_stream::data_space);
     lines.appendFormat("      Max size: %zu\n", mMaxSize);
-    lines.appendFormat("      Combined usage: %d, max HAL buffers: %d\n",
-            camera3_stream::usage | consumerUsage, camera3_stream::max_buffers);
+    lines.appendFormat("      Combined usage: %" PRIu64 ", max HAL buffers: %d\n",
+            mUsage | consumerUsage, camera3_stream::max_buffers);
     lines.appendFormat("      Frames produced: %d, last timestamp: %" PRId64 " ns\n",
             mFrameCount, mLastTimestamp);
     lines.appendFormat("      Total buffers: %zu, currently dequeued: %zu\n",
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index 35dda39..2376058 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -85,7 +85,7 @@
 
     virtual size_t   getHandoutInputBufferCountLocked();
 
-    virtual status_t getEndpointUsage(uint32_t *usage) const = 0;
+    virtual status_t getEndpointUsage(uint64_t *usage) const = 0;
 
     status_t getBufferPreconditionCheckLocked() const;
     status_t returnBufferPreconditionCheckLocked() const;
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index ff2dcef..2cb1ea7 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -258,7 +258,7 @@
             camera3_stream::max_buffers : minBufs;
         // TODO: somehow set the total buffer count when producer connects?
 
-        mConsumer = new BufferItemConsumer(consumer, camera3_stream::usage,
+        mConsumer = new BufferItemConsumer(consumer, mUsage,
                                            mTotalBufferCount);
         mConsumer->setName(String8::format("Camera3-InputStream-%d", mId));
 
@@ -284,7 +284,7 @@
     return OK;
 }
 
-status_t Camera3InputStream::getEndpointUsage(uint32_t *usage) const {
+status_t Camera3InputStream::getEndpointUsage(uint64_t *usage) const {
     // Per HAL3 spec, input streams have 0 for their initial usage field.
     *usage = 0;
     return OK;
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 8f5b431..81226f8 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -76,7 +76,7 @@
 
     virtual status_t configureQueueLocked();
 
-    virtual status_t getEndpointUsage(uint32_t *usage) const;
+    virtual status_t getEndpointUsage(uint64_t *usage) const;
 
     /**
      * BufferItemConsumer::BufferFreedListener interface
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index b02cd6a..dcaefe3 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -90,7 +90,7 @@
 
 Camera3OutputStream::Camera3OutputStream(int id,
         uint32_t width, uint32_t height, int format,
-        uint32_t consumerUsage, android_dataspace dataSpace,
+        uint64_t consumerUsage, android_dataspace dataSpace,
         camera3_stream_rotation_t rotation, nsecs_t timestampOffset, int setId) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
                             /*maxSize*/0, format, dataSpace, rotation, setId),
@@ -111,7 +111,8 @@
     // Sanity check for the consumer usage flag.
     if ((consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) == 0 &&
             (consumerUsage & GraphicBuffer::USAGE_HW_COMPOSER) == 0) {
-        ALOGE("%s: Deferred consumer usage flag is illegal (0x%x)!", __FUNCTION__, consumerUsage);
+        ALOGE("%s: Deferred consumer usage flag is illegal %" PRIu64 "!",
+              __FUNCTION__, consumerUsage);
         mState = STATE_ERROR;
     }
 
@@ -127,7 +128,7 @@
                                          int format,
                                          android_dataspace dataSpace,
                                          camera3_stream_rotation_t rotation,
-                                         uint32_t consumerUsage, nsecs_t timestampOffset,
+                                         uint64_t consumerUsage, nsecs_t timestampOffset,
                                          int setId) :
         Camera3IOStreamBase(id, type, width, height,
                             /*maxSize*/0,
@@ -365,10 +366,10 @@
 
     mConsumerName = mConsumer->getConsumerName();
 
-    res = native_window_set_usage(mConsumer.get(), camera3_stream::usage);
+    res = native_window_set_usage(mConsumer.get(), mUsage);
     if (res != OK) {
-        ALOGE("%s: Unable to configure usage %08x for stream %d",
-                __FUNCTION__, camera3_stream::usage, mId);
+        ALOGE("%s: Unable to configure usage %" PRIu64 " for stream %d",
+                __FUNCTION__, mUsage, mId);
         return res;
     }
 
@@ -461,11 +462,11 @@
      * HAL3.2 devices may not support the dynamic buffer registeration.
      */
     if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID) {
-        uint32_t consumerUsage = 0;
+        uint64_t consumerUsage = 0;
         getEndpointUsage(&consumerUsage);
         StreamInfo streamInfo(
                 getId(), getStreamSetId(), getWidth(), getHeight(), getFormat(), getDataSpace(),
-                camera3_stream::usage | consumerUsage, mTotalBufferCount,
+                mUsage | consumerUsage, mTotalBufferCount,
                 /*isConfigured*/true);
         wp<Camera3OutputStream> weakThis(this);
         res = mBufferManager->registerStream(weakThis,
@@ -628,7 +629,7 @@
     return OK;
 }
 
-status_t Camera3OutputStream::getEndpointUsage(uint32_t *usage) const {
+status_t Camera3OutputStream::getEndpointUsage(uint64_t *usage) const {
 
     status_t res;
 
@@ -643,14 +644,12 @@
     return res;
 }
 
-status_t Camera3OutputStream::getEndpointUsageForSurface(uint32_t *usage,
+status_t Camera3OutputStream::getEndpointUsageForSurface(uint64_t *usage,
         const sp<Surface>& surface) const {
     status_t res;
-    int32_t u = 0;
+    uint64_t u = 0;
 
-    res = static_cast<ANativeWindow*>(surface.get())->query(surface.get(),
-            NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u);
-
+    res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(surface.get()), &u);
     // If an opaque output stream's endpoint is ImageReader, add
     // GRALLOC_USAGE_HW_CAMERA_ZSL to the usage so HAL knows it will be used
     // for the ZSL use case.
@@ -670,7 +669,7 @@
 }
 
 bool Camera3OutputStream::isVideoStream() const {
-    uint32_t usage = 0;
+    uint64_t usage = 0;
     status_t res = getEndpointUsage(&usage);
     if (res != OK) {
         ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res);
@@ -813,7 +812,7 @@
 }
 
 bool Camera3OutputStream::isConsumedByHWComposer() const {
-    uint32_t usage = 0;
+    uint64_t usage = 0;
     status_t res = getEndpointUsage(&usage);
     if (res != OK) {
         ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res);
@@ -824,7 +823,7 @@
 }
 
 bool Camera3OutputStream::isConsumedByHWTexture() const {
-    uint32_t usage = 0;
+    uint64_t usage = 0;
     status_t res = getEndpointUsage(&usage);
     if (res != OK) {
         ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 97aa7d4..7023d5d 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -44,7 +44,7 @@
     uint32_t height;
     uint32_t format;
     android_dataspace dataSpace;
-    uint32_t combinedUsage;
+    uint64_t combinedUsage;
     size_t totalBufferCount;
     bool isConfigured;
     explicit StreamInfo(int id = CAMERA3_STREAM_ID_INVALID,
@@ -53,7 +53,7 @@
             uint32_t h = 0,
             uint32_t fmt = 0,
             android_dataspace ds = HAL_DATASPACE_UNKNOWN,
-            uint32_t usage = 0,
+            uint64_t usage = 0,
             size_t bufferCount = 0,
             bool configured = false) :
                 streamId(id),
@@ -101,7 +101,7 @@
      * stream set id needs to be set to support buffer sharing between multiple streams.
      */
     Camera3OutputStream(int id, uint32_t width, uint32_t height, int format,
-            uint32_t consumerUsage, android_dataspace dataSpace,
+            uint64_t consumerUsage, android_dataspace dataSpace,
             camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
@@ -176,7 +176,7 @@
     Camera3OutputStream(int id, camera3_stream_type_t type,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation,
-            uint32_t consumerUsage = 0, nsecs_t timestampOffset = 0,
+            uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
     /**
@@ -191,14 +191,14 @@
 
     virtual status_t disconnectLocked();
 
-    status_t getEndpointUsageForSurface(uint32_t *usage,
+    status_t getEndpointUsageForSurface(uint64_t *usage,
             const sp<Surface>& surface) const;
     status_t configureConsumerQueueLocked();
 
     // Consumer as the output of camera HAL
     sp<Surface> mConsumer;
 
-    uint32_t getPresetConsumerUsage() const { return mConsumerUsage; }
+    uint64_t getPresetConsumerUsage() const { return mConsumerUsage; }
 
     static const nsecs_t       kDequeueBufferTimeout   = 1000000000; // 1 sec
 
@@ -245,7 +245,7 @@
      * Consumer end point usage flag set by the constructor for the deferred
      * consumer case.
      */
-    uint32_t    mConsumerUsage;
+    uint64_t    mConsumerUsage;
 
     /**
      * Internal Camera3Stream interface
@@ -262,7 +262,7 @@
 
     virtual status_t configureQueueLocked();
 
-    virtual status_t getEndpointUsage(uint32_t *usage) const;
+    virtual status_t getEndpointUsage(uint64_t *usage) const;
 
     /**
      * Private methods
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 2ae5660..5051711 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -23,7 +23,7 @@
 Camera3SharedOutputStream::Camera3SharedOutputStream(int id,
         const std::vector<sp<Surface>>& surfaces,
         uint32_t width, uint32_t height, int format,
-        uint32_t consumerUsage, android_dataspace dataSpace,
+        uint64_t consumerUsage, android_dataspace dataSpace,
         camera3_stream_rotation_t rotation,
         nsecs_t timestampOffset, int setId) :
         Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
@@ -41,7 +41,7 @@
 
     mStreamSplitter = new Camera3StreamSplitter();
 
-    uint32_t usage;
+    uint64_t usage;
     getEndpointUsage(&usage);
 
     res = mStreamSplitter->connect(mSurfaces, usage, camera3_stream::max_buffers, &mConsumer);
@@ -191,10 +191,10 @@
     return res;
 }
 
-status_t Camera3SharedOutputStream::getEndpointUsage(uint32_t *usage) const {
+status_t Camera3SharedOutputStream::getEndpointUsage(uint64_t *usage) const {
 
     status_t res = OK;
-    uint32_t u = 0;
+    uint64_t u = 0;
 
     if (mConsumer == nullptr) {
         // Called before shared buffer queue is constructed.
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 7be0940..22bb2fc 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -34,7 +34,7 @@
      */
     Camera3SharedOutputStream(int id, const std::vector<sp<Surface>>& surfaces,
             uint32_t width, uint32_t height, int format,
-            uint32_t consumerUsage, android_dataspace dataSpace,
+            uint64_t consumerUsage, android_dataspace dataSpace,
             camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
@@ -74,7 +74,7 @@
 
     virtual status_t disconnectLocked();
 
-    virtual status_t getEndpointUsage(uint32_t *usage) const;
+    virtual status_t getEndpointUsage(uint64_t *usage) const;
 
 }; // class Camera3SharedOutputStream
 
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 9e6ac79..fbe8f4f 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -56,12 +56,15 @@
     mState(STATE_CONSTRUCTED),
     mStatusId(StatusTracker::NO_STATUS_ID),
     mStreamUnpreparable(true),
+    mUsage(0),
     mOldUsage(0),
     mOldMaxBuffers(0),
     mPrepared(false),
     mPreparedBufferIdx(0),
     mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX),
-    mBufferLimitLatency(kBufferLimitLatencyBinSize) {
+    mBufferLimitLatency(kBufferLimitLatencyBinSize),
+    mFormatOverridden(false),
+    mOriginalFormat(-1) {
 
     camera3_stream::stream_type = type;
     camera3_stream::width = width;
@@ -69,7 +72,6 @@
     camera3_stream::format = format;
     camera3_stream::data_space = dataSpace;
     camera3_stream::rotation = rotation;
-    camera3_stream::usage = 0;
     camera3_stream::max_buffers = 0;
     camera3_stream::priv = NULL;
 
@@ -104,6 +106,40 @@
     return camera3_stream::data_space;
 }
 
+uint64_t Camera3Stream::getUsage() const {
+    return mUsage;
+}
+
+void Camera3Stream::setUsage(uint64_t usage) {
+    mUsage = usage;
+}
+
+void Camera3Stream::setFormatOverride(bool formatOverridden) {
+    mFormatOverridden = formatOverridden;
+    if (formatOverridden) mOriginalFormat = camera3_stream::format;
+}
+
+bool Camera3Stream::isFormatOverridden() const {
+    return mFormatOverridden;
+}
+
+int Camera3Stream::getOriginalFormat() const {
+    return mOriginalFormat;
+}
+
+void Camera3Stream::setDataSpaceOverride(bool dataSpaceOverridden) {
+    mDataSpaceOverridden = dataSpaceOverridden;
+    if (dataSpaceOverridden) mOriginalDataSpace = camera3_stream::data_space;
+}
+
+bool Camera3Stream::isDataSpaceOverridden() const {
+    return mDataSpaceOverridden;
+}
+
+android_dataspace Camera3Stream::getOriginalDataSpace() const {
+    return mOriginalDataSpace;
+}
+
 camera3_stream* Camera3Stream::startConfiguration() {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
@@ -133,10 +169,10 @@
             return NULL;
     }
 
-    mOldUsage = camera3_stream::usage;
+    mOldUsage = mUsage;
     mOldMaxBuffers = camera3_stream::max_buffers;
 
-    res = getEndpointUsage(&(camera3_stream::usage));
+    res = getEndpointUsage(&mUsage);
     if (res != OK) {
         ALOGE("%s: Cannot query consumer endpoint usage!",
                 __FUNCTION__);
@@ -197,7 +233,7 @@
     // Check if the stream configuration is unchanged, and skip reallocation if
     // so. As documented in hardware/camera3.h:configure_streams().
     if (mState == STATE_IN_RECONFIG &&
-            mOldUsage == camera3_stream::usage &&
+            mOldUsage == mUsage &&
             mOldMaxBuffers == camera3_stream::max_buffers) {
         mState = STATE_CONFIGURED;
         return OK;
@@ -243,7 +279,7 @@
             return INVALID_OPERATION;
     }
 
-    camera3_stream::usage = mOldUsage;
+    mUsage = mOldUsage;
     camera3_stream::max_buffers = mOldMaxBuffers;
 
     mState = (mState == STATE_IN_RECONFIG) ? STATE_CONFIGURED : STATE_CONSTRUCTED;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 44fe6b6..6e7912e 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -144,6 +144,14 @@
     uint32_t          getHeight() const;
     int               getFormat() const;
     android_dataspace getDataSpace() const;
+    uint64_t          getUsage() const;
+    void              setUsage(uint64_t usage);
+    void              setFormatOverride(bool formatOverriden);
+    bool              isFormatOverridden() const;
+    int               getOriginalFormat() const;
+    void              setDataSpaceOverride(bool dataSpaceOverriden);
+    bool              isDataSpaceOverridden() const;
+    android_dataspace getOriginalDataSpace() const;
 
     camera3_stream*   asHalStream() override {
         return this;
@@ -459,7 +467,7 @@
 
     // Get the usage flags for the other endpoint, or return
     // INVALID_OPERATION if they cannot be obtained.
-    virtual status_t getEndpointUsage(uint32_t *usage) const = 0;
+    virtual status_t getEndpointUsage(uint64_t *usage) const = 0;
 
     // Return whether the buffer is in the list of outstanding buffers.
     bool isOutstandingBuffer(const camera3_stream_buffer& buffer) const;
@@ -473,8 +481,10 @@
     // prepareNextBuffer called on it.
     bool mStreamUnpreparable;
 
+    uint64_t mUsage;
+
   private:
-    uint32_t mOldUsage;
+    uint64_t mOldUsage;
     uint32_t mOldMaxBuffers;
     Condition mOutputBufferReturnedSignal;
     Condition mInputBufferReturnedSignal;
@@ -510,6 +520,15 @@
     // max_buffers.
     static const int32_t kBufferLimitLatencyBinSize = 33; //in ms
     CameraLatencyHistogram mBufferLimitLatency;
+
+    //Keep track of original format in case it gets overridden
+    bool mFormatOverridden;
+    int mOriginalFormat;
+
+    //Keep track of original dataSpace in case it gets overridden
+    bool mDataSpaceOverridden;
+    android_dataspace mOriginalDataSpace;
+
 }; // class Camera3Stream
 
 }; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 0544a1b..cc9bf8e 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -71,6 +71,12 @@
     virtual uint32_t getHeight() const = 0;
     virtual int      getFormat() const = 0;
     virtual android_dataspace getDataSpace() const = 0;
+    virtual void setFormatOverride(bool formatOverriden) = 0;
+    virtual bool isFormatOverridden() const = 0;
+    virtual int getOriginalFormat() const = 0;
+    virtual void setDataSpaceOverride(bool dataSpaceOverriden) = 0;
+    virtual bool isDataSpaceOverridden() const = 0;
+    virtual android_dataspace getOriginalDataSpace() const = 0;
 
     /**
      * Get a HAL3 handle for the stream, without starting stream configuration.
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 869e93a..a0a50c2 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -39,7 +39,7 @@
 namespace android {
 
 status_t Camera3StreamSplitter::connect(const std::vector<sp<Surface> >& surfaces,
-        uint32_t consumerUsage, size_t halMaxBuffers, sp<Surface>* consumer) {
+        uint64_t consumerUsage, size_t halMaxBuffers, sp<Surface>* consumer) {
     ATRACE_CALL();
     if (consumer == nullptr) {
         SP_LOGE("%s: consumer pointer is NULL", __FUNCTION__);
@@ -195,10 +195,8 @@
 
     // Set dequeueBuffer/attachBuffer timeout if the consumer is not hw composer or hw texture.
     // We need skip these cases as timeout will disable the non-blocking (async) mode.
-    int32_t usage = 0;
-    static_cast<ANativeWindow*>(outputQueue.get())->query(
-            outputQueue.get(),
-            NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
+    uint64_t usage = 0;
+    res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(outputQueue.get()), &usage);
     if (!(usage & (GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_TEXTURE))) {
         outputQueue->setDequeueTimeout(kDequeueBufferTimeout);
     }
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index cc623e0..3b8839e 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -52,7 +52,7 @@
     // Connect to the stream splitter by creating buffer queue and connecting it
     // with output surfaces.
     status_t connect(const std::vector<sp<Surface> >& surfaces,
-            uint32_t consumerUsage, size_t halMaxBuffers,
+            uint64_t consumerUsage, size_t halMaxBuffers,
             sp<Surface>* consumer);
 
     // addOutput adds an output BufferQueue to the splitter. The splitter
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
index 3d54460..ee018c3 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
@@ -38,7 +38,7 @@
 namespace android {
 
 RingBufferConsumer::RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer,
-        uint32_t consumerUsage,
+        uint64_t consumerUsage,
         int bufferCount) :
     ConsumerBase(consumer),
     mBufferCount(bufferCount),
@@ -368,7 +368,7 @@
     return mConsumer->setDefaultBufferFormat(defaultFormat);
 }
 
-status_t RingBufferConsumer::setConsumerUsage(uint32_t usage) {
+status_t RingBufferConsumer::setConsumerUsage(uint64_t usage) {
     Mutex::Autolock _l(mMutex);
     return mConsumer->setConsumerUsageBits(usage);
 }
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h
index 2bafe4a..b737469 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.h
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h
@@ -60,7 +60,7 @@
     // the consumer usage flags passed to the graphics allocator. The
     // bufferCount parameter specifies how many buffers can be pinned for user
     // access at the same time.
-    RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer, uint32_t consumerUsage,
+    RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
             int bufferCount);
 
     virtual ~RingBufferConsumer();
@@ -80,7 +80,7 @@
 
     // setConsumerUsage allows the BufferQueue consumer usage to be
     // set at a later time after construction.
-    status_t setConsumerUsage(uint32_t usage);
+    status_t setConsumerUsage(uint64_t usage);
 
     // Buffer info, minus the graphics buffer/slot itself.
     struct BufferInfo {
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index 876c685..c7f9270 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -29,12 +29,15 @@
 #include <unistd.h>
 
 #include <string.h>
+#include <pwd.h>
 
 #include <cutils/atomic.h>
 #include <cutils/properties.h> // for property_get
 
 #include <utils/misc.h>
 
+#include <android/content/pm/IPackageManagerNative.h>
+
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
@@ -80,27 +83,26 @@
 
 namespace android {
 
+    using namespace android::base;
+    using namespace android::content::pm;
+
 
 
 // summarized records
-// up to 48 sets, each covering an hour -- at least 2 days of coverage
+// up to 36 sets, each covering an hour -- so at least 1.5 days
 // (will be longer if there are hours without any media action)
 static const nsecs_t kNewSetIntervalNs = 3600*(1000*1000*1000ll);
-static const int kMaxRecordSets = 48;
-// individual records kept in memory
-static const int kMaxRecords    = 100;
+static const int kMaxRecordSets = 36;
 
+// individual records kept in memory: age or count
+// age: <= 36 hours (1.5 days)
+// count: hard limit of # records
+// (0 for either of these disables that threshold)
+static const nsecs_t kMaxRecordAgeNs =  36 * 3600 * (1000*1000*1000ll);
+static const int kMaxRecords    = 0;
 
 static const char *kServiceName = "media.metrics";
 
-
-//using android::status_t;
-//using android::OK;
-//using android::BAD_VALUE;
-//using android::NOT_ENOUGH_DATA;
-//using android::Parcel;
-
-
 void MediaAnalyticsService::instantiate() {
     defaultServiceManager()->addService(
             String16(kServiceName), new MediaAnalyticsService());
@@ -110,6 +112,7 @@
 MediaAnalyticsService::SummarizerSet::SummarizerSet() {
     mSummarizers = new List<MetricsSummarizer *>();
 }
+
 MediaAnalyticsService::SummarizerSet::~SummarizerSet() {
     // empty the list
     List<MetricsSummarizer *> *l = mSummarizers;
@@ -153,8 +156,10 @@
 
 MediaAnalyticsService::MediaAnalyticsService()
         : mMaxRecords(kMaxRecords),
+          mMaxRecordAgeNs(kMaxRecordAgeNs),
           mMaxRecordSets(kMaxRecordSets),
-          mNewSetInterval(kNewSetIntervalNs) {
+          mNewSetInterval(kNewSetIntervalNs),
+          mDumpProto(MediaAnalyticsItem::PROTO_V0) {
 
     ALOGD("MediaAnalyticsService created");
     // clear our queues
@@ -167,6 +172,8 @@
     mItemsSubmitted = 0;
     mItemsFinalized = 0;
     mItemsDiscarded = 0;
+    mItemsDiscardedExpire = 0;
+    mItemsDiscardedCount = 0;
 
     mLastSessionID = 0;
     // recover any persistency we set up
@@ -177,8 +184,23 @@
         ALOGD("MediaAnalyticsService destroyed");
 
     // clean out mOpen and mFinalized
+    while (mOpen->size() > 0) {
+        MediaAnalyticsItem * oitem = *(mOpen->begin());
+        mOpen->erase(mOpen->begin());
+        delete oitem;
+        mItemsDiscarded++;
+        mItemsDiscardedCount++;
+    }
     delete mOpen;
     mOpen = NULL;
+
+    while (mFinalized->size() > 0) {
+        MediaAnalyticsItem * oitem = *(mFinalized->begin());
+        mFinalized->erase(mFinalized->begin());
+        delete oitem;
+        mItemsDiscarded++;
+        mItemsDiscardedCount++;
+    }
     delete mFinalized;
     mFinalized = NULL;
 
@@ -200,6 +222,8 @@
 
     // we control these, generally not trusting user input
     nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
+    // round nsecs to seconds
+    now = ((now + 500000000) / 1000000000) * 1000000000;
     item->setTimestamp(now);
     int pid = IPCThreadState::self()->getCallingPid();
     int uid = IPCThreadState::self()->getCallingUid();
@@ -212,13 +236,15 @@
     //
     bool isTrusted = false;
 
+    ALOGV("caller has uid=%d, embedded uid=%d", uid, uid_given);
+
     switch (uid)  {
         case AID_MEDIA:
         case AID_MEDIA_CODEC:
         case AID_MEDIA_EX:
         case AID_MEDIA_DRM:
             // trusted source, only override default values
-                isTrusted = true;
+            isTrusted = true;
             if (uid_given == (-1)) {
                 item->setUid(uid);
             }
@@ -234,6 +260,22 @@
     }
 
 
+    // Overwrite package name and version if the caller was untrusted.
+    if (!isTrusted) {
+      setPkgInfo(item, item->getUid(), true, true);
+    } else if (item->getPkgName().empty()) {
+      // empty, so fill out both parts
+      setPkgInfo(item, item->getUid(), true, true);
+    } else {
+      // trusted, provided a package, do nothing
+    }
+
+    ALOGV("given uid %d; sanitized uid: %d sanitized pkg: %s "
+          "sanitized pkg version: %d",
+          uid_given, item->getUid(),
+          item->getPkgName().c_str(),
+          item->getPkgVersionCode());
+
     mItemsSubmitted++;
 
     // validate the record; we discard if we don't like it
@@ -316,6 +358,7 @@
     return id;
 }
 
+
 status_t MediaAnalyticsService::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 512;
@@ -333,22 +376,41 @@
     }
 
     // crack any parameters
-    bool clear = false;
-    bool summary = false;
-    nsecs_t ts_since = 0;
     String16 summaryOption("-summary");
+    bool summary = false;
+    String16 protoOption("-proto");
     String16 clearOption("-clear");
+    bool clear = false;
     String16 sinceOption("-since");
+    nsecs_t ts_since = 0;
     String16 helpOption("-help");
     String16 onlyOption("-only");
-    const char *only = NULL;
+    AString only;
     int n = args.size();
+
     for (int i = 0; i < n; i++) {
         String8 myarg(args[i]);
         if (args[i] == clearOption) {
             clear = true;
         } else if (args[i] == summaryOption) {
             summary = true;
+        } else if (args[i] == protoOption) {
+            i++;
+            if (i < n) {
+                String8 value(args[i]);
+                int proto = MediaAnalyticsItem::PROTO_V0;       // default to original
+                char *endp;
+                const char *p = value.string();
+                proto = strtol(p, &endp, 10);
+                if (endp != p || *endp == '\0') {
+                    if (proto < MediaAnalyticsItem::PROTO_FIRST) {
+                        proto = MediaAnalyticsItem::PROTO_FIRST;
+                    } else if (proto > MediaAnalyticsItem::PROTO_LAST) {
+                        proto = MediaAnalyticsItem::PROTO_LAST;
+                    }
+                    mDumpProto = proto;
+                }
+            }
         } else if (args[i] == sinceOption) {
             i++;
             if (i < n) {
@@ -368,18 +430,12 @@
             i++;
             if (i < n) {
                 String8 value(args[i]);
-                const char *p = value.string();
-                char *q = strdup(p);
-                if (q != NULL) {
-                    if (only != NULL) {
-                        free((void*)only);
-                    }
-                only = q;
-                }
+                only = value.string();
             }
         } else if (args[i] == helpOption) {
             result.append("Recognized parameters:\n");
             result.append("-help        this help message\n");
+            result.append("-proto X     dump using protocol X (defaults to 1)");
             result.append("-summary     show summary info\n");
             result.append("-clear       clears out saved records\n");
             result.append("-only X      process records for component X\n");
@@ -398,11 +454,11 @@
 
     dumpHeaders(result, ts_since);
 
-    // only want 1, to avoid confusing folks that parse the output
+    // want exactly 1, to avoid confusing folks that parse the output
     if (summary) {
-        dumpSummaries(result, ts_since, only);
+        dumpSummaries(result, ts_since, only.c_str());
     } else {
-        dumpRecent(result, ts_since, only);
+        dumpRecent(result, ts_since, only.c_str());
     }
 
 
@@ -428,6 +484,9 @@
     const size_t SIZE = 512;
     char buffer[SIZE];
 
+    snprintf(buffer, SIZE, "Protocol Version: %d\n", mDumpProto);
+    result.append(buffer);
+
     int enabled = MediaAnalyticsItem::isEnabled();
     if (enabled) {
         snprintf(buffer, SIZE, "Metrics gathering: enabled\n");
@@ -437,10 +496,14 @@
     result.append(buffer);
 
     snprintf(buffer, SIZE,
-        "Since Boot: Submissions: %" PRId64
-            " Finalizations: %" PRId64
-        " Discarded: %" PRId64 "\n",
-        mItemsSubmitted, mItemsFinalized, mItemsDiscarded);
+        "Since Boot: Submissions: %8" PRId64
+            " Finalizations: %8" PRId64 "\n",
+        mItemsSubmitted, mItemsFinalized);
+    result.append(buffer);
+    snprintf(buffer, SIZE,
+        "Records Discarded: %8" PRId64
+            " (by Count: %" PRId64 " by Expiration: %" PRId64 ")\n",
+         mItemsDiscarded, mItemsDiscardedCount, mItemsDiscardedExpire);
     result.append(buffer);
     snprintf(buffer, SIZE,
         "Summary Sets Discarded: %" PRId64 "\n", mSetsDiscarded);
@@ -462,6 +525,10 @@
     snprintf(buffer, SIZE, "\nSummarized Metrics:\n");
     result.append(buffer);
 
+    if (only != NULL && *only == '\0') {
+        only = NULL;
+    }
+
     // have each of the distillers dump records
     if (mSummarizerSets != NULL) {
         List<SummarizerSet *>::iterator itSet = mSummarizerSets->begin();
@@ -488,6 +555,10 @@
     const size_t SIZE = 512;
     char buffer[SIZE];
 
+    if (only != NULL && *only == '\0') {
+        only = NULL;
+    }
+
     // show the recently recorded records
     snprintf(buffer, sizeof(buffer), "\nFinalized Metrics (oldest first):\n");
     result.append(buffer);
@@ -524,7 +595,7 @@
                 ALOGV("Omit '%s', it's not '%s'", (*it)->getKey().c_str(), only);
                 continue;
             }
-            AString entry = (*it)->toString();
+            AString entry = (*it)->toString(mDumpProto);
             result.appendFormat("%5d: %s\n", slot, entry.c_str());
             slot++;
         }
@@ -549,13 +620,32 @@
         l->push_back(item);
     }
 
-    // keep removing old records the front until we're in-bounds
+    // keep removing old records the front until we're in-bounds (count)
     if (mMaxRecords > 0) {
         while (l->size() > (size_t) mMaxRecords) {
             MediaAnalyticsItem * oitem = *(l->begin());
             l->erase(l->begin());
             delete oitem;
             mItemsDiscarded++;
+            mItemsDiscardedCount++;
+        }
+    }
+
+    // keep removing old records the front until we're in-bounds (count)
+    if (mMaxRecordAgeNs > 0) {
+        nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
+        while (l->size() > 0) {
+            MediaAnalyticsItem * oitem = *(l->begin());
+            nsecs_t when = oitem->getTimestamp();
+            // careful about timejumps too
+            if ((now > when) && (now-when) <= mMaxRecordAgeNs) {
+                // this (and the rest) are recent enough to keep
+                break;
+            }
+            l->erase(l->begin());
+            delete oitem;
+            mItemsDiscarded++;
+            mItemsDiscardedExpire++;
         }
     }
 }
@@ -563,11 +653,6 @@
 // are they alike enough that nitem can be folded into oitem?
 static bool compatibleItems(MediaAnalyticsItem * oitem, MediaAnalyticsItem * nitem) {
 
-    if (0) {
-        ALOGD("Compare: o %s n %s",
-              oitem->toString().c_str(), nitem->toString().c_str());
-    }
-
     // general safety
     if (nitem->getUid() != oitem->getUid()) {
         return false;
@@ -718,4 +803,155 @@
 
 }
 
+// how long we hold package info before we re-fetch it
+#define PKG_EXPIRATION_NS (30*60*1000000000ll)   // 30 minutes, in nsecs
+
+// give me the package name, perhaps going to find it
+void MediaAnalyticsService::setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion) {
+    ALOGV("asking for packagename to go with uid=%d", uid);
+
+    if (!setName && !setVersion) {
+        // setting nothing? strange
+        return;
+    }
+
+    nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
+    struct UidToPkgMap mapping;
+    mapping.uid = (-1);
+
+    ssize_t i = mPkgMappings.indexOfKey(uid);
+    if (i >= 0) {
+        mapping = mPkgMappings.valueAt(i);
+        ALOGV("Expiration? uid %d expiration %" PRId64 " now %" PRId64,
+              uid, mapping.expiration, now);
+        if (mapping.expiration < now) {
+            // purge our current entry and re-query
+            ALOGV("entry for uid %d expired, now= %" PRId64 "", uid, now);
+            mPkgMappings.removeItemsAt(i, 1);
+            // could cheat and use a goto back to the top of the routine.
+            // a good compiler should recognize the local tail recursion...
+            return setPkgInfo(item, uid, setName, setVersion);
+        }
+    } else {
+        AString pkg;
+        std::string installer = "";
+        int32_t versionCode = 0;
+
+        struct passwd *pw = getpwuid(uid);
+        if (pw) {
+            pkg = pw->pw_name;
+        }
+
+        // find the proper value -- should we cache this binder??
+
+        sp<IBinder> binder = NULL;
+        sp<IServiceManager> sm = defaultServiceManager();
+        if (sm == NULL) {
+            ALOGE("defaultServiceManager failed");
+        } else {
+            binder = sm->getService(String16("package_native"));
+            if (binder == NULL) {
+                ALOGE("getService package_native failed");
+            }
+        }
+
+        if (binder != NULL) {
+            sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder);
+            binder::Status status;
+
+            std::vector<int> uids;
+            std::vector<std::string> names;
+
+            uids.push_back(uid);
+
+            status = package_mgr->getNamesForUids(uids, &names);
+            if (!status.isOk()) {
+                ALOGE("package_native::getNamesForUids failed: %s",
+                      status.exceptionMessage().c_str());
+            } else {
+                if (!names[0].empty()) {
+                    pkg = names[0].c_str();
+                }
+            }
+
+            // strip any leading "shared:" strings that came back
+            if (pkg.startsWith("shared:")) {
+                pkg.erase(0, 7);
+            }
+
+            // determine how pkg was installed and the versionCode
+            //
+            if (pkg.empty()) {
+                // no name for us to manage
+            } else if (strchr(pkg.c_str(), '.') == NULL) {
+                // not of form 'com.whatever...'; assume internal and ok
+            } else if (strncmp(pkg.c_str(), "android.", 8) == 0) {
+                // android.* packages are assumed fine
+            } else {
+                String16 pkgName16(pkg.c_str());
+                status = package_mgr->getInstallerForPackage(pkgName16, &installer);
+                if (!status.isOk()) {
+                    ALOGE("package_native::getInstallerForPackage failed: %s",
+                          status.exceptionMessage().c_str());
+                }
+
+                // skip if we didn't get an installer
+                if (status.isOk()) {
+                    status = package_mgr->getVersionCodeForPackage(pkgName16, &versionCode);
+                    if (!status.isOk()) {
+                        ALOGE("package_native::getVersionCodeForPackage failed: %s",
+                          status.exceptionMessage().c_str());
+                    }
+                }
+
+
+                ALOGV("package '%s' installed by '%s' versioncode %d / %08x",
+                      pkg.c_str(), installer.c_str(), versionCode, versionCode);
+
+                if (strncmp(installer.c_str(), "com.android.", 12) == 0) {
+                        // from play store, we keep info
+                } else if (strncmp(installer.c_str(), "com.google.", 11) == 0) {
+                        // some google source, we keep info
+                } else if (strcmp(installer.c_str(), "preload") == 0) {
+                        // preloads, we keep the info
+                } else if (installer.c_str()[0] == '\0') {
+                        // sideload (no installer); do not report
+                        pkg = "";
+                        versionCode = 0;
+                } else {
+                        // unknown installer; do not report
+                        pkg = "";
+                        versionCode = 0;
+                }
+            }
+        }
+
+        // add it to the map, to save a subsequent lookup
+        if (!pkg.empty()) {
+            Mutex::Autolock _l(mLock_mappings);
+            ALOGV("Adding uid %d pkg '%s'", uid, pkg.c_str());
+            ssize_t i = mPkgMappings.indexOfKey(uid);
+            if (i < 0) {
+                mapping.uid = uid;
+                mapping.pkg = pkg;
+                mapping.installer = installer.c_str();
+                mapping.versionCode = versionCode;
+                mapping.expiration = now + PKG_EXPIRATION_NS;
+                ALOGV("expiration for uid %d set to %" PRId64 "", uid, mapping.expiration);
+
+                mPkgMappings.add(uid, mapping);
+            }
+        }
+    }
+
+    if (mapping.uid != (uid_t)(-1)) {
+        if (setName) {
+            item->setPkgName(mapping.pkg);
+        }
+        if (setVersion) {
+            item->setPkgVersionCode(mapping.versionCode);
+        }
+    }
+}
+
 } // namespace android
diff --git a/services/mediaanalytics/MediaAnalyticsService.h b/services/mediaanalytics/MediaAnalyticsService.h
index 6685967..52e4631 100644
--- a/services/mediaanalytics/MediaAnalyticsService.h
+++ b/services/mediaanalytics/MediaAnalyticsService.h
@@ -54,16 +54,22 @@
     int64_t mItemsSubmitted;
     int64_t mItemsFinalized;
     int64_t mItemsDiscarded;
+    int64_t mItemsDiscardedExpire;
+    int64_t mItemsDiscardedCount;
     int64_t mSetsDiscarded;
     MediaAnalyticsItem::SessionID_t mLastSessionID;
 
     // partitioned a bit so we don't over serialize
     mutable Mutex           mLock;
     mutable Mutex           mLock_ids;
+    mutable Mutex           mLock_mappings;
 
-    // the most we hold in memory
-    // up to this many in each queue (open, finalized)
+    // limit how many records we'll retain
+    // by count (in each queue (open, finalized))
     int32_t mMaxRecords;
+    // by time (none older than this long agan
+    nsecs_t mMaxRecordAgeNs;
+    //
     // # of sets of summaries
     int32_t mMaxRecordSets;
     // nsecs until we start a new record set
@@ -118,6 +124,7 @@
     void deleteItem(List<MediaAnalyticsItem *> *, MediaAnalyticsItem *);
 
     // support for generating output
+    int mDumpProto;
     String8 dumpQueue(List<MediaAnalyticsItem*> *);
     String8 dumpQueue(List<MediaAnalyticsItem*> *, nsecs_t, const char *only);
 
@@ -125,6 +132,18 @@
     void dumpSummaries(String8 &result, nsecs_t ts_since, const char * only);
     void dumpRecent(String8 &result, nsecs_t ts_since, const char * only);
 
+    // mapping uids to package names
+    struct UidToPkgMap {
+        uid_t uid;
+        AString pkg;
+        AString installer;
+        int32_t versionCode;
+        nsecs_t expiration;
+    };
+
+    KeyedVector<uid_t,struct UidToPkgMap>  mPkgMappings;
+    void setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion);
+
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/mediaanalytics/MetricsSummarizer.cpp b/services/mediaanalytics/MetricsSummarizer.cpp
index 3477f1f..93fe0ec 100644
--- a/services/mediaanalytics/MetricsSummarizer.cpp
+++ b/services/mediaanalytics/MetricsSummarizer.cpp
@@ -141,23 +141,23 @@
     List<MediaAnalyticsItem *>::iterator it = mSummaries->begin();
     for (; it != mSummaries->end(); it++) {
         bool good = sameAttributes((*it), item, getIgnorables());
-        ALOGV("Match against %s says %d",
-              (*it)->toString().c_str(), good);
+        ALOGV("Match against %s says %d", (*it)->toString().c_str(), good);
         if (good)
             break;
     }
     if (it == mSummaries->end()) {
             ALOGV("save new record");
-            item = item->dup();
-            if (item == NULL) {
+            MediaAnalyticsItem *nitem = item->dup();
+            if (nitem == NULL) {
                 ALOGE("unable to save MediaMetrics record");
             }
-            sortProps(item);
-            item->setInt32("count",1);
-            mSummaries->push_back(item);
+            sortProps(nitem);
+            nitem->setInt32("aggregated",1);
+            mergeRecord(*nitem, *item);
+            mSummaries->push_back(nitem);
     } else {
             ALOGV("increment existing record");
-            (*it)->addInt32("count",1);
+            (*it)->addInt32("aggregated",1);
             mergeRecord(*(*it), *item);
     }
 }
@@ -168,6 +168,71 @@
     return;
 }
 
+// keep some stats for things: sums, counts, standard deviation
+// the integer version -- all of these pieces are in 64 bits
+void MetricsSummarizer::minMaxVar64(MediaAnalyticsItem &summation, const char *key, int64_t value) {
+    if (key == NULL)
+        return;
+    int len = strlen(key) + 32;
+    char *tmpKey = (char *)malloc(len);
+
+    if (tmpKey == NULL) {
+        return;
+    }
+
+    // N - count of samples
+    snprintf(tmpKey, len, "%s.n", key);
+    summation.addInt64(tmpKey, 1);
+
+    // zero - count of samples that are zero
+    if (value == 0) {
+        snprintf(tmpKey, len, "%s.zero", key);
+        int64_t zero = 0;
+        (void) summation.getInt64(tmpKey,&zero);
+        zero++;
+        summation.setInt64(tmpKey, zero);
+    }
+
+    // min
+    snprintf(tmpKey, len, "%s.min", key);
+    int64_t min = value;
+    if (summation.getInt64(tmpKey,&min)) {
+        if (min > value) {
+            summation.setInt64(tmpKey, value);
+        }
+    } else {
+        summation.setInt64(tmpKey, value);
+    }
+
+    // max
+    snprintf(tmpKey, len, "%s.max", key);
+    int64_t max = value;
+    if (summation.getInt64(tmpKey,&max)) {
+        if (max < value) {
+            summation.setInt64(tmpKey, value);
+        }
+    } else {
+        summation.setInt64(tmpKey, value);
+    }
+
+    // components for mean, stddev;
+    // stddev = sqrt(1/4*(sumx2 - (2*sumx*sumx/n) + ((sumx/n)^2)))
+    // sum x
+    snprintf(tmpKey, len, "%s.sumX", key);
+    summation.addInt64(tmpKey, value);
+    // sum x^2
+    snprintf(tmpKey, len, "%s.sumX2", key);
+    summation.addInt64(tmpKey, value*value);
+
+
+    // last thing we do -- remove the base key from the summation
+    // record so we won't get confused about it having both individual
+    // and summary information in there.
+    summation.removeProp(key);
+
+    free(tmpKey);
+}
+
 
 //
 // Comparators
@@ -186,20 +251,23 @@
     ALOGV("MetricsSummarizer::sameAttributes(): summ %s", summ->toString().c_str());
     ALOGV("MetricsSummarizer::sameAttributes(): single %s", single->toString().c_str());
 
+    // keep different sources/users separate
+    if (single->mUid != summ->mUid) {
+        return false;
+    }
+
     // this can be made better.
     for(size_t i=0;i<single->mPropCount;i++) {
         MediaAnalyticsItem::Prop *prop1 = &(single->mProps[i]);
         const char *attrName = prop1->mName;
-        ALOGV("compare on attr '%s'", attrName);
 
         // is it something we should ignore
         if (ignorable != NULL) {
             const char **ig = ignorable;
-            while (*ig) {
+            for (;*ig; ig++) {
                 if (strcmp(*ig, attrName) == 0) {
                     break;
                 }
-                ig++;
             }
             if (*ig) {
                 ALOGV("we don't mind that it has attr '%s'", attrName);
@@ -218,29 +286,42 @@
         }
         switch (prop1->mType) {
             case MediaAnalyticsItem::kTypeInt32:
-                if (prop1->u.int32Value != prop2->u.int32Value)
+                if (prop1->u.int32Value != prop2->u.int32Value) {
+                    ALOGV("mismatch values");
                     return false;
+                }
                 break;
             case MediaAnalyticsItem::kTypeInt64:
-                if (prop1->u.int64Value != prop2->u.int64Value)
+                if (prop1->u.int64Value != prop2->u.int64Value) {
+                    ALOGV("mismatch values");
                     return false;
+                }
                 break;
             case MediaAnalyticsItem::kTypeDouble:
                 // XXX: watch out for floating point comparisons!
-                if (prop1->u.doubleValue != prop2->u.doubleValue)
+                if (prop1->u.doubleValue != prop2->u.doubleValue) {
+                    ALOGV("mismatch values");
                     return false;
+                }
                 break;
             case MediaAnalyticsItem::kTypeCString:
-                if (strcmp(prop1->u.CStringValue, prop2->u.CStringValue) != 0)
+                if (strcmp(prop1->u.CStringValue, prop2->u.CStringValue) != 0) {
+                    ALOGV("mismatch values");
                     return false;
+                }
                 break;
             case MediaAnalyticsItem::kTypeRate:
-                if (prop1->u.rate.count != prop2->u.rate.count)
+                if (prop1->u.rate.count != prop2->u.rate.count) {
+                    ALOGV("mismatch values");
                     return false;
-                if (prop1->u.rate.duration != prop2->u.rate.duration)
+                }
+                if (prop1->u.rate.duration != prop2->u.rate.duration) {
+                    ALOGV("mismatch values");
                     return false;
+                }
                 break;
             default:
+                ALOGV("mismatch values in default type");
                 return false;
         }
     }
@@ -248,15 +329,6 @@
     return true;
 }
 
-bool MetricsSummarizer::sameAttributesId(MediaAnalyticsItem *summ, MediaAnalyticsItem *single, const char **ignorable) {
-
-    // verify same user
-    if (summ->mPid != single->mPid)
-        return false;
-
-    // and finally do the more expensive validation of the attributes
-    return sameAttributes(summ, single, ignorable);
-}
 
 int MetricsSummarizer::PropSorter(const void *a, const void *b) {
     MediaAnalyticsItem::Prop *ai = (MediaAnalyticsItem::Prop *)a;
@@ -267,14 +339,8 @@
 // we sort in the summaries so that it looks pretty in the dumpsys
 void MetricsSummarizer::sortProps(MediaAnalyticsItem *item) {
     if (item->mPropCount != 0) {
-        if (DEBUG_SORT) {
-            ALOGD("sortProps(pre): %s", item->toString().c_str());
-        }
         qsort(item->mProps, item->mPropCount,
               sizeof(MediaAnalyticsItem::Prop), MetricsSummarizer::PropSorter);
-        if (DEBUG_SORT) {
-            ALOGD("sortProps(pst): %s", item->toString().c_str());
-        }
     }
 }
 
diff --git a/services/mediaanalytics/MetricsSummarizer.h b/services/mediaanalytics/MetricsSummarizer.h
index 0b64eac..a9f0786 100644
--- a/services/mediaanalytics/MetricsSummarizer.h
+++ b/services/mediaanalytics/MetricsSummarizer.h
@@ -59,10 +59,9 @@
 
     // various comparators
     // "do these records have same attributes and values in those attrs"
-    // ditto, but watch for "error" fields
     bool sameAttributes(MediaAnalyticsItem *summ, MediaAnalyticsItem *single, const char **ignoreables);
-    // attributes + from the same app/userid
-    bool sameAttributesId(MediaAnalyticsItem *summ, MediaAnalyticsItem *single, const char **ignoreables);
+
+    void minMaxVar64(MediaAnalyticsItem &summ, const char *key, int64_t value);
 
     static int PropSorter(const void *a, const void *b);
     void sortProps(MediaAnalyticsItem *item);
diff --git a/services/mediaanalytics/MetricsSummarizerCodec.cpp b/services/mediaanalytics/MetricsSummarizerCodec.cpp
index 8c74782..6af3c9a 100644
--- a/services/mediaanalytics/MetricsSummarizerCodec.cpp
+++ b/services/mediaanalytics/MetricsSummarizerCodec.cpp
@@ -17,6 +17,8 @@
 #define LOG_TAG "MetricsSummarizerCodec"
 #include <utils/Log.h>
 
+#include <stdint.h>
+#include <inttypes.h>
 
 #include <utils/threads.h>
 #include <utils/Errors.h>
@@ -40,5 +42,4 @@
     ALOGV("MetricsSummarizerCodec::MetricsSummarizerCodec");
 }
 
-
 } // namespace android
diff --git a/services/mediaanalytics/MetricsSummarizerPlayer.cpp b/services/mediaanalytics/MetricsSummarizerPlayer.cpp
index 5162059..f882cb9 100644
--- a/services/mediaanalytics/MetricsSummarizerPlayer.cpp
+++ b/services/mediaanalytics/MetricsSummarizerPlayer.cpp
@@ -51,37 +51,43 @@
     setIgnorables(player_ignorable);
 }
 
+// NB: this is also called for the first time -- so summation == item
+// Not sure if we need a flag for that or not.
+// In this particular mergeRecord() code -- we're' ok for this.
 void MetricsSummarizerPlayer::mergeRecord(MediaAnalyticsItem &summation, MediaAnalyticsItem &item) {
 
     ALOGV("MetricsSummarizerPlayer::mergeRecord()");
 
-    //
-    // we sum time & frames.
-    // be careful about our special "-1" values that indicate 'unknown'
-    // treat those as 0 [basically, not summing them into the totals].
+
     int64_t duration = 0;
     if (item.getInt64("android.media.mediaplayer.durationMs", &duration)) {
         ALOGV("found durationMs of %" PRId64, duration);
-        summation.addInt64("android.media.mediaplayer.durationMs",duration);
+        minMaxVar64(summation, "android.media.mediaplayer.durationMs", duration);
     }
+
     int64_t playing = 0;
-    if (item.getInt64("android.media.mediaplayer.playingMs", &playing))
+    if (item.getInt64("android.media.mediaplayer.playingMs", &playing)) {
         ALOGV("found playingMs of %" PRId64, playing);
-        if (playing >= 0) {
-            summation.addInt64("android.media.mediaplayer.playingMs",playing);
-        }
+    }
+    if (playing >= 0) {
+        minMaxVar64(summation,"android.media.mediaplayer.playingMs",playing);
+    }
+
     int64_t frames = 0;
-    if (item.getInt64("android.media.mediaplayer.frames", &frames))
+    if (item.getInt64("android.media.mediaplayer.frames", &frames)) {
         ALOGV("found framess of %" PRId64, frames);
-        if (frames >= 0) {
-            summation.addInt64("android.media.mediaplayer.frames",frames);
-        }
+    }
+    if (frames >= 0) {
+        minMaxVar64(summation,"android.media.mediaplayer.frames",frames);
+    }
+
     int64_t dropped = 0;
-    if (item.getInt64("android.media.mediaplayer.dropped", &dropped))
+    if (item.getInt64("android.media.mediaplayer.dropped", &dropped)) {
         ALOGV("found dropped of %" PRId64, dropped);
-        if (dropped >= 0) {
-            summation.addInt64("android.media.mediaplayer.dropped",dropped);
-        }
+    }
+    if (dropped >= 0) {
+        minMaxVar64(summation,"android.media.mediaplayer.dropped",dropped);
+    }
 }
 
 } // namespace android
diff --git a/services/mediaanalytics/mediametrics.rc b/services/mediaanalytics/mediametrics.rc
index 3829f8c..1efde5e 100644
--- a/services/mediaanalytics/mediametrics.rc
+++ b/services/mediaanalytics/mediametrics.rc
@@ -1,5 +1,6 @@
 service mediametrics /system/bin/mediametrics
     class main
     user media
+    group media
     ioprio rt 4
     writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 6997b5a..faeb0a7 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -9,13 +9,8 @@
     libgui \
     libutils \
     liblog \
-    libstagefright_omx
-LOCAL_C_INCLUDES := \
-    frameworks/av/include \
-    frameworks/av/media/libstagefright \
-    frameworks/av/media/libstagefright/include \
-    frameworks/native/include \
-    frameworks/native/include/media/openmax
+    libstagefright_omx \
+    libstagefright_xmlparser
 LOCAL_MODULE:= libmediacodecservice
 LOCAL_VENDOR_MODULE := true
 LOCAL_32_BIT_ONLY := true
@@ -38,15 +33,10 @@
     libhwbinder \
     libhidltransport \
     libstagefright_omx \
+    libstagefright_xmlparser \
     android.hardware.media.omx@1.0 \
     android.hidl.memory@1.0
 
-LOCAL_C_INCLUDES := \
-    frameworks/av/include \
-    frameworks/av/media/libstagefright \
-    frameworks/av/media/libstagefright/include \
-    frameworks/native/include \
-    frameworks/native/include/media/openmax
 LOCAL_MODULE := android.hardware.media.omx@1.0-service
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_VENDOR_MODULE := true
diff --git a/services/mediacodec/MediaCodecService.cpp b/services/mediacodec/MediaCodecService.cpp
index fc1e5d9..6b510c6 100644
--- a/services/mediacodec/MediaCodecService.cpp
+++ b/services/mediacodec/MediaCodecService.cpp
@@ -24,15 +24,25 @@
 
 sp<IOMX> MediaCodecService::getOMX() {
 
-    Mutex::Autolock autoLock(mLock);
+    Mutex::Autolock autoLock(mOMXLock);
 
     if (mOMX.get() == NULL) {
-        mOMX = new OMX;
+        mOMX = new OMX();
     }
 
     return mOMX;
 }
 
+sp<IOMXStore> MediaCodecService::getOMXStore() {
+
+    Mutex::Autolock autoLock(mOMXStoreLock);
+
+    if (mOMXStore.get() == NULL) {
+        mOMXStore = new OMXStore();
+    }
+
+    return mOMXStore;
+}
 
 status_t MediaCodecService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
         uint32_t flags)
diff --git a/services/mediacodec/MediaCodecService.h b/services/mediacodec/MediaCodecService.h
index d64debb..9301135 100644
--- a/services/mediacodec/MediaCodecService.h
+++ b/services/mediacodec/MediaCodecService.h
@@ -19,11 +19,13 @@
 
 #include <binder/BinderService.h>
 #include <media/IMediaCodecService.h>
-#include <include/OMX.h>
+#include <media/stagefright/omx/OMX.h>
+#include <media/stagefright/omx/OMXStore.h>
 
 namespace android {
 
-class MediaCodecService : public BinderService<MediaCodecService>, public BnMediaCodecService
+class MediaCodecService : public BinderService<MediaCodecService>,
+        public BnMediaCodecService
 {
     friend class BinderService<MediaCodecService>;    // for MediaCodecService()
 public:
@@ -31,16 +33,20 @@
     virtual ~MediaCodecService() { }
     virtual void onFirstRef() { }
 
-    static const char*  getServiceName() { return "media.codec"; }
+    static const char*    getServiceName() { return "media.codec"; }
 
-    virtual sp<IOMX>    getOMX();
+    virtual sp<IOMX>      getOMX();
 
-    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-                                uint32_t flags);
+    virtual sp<IOMXStore> getOMXStore();
+
+    virtual status_t      onTransact(uint32_t code, const Parcel& data,
+                                     Parcel* reply, uint32_t flags);
 
 private:
-    Mutex               mLock;
-    sp<IOMX>            mOMX;
+    Mutex                 mOMXLock;
+    sp<IOMX>              mOMX;
+    Mutex                 mOMXStoreLock;
+    sp<IOMXStore>         mOMXStore;
 };
 
 }   // namespace android
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index c59944a..79d6da5 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -32,8 +32,8 @@
 #include "minijail.h"
 
 #include <hidl/HidlTransportSupport.h>
-#include <omx/1.0/Omx.h>
-#include <omx/1.0/OmxStore.h>
+#include <media/stagefright/omx/1.0/Omx.h>
+#include <media/stagefright/omx/1.0/OmxStore.h>
 
 using namespace android;
 
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index 6b30db6..2daa829 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -17,7 +17,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    MediaCasService.cpp \
     MediaDrmService.cpp \
     main_mediadrmserver.cpp
 
diff --git a/services/mediadrm/FactoryLoader.h b/services/mediadrm/FactoryLoader.h
deleted file mode 100644
index d7f1118..0000000
--- a/services/mediadrm/FactoryLoader.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MEDIA_CAS_LOADER_H_
-#define MEDIA_CAS_LOADER_H_
-
-#include <dirent.h>
-#include <dlfcn.h>
-#include <media/SharedLibrary.h>
-#include <utils/KeyedVector.h>
-#include <utils/Mutex.h>
-
-namespace android {
-using namespace std;
-using namespace media;
-using namespace MediaCas;
-
-template <class T>
-class FactoryLoader {
-public:
-    FactoryLoader(const char *name) :
-        mFactory(NULL), mCreateFactoryFuncName(name) {}
-
-    virtual ~FactoryLoader() { closeFactory(); }
-
-    bool findFactoryForScheme(
-            int32_t CA_system_id,
-            sp<SharedLibrary> *library = NULL,
-            T** factory = NULL);
-
-    bool enumeratePlugins(vector<ParcelableCasPluginDescriptor>* results);
-
-private:
-    typedef T*(*CreateFactoryFunc)();
-
-    Mutex mMapLock;
-    T* mFactory;
-    const char *mCreateFactoryFuncName;
-    sp<SharedLibrary> mLibrary;
-    KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
-    KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap;
-
-    bool loadFactoryForSchemeFromPath(
-            const String8 &path,
-            int32_t CA_system_id,
-            sp<SharedLibrary> *library,
-            T** factory);
-
-    bool queryPluginsFromPath(
-            const String8 &path,
-            vector<ParcelableCasPluginDescriptor>* results);
-
-    bool openFactory(const String8 &path);
-    void closeFactory();
-};
-
-template <class T>
-bool FactoryLoader<T>::findFactoryForScheme(
-        int32_t CA_system_id, sp<SharedLibrary> *library, T** factory) {
-    if (library != NULL) {
-        library->clear();
-    }
-    if (factory != NULL) {
-        *factory = NULL;
-    }
-
-    Mutex::Autolock autoLock(mMapLock);
-
-    // first check cache
-    ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id);
-    if (index >= 0) {
-        return loadFactoryForSchemeFromPath(
-                mCASystemIdToLibraryPathMap[index],
-                CA_system_id, library, factory);
-    }
-
-    // no luck, have to search
-    String8 dirPath("/system/lib/mediacas");
-    DIR* pDir = opendir(dirPath.string());
-
-    if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
-        return false;
-    }
-
-    struct dirent* pEntry;
-    while ((pEntry = readdir(pDir))) {
-        String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
-            if (loadFactoryForSchemeFromPath(
-                    pluginPath, CA_system_id, library, factory)) {
-                mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
-                closedir(pDir);
-
-                return true;
-            }
-        }
-    }
-
-    closedir(pDir);
-
-    ALOGE("Failed to find plugin");
-    return false;
-}
-
-template <class T>
-bool FactoryLoader<T>::enumeratePlugins(
-        vector<ParcelableCasPluginDescriptor>* results) {
-    ALOGI("enumeratePlugins");
-
-    results->clear();
-
-    String8 dirPath("/system/lib/mediacas");
-    DIR* pDir = opendir(dirPath.string());
-
-    if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
-        return false;
-    }
-
-    Mutex::Autolock autoLock(mMapLock);
-
-    struct dirent* pEntry;
-    while ((pEntry = readdir(pDir))) {
-        String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
-            queryPluginsFromPath(pluginPath, results);
-        }
-    }
-    return true;
-}
-
-template <class T>
-bool FactoryLoader<T>::loadFactoryForSchemeFromPath(
-        const String8 &path, int32_t CA_system_id,
-        sp<SharedLibrary> *library, T** factory) {
-    closeFactory();
-
-    if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) {
-        closeFactory();
-        return false;
-    }
-
-    if (library != NULL) {
-        *library = mLibrary;
-    }
-    if (factory != NULL) {
-        *factory = mFactory;
-    }
-    return true;
-}
-
-template <class T>
-bool FactoryLoader<T>::queryPluginsFromPath(
-        const String8 &path, vector<ParcelableCasPluginDescriptor>* results) {
-    closeFactory();
-
-    vector<CasPluginDescriptor> descriptors;
-    if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) {
-        closeFactory();
-        return false;
-    }
-
-    for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
-        results->push_back(ParcelableCasPluginDescriptor(
-                it->CA_system_id, it->name));
-    }
-    return true;
-}
-
-template <class T>
-bool FactoryLoader<T>::openFactory(const String8 &path) {
-    // get strong pointer to open shared library
-    ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
-    if (index >= 0) {
-        mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
-    } else {
-        index = mLibraryPathToOpenLibraryMap.add(path, NULL);
-    }
-
-    if (!mLibrary.get()) {
-        mLibrary = new SharedLibrary(path);
-        if (!*mLibrary) {
-            return false;
-        }
-
-        mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
-    }
-
-    CreateFactoryFunc createFactory =
-        (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName);
-    if (createFactory == NULL || (mFactory = createFactory()) == NULL) {
-        return false;
-    }
-    return true;
-}
-
-template <class T>
-void FactoryLoader<T>::closeFactory() {
-    delete mFactory;
-    mFactory = NULL;
-    mLibrary.clear();
-}
-
-} // namespace android
-
-#endif // MEDIA_CAS_LOADER_H_
diff --git a/services/mediadrm/MediaCasService.cpp b/services/mediadrm/MediaCasService.cpp
deleted file mode 100644
index c111283..0000000
--- a/services/mediadrm/MediaCasService.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaCasService"
-
-#include <binder/IServiceManager.h>
-#include <media/cas/CasAPI.h>
-#include <media/cas/DescramblerAPI.h>
-#include <media/CasImpl.h>
-#include <media/DescramblerImpl.h>
-#include <utils/Log.h>
-#include <utils/List.h>
-#include "MediaCasService.h"
-#include <android/media/ICasListener.h>
-
-namespace android {
-
-//static
-void MediaCasService::instantiate() {
-    defaultServiceManager()->addService(
-            String16("media.cas"), new MediaCasService());
-}
-
-MediaCasService::MediaCasService() :
-    mCasLoader(new FactoryLoader<CasFactory>("createCasFactory")),
-    mDescramblerLoader(new FactoryLoader<DescramblerFactory>(
-            "createDescramblerFactory")) {
-}
-
-MediaCasService::~MediaCasService() {
-    delete mCasLoader;
-    delete mDescramblerLoader;
-}
-
-Status MediaCasService::enumeratePlugins(
-        vector<ParcelableCasPluginDescriptor>* results) {
-    ALOGV("enumeratePlugins");
-
-    mCasLoader->enumeratePlugins(results);
-
-    return Status::ok();
-}
-
-Status MediaCasService::isSystemIdSupported(
-        int32_t CA_system_id, bool* result) {
-    ALOGV("isSystemIdSupported: CA_system_id=%d", CA_system_id);
-
-    *result = mCasLoader->findFactoryForScheme(CA_system_id);
-
-    return Status::ok();
-}
-
-Status MediaCasService::createPlugin(
-        int32_t CA_system_id,
-        const sp<ICasListener> &listener,
-        sp<ICas>* result) {
-    ALOGV("createPlugin: CA_system_id=%d", CA_system_id);
-
-    result->clear();
-
-    CasFactory *factory;
-    sp<SharedLibrary> library;
-    if (mCasLoader->findFactoryForScheme(CA_system_id, &library, &factory)) {
-        CasPlugin *plugin = NULL;
-        sp<CasImpl> casImpl = new CasImpl(listener);
-        if (factory->createPlugin(CA_system_id, (uint64_t)casImpl.get(),
-                &CasImpl::OnEvent, &plugin) == OK && plugin != NULL) {
-            casImpl->init(library, plugin);
-            *result = casImpl;
-        }
-    }
-
-    return Status::ok();
-}
-
-Status MediaCasService::isDescramblerSupported(
-        int32_t CA_system_id, bool* result) {
-    ALOGV("isDescramblerSupported: CA_system_id=%d", CA_system_id);
-
-    *result = mDescramblerLoader->findFactoryForScheme(CA_system_id);
-
-    return Status::ok();
-}
-
-Status MediaCasService::createDescrambler(
-        int32_t CA_system_id, sp<IDescrambler>* result) {
-    ALOGV("createDescrambler: CA_system_id=%d", CA_system_id);
-
-    result->clear();
-
-    DescramblerFactory *factory;
-    sp<SharedLibrary> library;
-    if (mDescramblerLoader->findFactoryForScheme(
-            CA_system_id, &library, &factory)) {
-        DescramblerPlugin *plugin = NULL;
-        if (factory->createPlugin(CA_system_id, &plugin) == OK
-                && plugin != NULL) {
-            *result = new DescramblerImpl(library, plugin);
-        }
-    }
-
-    return Status::ok();
-}
-
-} // namespace android
diff --git a/services/mediadrm/MediaCasService.h b/services/mediadrm/MediaCasService.h
deleted file mode 100644
index cb828f2..0000000
--- a/services/mediadrm/MediaCasService.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MEDIA_CAS_SERVICE_H_
-#define MEDIA_CAS_SERVICE_H_
-
-#include <android/media/BnMediaCasService.h>
-
-#include "FactoryLoader.h"
-
-namespace android {
-using binder::Status;
-struct CasFactory;
-struct DescramblerFactory;
-
-class MediaCasService : public BnMediaCasService {
-public:
-    static void instantiate();
-
-    virtual Status enumeratePlugins(
-            vector<ParcelableCasPluginDescriptor>* results) override;
-
-    virtual Status isSystemIdSupported(
-            int32_t CA_system_id, bool* result) override;
-
-    virtual Status createPlugin(
-            int32_t CA_system_id,
-            const sp<ICasListener> &listener,
-            sp<ICas>* result) override;
-
-    virtual Status isDescramblerSupported(
-            int32_t CA_system_id, bool* result) override;
-
-    virtual Status createDescrambler(
-            int32_t CA_system_id, sp<IDescrambler>* result) override;
-
-private:
-    FactoryLoader<CasFactory> *mCasLoader;
-    FactoryLoader<DescramblerFactory> *mDescramblerLoader;
-
-    MediaCasService();
-    virtual ~MediaCasService();
-};
-
-} // namespace android
-
-#endif // MEDIA_CAS_SERVICE_H_
diff --git a/services/mediadrm/main_mediadrmserver.cpp b/services/mediadrm/main_mediadrmserver.cpp
index b685ae0..b767b8c 100644
--- a/services/mediadrm/main_mediadrmserver.cpp
+++ b/services/mediadrm/main_mediadrmserver.cpp
@@ -27,7 +27,6 @@
 #include <cutils/properties.h>
 #include <utils/Log.h>
 #include "MediaDrmService.h"
-#include "MediaCasService.h"
 
 using namespace android;
 
@@ -39,7 +38,6 @@
     sp<IServiceManager> sm = defaultServiceManager();
     ALOGI("ServiceManager: %p", sm.get());
     MediaDrmService::instantiate();
-    MediaCasService::instantiate();
     ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
 }
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index ec2f5b9..f996f74 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -26,6 +26,10 @@
 #include <utility/AAudioUtilities.h>
 
 #include "AAudioEndpointManager.h"
+#include "AAudioServiceEndpointShared.h"
+#include "AAudioServiceEndpointMMAP.h"
+#include "AAudioServiceEndpointCapture.h"
+#include "AAudioServiceEndpointPlay.h"
 
 using namespace android;
 using namespace aaudio;
@@ -34,159 +38,237 @@
 
 AAudioEndpointManager::AAudioEndpointManager()
         : Singleton<AAudioEndpointManager>()
-        , mInputs()
-        , mOutputs() {
+        , mSharedStreams()
+        , mExclusiveStreams() {
 }
 
 std::string AAudioEndpointManager::dump() const {
     std::stringstream result;
-    const bool isLocked = AAudio_tryUntilTrue(
-            [this]()->bool { return mLock.try_lock(); } /* f */,
-            50 /* times */,
-            20 /* sleepMs */);
-    if (!isLocked) {
-        result << "EndpointManager may be deadlocked\n";
-    }
+    int index = 0;
 
     result << "AAudioEndpointManager:" << "\n";
-    size_t inputs = mInputs.size();
-    result << "Input Endpoints: " << inputs << "\n";
-    for (const auto &input : mInputs) {
-        result << "  Input: " << input->dump() << "\n";
+
+    const bool isSharedLocked = AAudio_tryUntilTrue(
+            [this]()->bool { return mSharedLock.try_lock(); } /* f */,
+            50 /* times */,
+            20 /* sleepMs */);
+    if (!isSharedLocked) {
+        result << "AAudioEndpointManager Shared may be deadlocked\n";
     }
 
-    size_t outputs = mOutputs.size();
-    result << "Output Endpoints: " << outputs << "\n";
-    for (const auto &output : mOutputs) {
-        result << "  Output: " << output->dump() << "\n";
+    {
+        const bool isExclusiveLocked = AAudio_tryUntilTrue(
+                [this]() -> bool { return mExclusiveLock.try_lock(); } /* f */,
+                50 /* times */,
+                20 /* sleepMs */);
+        if (!isExclusiveLocked) {
+            result << "AAudioEndpointManager Exclusive may be deadlocked\n";
+        }
+
+        result << "Exclusive MMAP Endpoints: " << mExclusiveStreams.size() << "\n";
+        index = 0;
+        for (const auto &output : mExclusiveStreams) {
+            result << "  #" << index++ << ":";
+            result << output->dump() << "\n";
+        }
+
+        if (isExclusiveLocked) {
+            mExclusiveLock.unlock();
+        }
     }
 
-    if (isLocked) {
-        mLock.unlock();
+    result << "Shared Endpoints: " << mSharedStreams.size() << "\n";
+    index = 0;
+    for (const auto &input : mSharedStreams) {
+        result << "  #" << index++ << ":";
+        result << input->dump() << "\n";
+    }
+
+    if (isSharedLocked) {
+        mSharedLock.unlock();
     }
     return result.str();
 }
 
-AAudioServiceEndpoint *AAudioEndpointManager::openEndpoint(AAudioService &audioService,
-        const AAudioStreamConfiguration& configuration, aaudio_direction_t direction) {
-    AAudioServiceEndpoint *endpoint = nullptr;
-    AAudioServiceEndpointCapture *capture = nullptr;
-    AAudioServiceEndpointPlay *player = nullptr;
-    std::lock_guard<std::mutex> lock(mLock);
+
+// Try to find an existing endpoint.
+sp<AAudioServiceEndpoint> AAudioEndpointManager::findExclusiveEndpoint_l(
+        const AAudioStreamConfiguration &configuration) {
+    sp<AAudioServiceEndpoint> endpoint;
+    for (const auto ep : mExclusiveStreams) {
+        if (ep->matches(configuration)) {
+            endpoint = ep;
+            break;
+        }
+    }
+
+    ALOGV("AAudioEndpointManager.findExclusiveEndpoint_l(), found %p for device = %d",
+          endpoint.get(), configuration.getDeviceId());
+    return endpoint;
+}
+
+// Try to find an existing endpoint.
+sp<AAudioServiceEndpointShared> AAudioEndpointManager::findSharedEndpoint_l(
+        const AAudioStreamConfiguration &configuration) {
+    sp<AAudioServiceEndpointShared> endpoint;
+    for (const auto ep  : mSharedStreams) {
+        if (ep->matches(configuration)) {
+            endpoint = ep;
+            break;
+        }
+    }
+
+    ALOGV("AAudioEndpointManager.findSharedEndpoint_l(), found %p for device = %d",
+          endpoint.get(), configuration.getDeviceId());
+    return endpoint;
+}
+
+sp<AAudioServiceEndpoint> AAudioEndpointManager::openEndpoint(AAudioService &audioService,
+                                        const aaudio::AAudioStreamRequest &request,
+                                        aaudio_sharing_mode_t sharingMode) {
+    if (sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) {
+        return openExclusiveEndpoint(audioService, request);
+    } else {
+        return openSharedEndpoint(audioService, request);
+    }
+}
+
+sp<AAudioServiceEndpoint> AAudioEndpointManager::openExclusiveEndpoint(
+        AAudioService &aaudioService __unused,
+        const aaudio::AAudioStreamRequest &request) {
+
+    std::lock_guard<std::mutex> lock(mExclusiveLock);
+
+    const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
 
     // Try to find an existing endpoint.
+    sp<AAudioServiceEndpoint> endpoint = findExclusiveEndpoint_l(configuration);
 
+    // If we find an existing one then this one cannot be exclusive.
+    if (endpoint.get() != nullptr) {
+        ALOGE("AAudioEndpointManager.openExclusiveEndpoint() already in use");
+        // Already open so do not allow a second stream.
+        return nullptr;
+    } else {
+        sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP();
+        ALOGE("AAudioEndpointManager.openEndpoint(),created MMAP %p", endpointMMap.get());
+        endpoint = endpointMMap;
 
-
-    switch (direction) {
-        case AAUDIO_DIRECTION_INPUT:
-            for (AAudioServiceEndpoint *ep : mInputs) {
-                if (ep->matches(configuration)) {
-                    endpoint = ep;
-                    break;
-                }
-            }
-            break;
-        case AAUDIO_DIRECTION_OUTPUT:
-            for (AAudioServiceEndpoint *ep : mOutputs) {
-                if (ep->matches(configuration)) {
-                    endpoint = ep;
-                    break;
-                }
-            }
-            break;
-        default:
-            assert(false); // There are only two possible directions.
-            break;
-    }
-    ALOGD("AAudioEndpointManager::openEndpoint(), found %p for device = %d, dir = %d",
-          endpoint, configuration.getDeviceId(), (int)direction);
-
-    // If we can't find an existing one then open a new one.
-    if (endpoint == nullptr) {
-        // we must call openStream with audioserver identity
-        int64_t token = IPCThreadState::self()->clearCallingIdentity();
-        switch(direction) {
-            case AAUDIO_DIRECTION_INPUT:
-                capture = new AAudioServiceEndpointCapture(audioService);
-                endpoint = capture;
-                break;
-            case AAUDIO_DIRECTION_OUTPUT:
-                player = new AAudioServiceEndpointPlay(audioService);
-                endpoint = player;
-                break;
-            default:
-                break;
+        aaudio_result_t result = endpoint->open(request);
+        if (result != AAUDIO_OK) {
+            ALOGE("AAudioEndpointManager.openEndpoint(), open failed");
+            endpoint.clear();
+        } else {
+            mExclusiveStreams.push_back(endpointMMap);
         }
 
-        if (endpoint != nullptr) {
-            aaudio_result_t result = endpoint->open(configuration);
-            if (result != AAUDIO_OK) {
-                ALOGE("AAudioEndpointManager::findEndpoint(), open failed");
-                delete endpoint;
-                endpoint = nullptr;
-            } else {
-                switch(direction) {
-                    case AAUDIO_DIRECTION_INPUT:
-                        mInputs.push_back(capture);
-                        break;
-                    case AAUDIO_DIRECTION_OUTPUT:
-                        mOutputs.push_back(player);
-                        break;
-                    default:
-                        break;
-                }
-            }
-        }
-        ALOGD("AAudioEndpointManager::openEndpoint(), created %p for device = %d, dir = %d",
-              endpoint, configuration.getDeviceId(), (int)direction);
-        IPCThreadState::self()->restoreCallingIdentity(token);
+        ALOGD("AAudioEndpointManager.openEndpoint(), created %p for device = %d",
+              endpoint.get(), configuration.getDeviceId());
     }
 
-    if (endpoint != nullptr) {
-        ALOGD("AAudioEndpointManager::openEndpoint(), sampleRate = %d, framesPerBurst = %d",
-              endpoint->getSampleRate(), endpoint->getFramesPerBurst());
+    if (endpoint.get() != nullptr) {
         // Increment the reference count under this lock.
-        endpoint->setReferenceCount(endpoint->getReferenceCount() + 1);
+        endpoint->setOpenCount(endpoint->getOpenCount() + 1);
     }
     return endpoint;
 }
 
-void AAudioEndpointManager::closeEndpoint(AAudioServiceEndpoint *serviceEndpoint) {
-    std::lock_guard<std::mutex> lock(mLock);
-    if (serviceEndpoint == nullptr) {
-        return;
-    }
+sp<AAudioServiceEndpoint> AAudioEndpointManager::openSharedEndpoint(
+        AAudioService &aaudioService,
+        const aaudio::AAudioStreamRequest &request) {
 
-    // Decrement the reference count under this lock.
-    int32_t newRefCount = serviceEndpoint->getReferenceCount() - 1;
-    serviceEndpoint->setReferenceCount(newRefCount);
-    ALOGD("AAudioEndpointManager::closeEndpoint(%p) newRefCount = %d",
-          serviceEndpoint, newRefCount);
+    std::lock_guard<std::mutex> lock(mSharedLock);
 
-    // If no longer in use then close and delete it.
-    if (newRefCount <= 0) {
-        aaudio_direction_t direction = serviceEndpoint->getDirection();
-        // Track endpoints based on requested deviceId because UNSPECIFIED
-        // can change to a specific device after opening.
-        int32_t deviceId = serviceEndpoint->getRequestedDeviceId();
+    const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
+    aaudio_direction_t direction = configuration.getDirection();
 
+    // Try to find an existing endpoint.
+    sp<AAudioServiceEndpointShared> endpoint = findSharedEndpoint_l(configuration);
+
+    // If we can't find an existing one then open a new one.
+    if (endpoint.get() == nullptr) {
+        // we must call openStream with audioserver identity
+        int64_t token = IPCThreadState::self()->clearCallingIdentity();
         switch (direction) {
             case AAUDIO_DIRECTION_INPUT:
-                mInputs.erase(
-                  std::remove(mInputs.begin(), mInputs.end(), serviceEndpoint), mInputs.end());
+                endpoint = new AAudioServiceEndpointCapture(aaudioService);
                 break;
             case AAUDIO_DIRECTION_OUTPUT:
-                mOutputs.erase(
-                  std::remove(mOutputs.begin(), mOutputs.end(), serviceEndpoint), mOutputs.end());
+                endpoint = new AAudioServiceEndpointPlay(aaudioService);
                 break;
             default:
                 break;
         }
 
+        if (endpoint.get() != nullptr) {
+            aaudio_result_t result = endpoint->open(request);
+            if (result != AAUDIO_OK) {
+                ALOGE("AAudioEndpointManager.openEndpoint(), open failed");
+                endpoint.clear();
+            } else {
+                mSharedStreams.push_back(endpoint);
+            }
+        }
+        ALOGD("AAudioEndpointManager.openSharedEndpoint(), created %p for device = %d, dir = %d",
+              endpoint.get(), configuration.getDeviceId(), (int)direction);
+        IPCThreadState::self()->restoreCallingIdentity(token);
+    }
+
+    if (endpoint.get() != nullptr) {
+        // Increment the reference count under this lock.
+        endpoint->setOpenCount(endpoint->getOpenCount() + 1);
+    }
+    return endpoint;
+}
+
+void AAudioEndpointManager::closeEndpoint(sp<AAudioServiceEndpoint>serviceEndpoint) {
+    if (serviceEndpoint->getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
+        return closeExclusiveEndpoint(serviceEndpoint);
+    } else {
+        return closeSharedEndpoint(serviceEndpoint);
+    }
+}
+
+void AAudioEndpointManager::closeExclusiveEndpoint(sp<AAudioServiceEndpoint> serviceEndpoint) {
+    if (serviceEndpoint.get() == nullptr) {
+        return;
+    }
+
+    // Decrement the reference count under this lock.
+    std::lock_guard<std::mutex> lock(mExclusiveLock);
+    int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
+    serviceEndpoint->setOpenCount(newRefCount);
+
+    // If no longer in use then close and delete it.
+    if (newRefCount <= 0) {
+        mExclusiveStreams.erase(
+                std::remove(mExclusiveStreams.begin(), mExclusiveStreams.end(), serviceEndpoint),
+                mExclusiveStreams.end());
+
         serviceEndpoint->close();
-        ALOGD("AAudioEndpointManager::closeEndpoint() delete %p for device %d, dir = %d",
-              serviceEndpoint, deviceId, (int)direction);
-        delete serviceEndpoint;
+        ALOGD("AAudioEndpointManager::closeExclusiveEndpoint() %p for device %d",
+              serviceEndpoint.get(), serviceEndpoint->getDeviceId());
+    }
+}
+
+void AAudioEndpointManager::closeSharedEndpoint(sp<AAudioServiceEndpoint> serviceEndpoint) {
+    if (serviceEndpoint.get() == nullptr) {
+        return;
+    }
+
+    // Decrement the reference count under this lock.
+    std::lock_guard<std::mutex> lock(mSharedLock);
+    int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
+    serviceEndpoint->setOpenCount(newRefCount);
+
+    // If no longer in use then close and delete it.
+    if (newRefCount <= 0) {
+        mSharedStreams.erase(
+                std::remove(mSharedStreams.begin(), mSharedStreams.end(), serviceEndpoint),
+                mSharedStreams.end());
+
+        serviceEndpoint->close();
+        ALOGD("AAudioEndpointManager::closeSharedEndpoint() %p for device %d",
+              serviceEndpoint.get(), serviceEndpoint->getDeviceId());
     }
 }
diff --git a/services/oboeservice/AAudioEndpointManager.h b/services/oboeservice/AAudioEndpointManager.h
index 2511b2f..32c8454 100644
--- a/services/oboeservice/AAudioEndpointManager.h
+++ b/services/oboeservice/AAudioEndpointManager.h
@@ -24,11 +24,12 @@
 #include "binding/AAudioServiceMessage.h"
 #include "AAudioServiceEndpoint.h"
 #include "AAudioServiceEndpointCapture.h"
+#include "AAudioServiceEndpointMMAP.h"
 #include "AAudioServiceEndpointPlay.h"
 
 namespace aaudio {
 
-class AAudioEndpointManager : public android::Singleton<AAudioEndpointManager>{
+class AAudioEndpointManager : public android::Singleton<AAudioEndpointManager> {
 public:
     AAudioEndpointManager();
     ~AAudioEndpointManager() = default;
@@ -49,22 +50,42 @@
      * Find a service endpoint for the given deviceId and direction.
      * If an endpoint does not already exist then try to create one.
      *
-     * @param deviceId
-     * @param direction
-     * @return endpoint or nullptr
+     * @param audioService
+     * @param request
+     * @param sharingMode
+     * @return endpoint or null
      */
-    AAudioServiceEndpoint *openEndpoint(android::AAudioService &audioService,
-                                        const AAudioStreamConfiguration& configuration,
-                                        aaudio_direction_t direction);
+    android::sp<AAudioServiceEndpoint> openEndpoint(android::AAudioService &audioService,
+                                        const aaudio::AAudioStreamRequest &request,
+                                        aaudio_sharing_mode_t sharingMode);
 
-    void closeEndpoint(AAudioServiceEndpoint *serviceEndpoint);
+    void closeEndpoint(android::sp<AAudioServiceEndpoint> serviceEndpoint);
 
 private:
+    android::sp<AAudioServiceEndpoint> openExclusiveEndpoint(android::AAudioService &aaudioService,
+                                                 const aaudio::AAudioStreamRequest &request);
 
-    mutable std::mutex mLock;
+    android::sp<AAudioServiceEndpoint> openSharedEndpoint(android::AAudioService &aaudioService,
+                                              const aaudio::AAudioStreamRequest &request);
 
-    std::vector<AAudioServiceEndpointCapture *> mInputs;
-    std::vector<AAudioServiceEndpointPlay *> mOutputs;
+    android::sp<AAudioServiceEndpoint> findExclusiveEndpoint_l(
+            const AAudioStreamConfiguration& configuration);
+
+    android::sp<AAudioServiceEndpointShared> findSharedEndpoint_l(
+            const AAudioStreamConfiguration& configuration);
+
+    void closeExclusiveEndpoint(android::sp<AAudioServiceEndpoint> serviceEndpoint);
+    void closeSharedEndpoint(android::sp<AAudioServiceEndpoint> serviceEndpoint);
+
+    // Use separate locks because opening a Shared endpoint requires opening an Exclusive one.
+    // That could cause a recursive lock.
+    // Lock mSharedLock before mExclusiveLock.
+    // it is OK to only lock mExclusiveLock.
+    mutable std::mutex                                     mSharedLock;
+    std::vector<android::sp<AAudioServiceEndpointShared>>  mSharedStreams;
+
+    mutable std::mutex                                     mExclusiveLock;
+    std::vector<android::sp<AAudioServiceEndpointMMAP>>    mExclusiveStreams;
 
 };
 
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 3992719..5a3488d 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -18,9 +18,9 @@
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
+#include <iomanip>
+#include <iostream>
 #include <sstream>
-//#include <time.h>
-//#include <pthread.h>
 
 #include <aaudio/AAudio.h>
 #include <mediautils/SchedulingPolicyService.h>
@@ -35,18 +35,13 @@
 #include "AAudioServiceStreamMMAP.h"
 #include "binding/IAAudioService.h"
 #include "ServiceUtilities.h"
-#include "utility/HandleTracker.h"
 
 using namespace android;
 using namespace aaudio;
 
 #define MAX_STREAMS_PER_PROCESS   8
 
-typedef enum
-{
-    AAUDIO_HANDLE_TYPE_STREAM
-} aaudio_service_handle_type_t;
-static_assert(AAUDIO_HANDLE_TYPE_STREAM < HANDLE_TRACKER_MAX_TYPES, "Too many handle types.");
+using android::AAudioService;
 
 android::AAudioService::AAudioService()
     : BnAAudioService() {
@@ -70,7 +65,8 @@
         result = ss.str();
         ALOGW("%s", result.c_str());
     } else {
-        result = mHandleTracker.dump()
+        result = "------------ AAudio Service ------------\n"
+                 + mStreamTracker.dump()
                  + AAudioClientTracker::getInstance().dump()
                  + AAudioEndpointManager::getInstance().dump();
     }
@@ -114,23 +110,20 @@
                 mAudioClient.clientUid == IPCThreadState::self()->getCallingUid()) {
             inService = request.isInService();
         }
-        serviceStream = new AAudioServiceStreamMMAP(mAudioClient, inService);
-        result = serviceStream->open(request, configurationOutput);
+        serviceStream = new AAudioServiceStreamMMAP(*this, inService);
+        result = serviceStream->open(request);
         if (result != AAUDIO_OK) {
-            // fall back to using a shared stream
+            // Clear it so we can possibly fall back to using a shared stream.
             ALOGW("AAudioService::openStream(), could not open in EXCLUSIVE mode");
             serviceStream.clear();
-        } else {
-            configurationOutput.setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
         }
     }
 
     // if SHARED requested or if EXCLUSIVE failed
     if (sharingMode == AAUDIO_SHARING_MODE_SHARED
-         || (serviceStream == nullptr && !sharingModeMatchRequired)) {
+         || (serviceStream.get() == nullptr && !sharingModeMatchRequired)) {
         serviceStream =  new AAudioServiceStreamShared(*this);
-        result = serviceStream->open(request, configurationOutput);
-        configurationOutput.setSharingMode(AAUDIO_SHARING_MODE_SHARED);
+        result = serviceStream->open(request);
     }
 
     if (result != AAUDIO_OK) {
@@ -139,17 +132,12 @@
               result, AAudio_convertResultToText(result));
         return result;
     } else {
-        aaudio_handle_t handle = mHandleTracker.put(AAUDIO_HANDLE_TYPE_STREAM, serviceStream.get());
-        if (handle < 0) {
-            ALOGE("AAudioService::openStream(): handle table full");
-            serviceStream->close();
-            serviceStream.clear();
-        } else {
-            ALOGD("AAudioService::openStream(): handle = 0x%08X", handle);
-            serviceStream->setHandle(handle);
-            pid_t pid = request.getProcessId();
-            AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
-        }
+        aaudio_handle_t handle = mStreamTracker.addStreamForHandle(serviceStream.get());
+        ALOGD("AAudioService::openStream(): handle = 0x%08X", handle);
+        serviceStream->setHandle(handle);
+        pid_t pid = request.getProcessId();
+        AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
+        configurationOutput.copyFrom(*serviceStream);
         return handle;
     }
 }
@@ -157,30 +145,32 @@
 aaudio_result_t AAudioService::closeStream(aaudio_handle_t streamHandle) {
     // Check permission and ownership first.
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
-        ALOGE("AAudioService::startStream(), illegal stream handle = 0x%0x", streamHandle);
+    if (serviceStream.get() == nullptr) {
+        ALOGE("AAudioService::closeStream(0x%0x), illegal stream handle", streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
 
     ALOGD("AAudioService.closeStream(0x%08X)", streamHandle);
     // Remove handle from tracker so that we cannot look up the raw address any more.
-    serviceStream = (AAudioServiceStreamBase *)
-            mHandleTracker.remove(AAUDIO_HANDLE_TYPE_STREAM,
-                                  streamHandle);
-    if (serviceStream != nullptr) {
+    // removeStreamByHandle() uses a lock so that if there are two simultaneous closes
+    // then only one will get the pointer and do the close.
+    serviceStream = mStreamTracker.removeStreamByHandle(streamHandle);
+    if (serviceStream.get() != nullptr) {
         serviceStream->close();
         pid_t pid = serviceStream->getOwnerProcessId();
         AAudioClientTracker::getInstance().unregisterClientStream(pid, serviceStream);
         return AAUDIO_OK;
+    } else {
+        ALOGW("AAudioService::closeStream(0x%0x) being handled by another thread", streamHandle);
+        return AAUDIO_ERROR_INVALID_HANDLE;
     }
-    return AAUDIO_ERROR_INVALID_HANDLE;
 }
 
-AAudioServiceStreamBase *AAudioService::convertHandleToServiceStream(
-        aaudio_handle_t streamHandle) const {
-    AAudioServiceStreamBase *serviceStream = (AAudioServiceStreamBase *)
-            mHandleTracker.get(AAUDIO_HANDLE_TYPE_STREAM, (aaudio_handle_t)streamHandle);
-    if (serviceStream != nullptr) {
+
+sp<AAudioServiceStreamBase> AAudioService::convertHandleToServiceStream(
+        aaudio_handle_t streamHandle) {
+    sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandle(streamHandle);
+    if (serviceStream.get() != nullptr) {
         // Only allow owner or the aaudio service to access the stream.
         const uid_t callingUserId = IPCThreadState::self()->getCallingUid();
         const uid_t ownerUserId = serviceStream->getOwnerUserId();
@@ -200,30 +190,30 @@
 aaudio_result_t AAudioService::getStreamDescription(
                 aaudio_handle_t streamHandle,
                 aaudio::AudioEndpointParcelable &parcelable) {
-    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
+    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+    if (serviceStream.get() == nullptr) {
         ALOGE("AAudioService::getStreamDescription(), illegal stream handle = 0x%0x", streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
+
     aaudio_result_t result = serviceStream->getDescription(parcelable);
     // parcelable.dump();
     return result;
 }
 
 aaudio_result_t AAudioService::startStream(aaudio_handle_t streamHandle) {
-    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
+    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+    if (serviceStream.get() == nullptr) {
         ALOGE("AAudioService::startStream(), illegal stream handle = 0x%0x", streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
 
-    aaudio_result_t result = serviceStream->start();
-    return result;
+    return serviceStream->start();
 }
 
 aaudio_result_t AAudioService::pauseStream(aaudio_handle_t streamHandle) {
-    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
+    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+    if (serviceStream.get() == nullptr) {
         ALOGE("AAudioService::pauseStream(), illegal stream handle = 0x%0x", streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
@@ -232,9 +222,9 @@
 }
 
 aaudio_result_t AAudioService::stopStream(aaudio_handle_t streamHandle) {
-    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
-        ALOGE("AAudioService::pauseStream(), illegal stream handle = 0x%0x", streamHandle);
+    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+    if (serviceStream.get() == nullptr) {
+        ALOGE("AAudioService::stopStream(), illegal stream handle = 0x%0x", streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
     aaudio_result_t result = serviceStream->stop();
@@ -242,8 +232,8 @@
 }
 
 aaudio_result_t AAudioService::flushStream(aaudio_handle_t streamHandle) {
-    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
+    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+    if (serviceStream.get() == nullptr) {
         ALOGE("AAudioService::flushStream(), illegal stream handle = 0x%0x", streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
@@ -253,8 +243,8 @@
 aaudio_result_t AAudioService::registerAudioThread(aaudio_handle_t streamHandle,
                                                    pid_t clientThreadId,
                                                    int64_t periodNanoseconds) {
-    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
+    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+    if (serviceStream.get() == nullptr) {
         ALOGE("AAudioService::registerAudioThread(), illegal stream handle = 0x%0x", streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
@@ -278,8 +268,8 @@
 
 aaudio_result_t AAudioService::unregisterAudioThread(aaudio_handle_t streamHandle,
                                                      pid_t clientThreadId) {
-    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
+    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+    if (serviceStream.get() == nullptr) {
         ALOGE("AAudioService::unregisterAudioThread(), illegal stream handle = 0x%0x",
               streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
@@ -295,8 +285,8 @@
 aaudio_result_t AAudioService::startClient(aaudio_handle_t streamHandle,
                                   const android::AudioClient& client,
                                   audio_port_handle_t *clientHandle) {
-    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
+    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+    if (serviceStream.get() == nullptr) {
         ALOGE("AAudioService::startClient(), illegal stream handle = 0x%0x",
               streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
@@ -306,8 +296,8 @@
 
 aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
                                           audio_port_handle_t clientHandle) {
-    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
-    if (serviceStream == nullptr) {
+    sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+    if (serviceStream.get() == nullptr) {
         ALOGE("AAudioService::stopClient(), illegal stream handle = 0x%0x",
               streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index 8421efc..eef0824 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -24,11 +24,13 @@
 #include <media/AudioClient.h>
 
 #include <aaudio/AAudio.h>
-#include "utility/HandleTracker.h"
-#include "binding/IAAudioService.h"
+
+#include "binding/AAudioCommon.h"
 #include "binding/AAudioServiceInterface.h"
+#include "binding/IAAudioService.h"
 
 #include "AAudioServiceStreamBase.h"
+#include "AAudioStreamTracker.h"
 
 namespace android {
 
@@ -49,45 +51,53 @@
 
     virtual void            registerClient(const sp<IAAudioClient>& client);
 
-    virtual aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
-                                     aaudio::AAudioStreamConfiguration &configurationOutput);
+    aaudio::aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
+                                       aaudio::AAudioStreamConfiguration &configurationOutput)
+                                       override;
 
-    virtual aaudio_result_t closeStream(aaudio_handle_t streamHandle);
+    aaudio_result_t closeStream(aaudio::aaudio_handle_t streamHandle) override;
 
-    virtual aaudio_result_t getStreamDescription(
-                aaudio_handle_t streamHandle,
-                aaudio::AudioEndpointParcelable &parcelable);
+    aaudio_result_t getStreamDescription(
+                aaudio::aaudio_handle_t streamHandle,
+                aaudio::AudioEndpointParcelable &parcelable) override;
 
-    virtual aaudio_result_t startStream(aaudio_handle_t streamHandle);
+    aaudio_result_t startStream(aaudio::aaudio_handle_t streamHandle) override;
 
-    virtual aaudio_result_t pauseStream(aaudio_handle_t streamHandle);
+    aaudio_result_t pauseStream(aaudio::aaudio_handle_t streamHandle) override;
 
-    virtual aaudio_result_t stopStream(aaudio_handle_t streamHandle);
+    aaudio_result_t stopStream(aaudio::aaudio_handle_t streamHandle) override;
 
-    virtual aaudio_result_t flushStream(aaudio_handle_t streamHandle);
+    aaudio_result_t flushStream(aaudio::aaudio_handle_t streamHandle) override;
 
-    virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
+    aaudio_result_t registerAudioThread(aaudio::aaudio_handle_t streamHandle,
                                                 pid_t tid,
-                                                int64_t periodNanoseconds) ;
+                                                int64_t periodNanoseconds) override;
 
-    virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
-                                                  pid_t tid);
+    aaudio_result_t unregisterAudioThread(aaudio::aaudio_handle_t streamHandle,
+                                                  pid_t tid) override;
 
-    virtual aaudio_result_t startClient(aaudio_handle_t streamHandle,
+    aaudio_result_t startClient(aaudio::aaudio_handle_t streamHandle,
                                       const android::AudioClient& client,
-                                      audio_port_handle_t *clientHandle);
+                                      audio_port_handle_t *clientHandle) override;
 
-    virtual aaudio_result_t stopClient(aaudio_handle_t streamHandle,
-                                       audio_port_handle_t clientHandle);
+    aaudio_result_t stopClient(aaudio::aaudio_handle_t streamHandle,
+                                       audio_port_handle_t clientHandle) override;
 
 private:
 
-    aaudio::AAudioServiceStreamBase *convertHandleToServiceStream(aaudio_handle_t streamHandle) const;
+    /**
+     * Lookup stream and then validate access to the stream.
+     * @param streamHandle
+     * @return
+     */
+    sp<aaudio::AAudioServiceStreamBase> convertHandleToServiceStream(
+            aaudio::aaudio_handle_t streamHandle);
 
-    HandleTracker mHandleTracker;
 
     android::AudioClient mAudioClient;
 
+    aaudio::AAudioStreamTracker                 mStreamTracker;
+
     enum constants {
         DEFAULT_AUDIO_PRIORITY = 2
     };
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 0f863fe..3095bc9 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -33,17 +33,14 @@
 #include "core/AudioStreamBuilder.h"
 #include "AAudioServiceEndpoint.h"
 #include "AAudioServiceStreamShared.h"
+#include "AAudioServiceEndpointShared.h"
 
 using namespace android;  // TODO just import names needed
 using namespace aaudio;   // TODO just import names needed
 
-#define MIN_TIMEOUT_NANOS        (1000 * AAUDIO_NANOS_PER_MILLISECOND)
-
-// Wait at least this many times longer than the operation should take.
-#define MIN_TIMEOUT_OPERATIONS    4
-
-// This is the maximum size in frames. The effective size can be tuned smaller at runtime.
-#define DEFAULT_BUFFER_CAPACITY   (48 * 8)
+AAudioServiceEndpoint::~AAudioServiceEndpoint() {
+    ALOGD("AAudioServiceEndpoint::~AAudioServiceEndpoint() destroying endpoint %p", this);
+}
 
 std::string AAudioServiceEndpoint::dump() const {
     std::stringstream result;
@@ -53,19 +50,20 @@
             50 /* times */,
             20 /* sleepMs */);
     if (!isLocked) {
-        result << "EndpointManager may be deadlocked\n";
+        result << "AAudioServiceEndpoint may be deadlocked\n";
     }
 
-    AudioStreamInternal     *stream = mStreamInternal;
-    if (stream == nullptr) {
-        result << "null stream!" << "\n";
-    } else {
-        result << "mmap stream: rate = " << stream->getSampleRate() << "\n";
-    }
-
+    result << "    Direction:            " << ((getDirection() == AAUDIO_DIRECTION_OUTPUT)
+                                   ? "OUTPUT" : "INPUT") << "\n";
+    result << "    Sample Rate:          " << getSampleRate() << "\n";
+    result << "    Frames Per Burst:     " << mFramesPerBurst << "\n";
+    result << "    Reference Count:      " << mOpenCount << "\n";
+    result << "    Requested Device Id:  " << mRequestedDeviceId << "\n";
+    result << "    Device Id:            " << getDeviceId() << "\n";
     result << "    Registered Streams:" << "\n";
-    for (sp<AAudioServiceStreamShared> sharedStream : mRegisteredStreams) {
-        result << sharedStream->dump();
+    result << AAudioServiceStreamShared::dumpHeader() << "\n";
+    for (const auto stream : mRegisteredStreams) {
+        result << stream->dump() << "\n";
     }
 
     if (isLocked) {
@@ -74,110 +72,44 @@
     return result.str();
 }
 
-// Set up an EXCLUSIVE MMAP stream that will be shared.
-aaudio_result_t AAudioServiceEndpoint::open(const AAudioStreamConfiguration& configuration) {
-    mRequestedDeviceId = configuration.getDeviceId();
-    mStreamInternal = getStreamInternal();
-
-    AudioStreamBuilder builder;
-    builder.setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
-    // Don't fall back to SHARED because that would cause recursion.
-    builder.setSharingModeMatchRequired(true);
-    builder.setDeviceId(mRequestedDeviceId);
-    builder.setFormat(configuration.getFormat());
-    builder.setSampleRate(configuration.getSampleRate());
-    builder.setSamplesPerFrame(configuration.getSamplesPerFrame());
-    builder.setDirection(getDirection());
-    builder.setBufferCapacity(DEFAULT_BUFFER_CAPACITY);
-
-    return getStreamInternal()->open(builder);
-}
-
-aaudio_result_t AAudioServiceEndpoint::close() {
-     return getStreamInternal()->close();
-}
-
-// TODO, maybe use an interface to reduce exposure
-aaudio_result_t AAudioServiceEndpoint::registerStream(sp<AAudioServiceStreamShared>sharedStream) {
-    std::lock_guard<std::mutex> lock(mLockStreams);
-    mRegisteredStreams.push_back(sharedStream);
-    return AAUDIO_OK;
-}
-
-aaudio_result_t AAudioServiceEndpoint::unregisterStream(sp<AAudioServiceStreamShared>sharedStream) {
-    std::lock_guard<std::mutex> lock(mLockStreams);
-    mRegisteredStreams.erase(std::remove(mRegisteredStreams.begin(), mRegisteredStreams.end(), sharedStream),
-              mRegisteredStreams.end());
-    return AAUDIO_OK;
-}
-
-aaudio_result_t AAudioServiceEndpoint::startStream(sp<AAudioServiceStreamShared> sharedStream) {
-    aaudio_result_t result = AAUDIO_OK;
-    if (++mRunningStreams == 1) {
-        // TODO use real-time technique to avoid mutex, eg. atomic command FIFO
-        std::lock_guard<std::mutex> lock(mLockStreams);
-        result = getStreamInternal()->requestStart();
-        startSharingThread_l();
-    }
-    return result;
-}
-
-aaudio_result_t AAudioServiceEndpoint::stopStream(sp<AAudioServiceStreamShared> sharedStream) {
-    // Don't lock here because the disconnectRegisteredStreams also uses the lock.
-    if (--mRunningStreams == 0) { // atomic
-        stopSharingThread();
-        getStreamInternal()->requestStop();
-    }
-    return AAUDIO_OK;
-}
-
-static void *aaudio_endpoint_thread_proc(void *context) {
-    AAudioServiceEndpoint *endpoint = (AAudioServiceEndpoint *) context;
-    if (endpoint != NULL) {
-        return endpoint->callbackLoop();
-    } else {
-        return NULL;
-    }
-}
-
-aaudio_result_t AAudioServiceEndpoint::startSharingThread_l() {
-    // Launch the callback loop thread.
-    int64_t periodNanos = getStreamInternal()->getFramesPerBurst()
-                          * AAUDIO_NANOS_PER_SECOND
-                          / getSampleRate();
-    mCallbackEnabled.store(true);
-    return getStreamInternal()->createThread(periodNanos, aaudio_endpoint_thread_proc, this);
-}
-
-aaudio_result_t AAudioServiceEndpoint::stopSharingThread() {
-    mCallbackEnabled.store(false);
-    aaudio_result_t result = getStreamInternal()->joinThread(NULL);
-    return result;
-}
-
 void AAudioServiceEndpoint::disconnectRegisteredStreams() {
     std::lock_guard<std::mutex> lock(mLockStreams);
-    for(auto sharedStream : mRegisteredStreams) {
-        sharedStream->stop();
-        sharedStream->disconnect();
+    for (const auto stream : mRegisteredStreams) {
+        stream->stop();
+        stream->disconnect();
     }
     mRegisteredStreams.clear();
 }
 
+aaudio_result_t AAudioServiceEndpoint::registerStream(sp<AAudioServiceStreamBase>stream) {
+    std::lock_guard<std::mutex> lock(mLockStreams);
+    mRegisteredStreams.push_back(stream);
+    return AAUDIO_OK;
+}
+
+aaudio_result_t AAudioServiceEndpoint::unregisterStream(sp<AAudioServiceStreamBase>stream) {
+    std::lock_guard<std::mutex> lock(mLockStreams);
+    mRegisteredStreams.erase(std::remove(
+            mRegisteredStreams.begin(), mRegisteredStreams.end(), stream),
+                             mRegisteredStreams.end());
+    return AAUDIO_OK;
+}
+
 bool AAudioServiceEndpoint::matches(const AAudioStreamConfiguration& configuration) {
+    if (configuration.getDirection() != getDirection()) {
+        return false;
+    }
     if (configuration.getDeviceId() != AAUDIO_UNSPECIFIED &&
-            configuration.getDeviceId() != mStreamInternal->getDeviceId()) {
+        configuration.getDeviceId() != getDeviceId()) {
         return false;
     }
     if (configuration.getSampleRate() != AAUDIO_UNSPECIFIED &&
-            configuration.getSampleRate() != mStreamInternal->getSampleRate()) {
+        configuration.getSampleRate() != getSampleRate()) {
         return false;
     }
     if (configuration.getSamplesPerFrame() != AAUDIO_UNSPECIFIED &&
-            configuration.getSamplesPerFrame() != mStreamInternal->getSamplesPerFrame()) {
+        configuration.getSamplesPerFrame() != getSamplesPerFrame()) {
         return false;
     }
-
     return true;
 }
-
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index e40a670..2ef6234 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -24,70 +24,93 @@
 
 #include "client/AudioStreamInternal.h"
 #include "client/AudioStreamInternalPlay.h"
+#include "core/AAudioStreamParameters.h"
 #include "binding/AAudioServiceMessage.h"
-#include "AAudioServiceStreamShared.h"
-#include "AAudioServiceStreamMMAP.h"
-#include "AAudioMixer.h"
-#include "AAudioService.h"
+#include "binding/AAudioStreamConfiguration.h"
+
+#include "AAudioServiceStreamBase.h"
 
 namespace aaudio {
 
-class AAudioServiceEndpoint {
+/**
+ * AAudioServiceEndpoint is used by a subclass of AAudioServiceStreamBase
+ * to communicate with the underlying audio device or port.
+ */
+class AAudioServiceEndpoint
+        : public virtual android::RefBase
+        , public AAudioStreamParameters {
 public:
-    virtual ~AAudioServiceEndpoint() = default;
 
-    std::string dump() const;
+    virtual ~AAudioServiceEndpoint();
 
-    virtual aaudio_result_t open(const AAudioStreamConfiguration& configuration);
+    virtual std::string dump() const;
 
-    int32_t getSampleRate() const { return mStreamInternal->getSampleRate(); }
-    int32_t getSamplesPerFrame() const { return mStreamInternal->getSamplesPerFrame();  }
-    int32_t getFramesPerBurst() const { return mStreamInternal->getFramesPerBurst();  }
+    virtual aaudio_result_t open(const aaudio::AAudioStreamRequest &request) = 0;
 
-    aaudio_result_t registerStream(android::sp<AAudioServiceStreamShared> sharedStream);
-    aaudio_result_t unregisterStream(android::sp<AAudioServiceStreamShared> sharedStream);
-    aaudio_result_t startStream(android::sp<AAudioServiceStreamShared> sharedStream);
-    aaudio_result_t stopStream(android::sp<AAudioServiceStreamShared> sharedStream);
-    aaudio_result_t close();
+    virtual aaudio_result_t close() = 0;
+
+    virtual aaudio_result_t registerStream(android::sp<AAudioServiceStreamBase> stream);
+
+    virtual aaudio_result_t unregisterStream(android::sp<AAudioServiceStreamBase> stream);
+
+    virtual aaudio_result_t startStream(android::sp<AAudioServiceStreamBase> stream,
+                                        audio_port_handle_t *clientHandle) = 0;
+
+    virtual aaudio_result_t stopStream(android::sp<AAudioServiceStreamBase> stream,
+                                       audio_port_handle_t clientHandle) = 0;
+
+    virtual aaudio_result_t startClient(const android::AudioClient& client,
+                                        audio_port_handle_t *clientHandle) {
+        ALOGD("AAudioServiceEndpoint::startClient(%p, ...) AAUDIO_ERROR_UNAVAILABLE", &client);
+        return AAUDIO_ERROR_UNAVAILABLE;
+    }
+
+    virtual aaudio_result_t stopClient(audio_port_handle_t clientHandle) {
+        ALOGD("AAudioServiceEndpoint::stopClient(...) AAUDIO_ERROR_UNAVAILABLE");
+        return AAUDIO_ERROR_UNAVAILABLE;
+    }
+
+    /**
+     * @param positionFrames
+     * @param timeNanos
+     * @return AAUDIO_OK or AAUDIO_ERROR_UNAVAILABLE or other negative error
+     */
+    virtual aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) = 0;
+
+    virtual aaudio_result_t getTimestamp(int64_t *positionFrames, int64_t *timeNanos) = 0;
+
+    int32_t getFramesPerBurst() const {
+        return mFramesPerBurst;
+    }
 
     int32_t getRequestedDeviceId() const { return mRequestedDeviceId; }
-    int32_t getDeviceId() const { return mStreamInternal->getDeviceId(); }
-
-    aaudio_direction_t getDirection() const { return mStreamInternal->getDirection(); }
-
-    void disconnectRegisteredStreams();
-
-    virtual void *callbackLoop() = 0;
-
-    // This should only be called from the AAudioEndpointManager under a mutex.
-    int32_t getReferenceCount() const {
-        return mReferenceCount;
-    }
-
-    // This should only be called from the AAudioEndpointManager under a mutex.
-    void setReferenceCount(int32_t count) {
-        mReferenceCount = count;
-    }
 
     bool matches(const AAudioStreamConfiguration& configuration);
 
-    virtual AudioStreamInternal *getStreamInternal() = 0;
+    // This should only be called from the AAudioEndpointManager under a mutex.
+    int32_t getOpenCount() const {
+        return mOpenCount;
+    }
 
-    std::atomic<bool>        mCallbackEnabled{false};
+    // This should only be called from the AAudioEndpointManager under a mutex.
+    void setOpenCount(int32_t count) {
+        mOpenCount = count;
+    }
+
+protected:
+    void                     disconnectRegisteredStreams();
 
     mutable std::mutex       mLockStreams;
+    std::vector<android::sp<AAudioServiceStreamBase>> mRegisteredStreams;
 
-    std::vector<android::sp<AAudioServiceStreamShared>> mRegisteredStreams;
+    SimpleDoubleBuffer<Timestamp>  mAtomicTimestamp;
 
-    std::atomic<int>         mRunningStreams{0};
+    android::AudioClient     mMmapClient;   // set in open, used in open and startStream
 
-private:
-    aaudio_result_t startSharingThread_l();
-    aaudio_result_t stopSharingThread();
-
-    AudioStreamInternal     *mStreamInternal = nullptr;
-    int32_t                  mReferenceCount = 0;
+    int32_t                  mFramesPerBurst = 0;
+    int32_t                  mOpenCount = 0;
     int32_t                  mRequestedDeviceId = 0;
+
 };
 
 } /* namespace aaudio */
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index 6a37330..c7d9b8e 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -30,20 +30,22 @@
 #include "AAudioServiceEndpoint.h"
 #include "AAudioServiceStreamShared.h"
 #include "AAudioServiceEndpointCapture.h"
+#include "AAudioServiceEndpointShared.h"
 
 using namespace android;  // TODO just import names needed
 using namespace aaudio;   // TODO just import names needed
 
 AAudioServiceEndpointCapture::AAudioServiceEndpointCapture(AAudioService &audioService)
         : mStreamInternalCapture(audioService, true) {
+    mStreamInternal = &mStreamInternalCapture;
 }
 
 AAudioServiceEndpointCapture::~AAudioServiceEndpointCapture() {
     delete mDistributionBuffer;
 }
 
-aaudio_result_t AAudioServiceEndpointCapture::open(const AAudioStreamConfiguration& configuration) {
-    aaudio_result_t result = AAudioServiceEndpoint::open(configuration);
+aaudio_result_t AAudioServiceEndpointCapture::open(const aaudio::AAudioStreamRequest &request) {
+    aaudio_result_t result = AAudioServiceEndpointShared::open(request);
     if (result == AAUDIO_OK) {
         delete mDistributionBuffer;
         int distributionBufferSizeBytes = getStreamInternal()->getFramesPerBurst()
@@ -62,6 +64,9 @@
 
     // result might be a frame count
     while (mCallbackEnabled.load() && getStreamInternal()->isActive() && (result >= 0)) {
+
+        int64_t mmapFramesRead = getStreamInternal()->getFramesRead();
+
         // Read audio data from stream using a blocking read.
         result = getStreamInternal()->read(mDistributionBuffer, getFramesPerBurst(), timeoutNanos);
         if (result == AAUDIO_ERROR_DISCONNECTED) {
@@ -74,18 +79,47 @@
         }
 
         // Distribute data to each active stream.
-        { // use lock guard
+        { // brackets are for lock_guard
+
             std::lock_guard <std::mutex> lock(mLockStreams);
-            for (sp<AAudioServiceStreamShared> sharedStream : mRegisteredStreams) {
-                if (sharedStream->isRunning()) {
-                    FifoBuffer *fifo = sharedStream->getDataFifoBuffer();
-                    if (fifo->getFifoControllerBase()->getEmptyFramesAvailable() <
-                        getFramesPerBurst()) {
-                        underflowCount++;
-                    } else {
-                        fifo->write(mDistributionBuffer, getFramesPerBurst());
+            for (const auto clientStream : mRegisteredStreams) {
+                if (clientStream->isRunning()) {
+                    int64_t clientFramesWritten = 0;
+                    sp<AAudioServiceStreamShared> streamShared =
+                            static_cast<AAudioServiceStreamShared *>(clientStream.get());
+
+                    {
+                        // Lock the AudioFifo to protect against close.
+                        std::lock_guard <std::mutex> lock(streamShared->getAudioDataQueueLock());
+
+                        FifoBuffer *fifo = streamShared->getAudioDataFifoBuffer_l();
+                        if (fifo != nullptr) {
+
+                            // Determine offset between framePosition in client's stream
+                            // vs the underlying MMAP stream.
+                            clientFramesWritten = fifo->getWriteCounter();
+                            // There are two indices that refer to the same frame.
+                            int64_t positionOffset = mmapFramesRead - clientFramesWritten;
+                            streamShared->setTimestampPositionOffset(positionOffset);
+
+                            if (fifo->getFifoControllerBase()->getEmptyFramesAvailable() <
+                                getFramesPerBurst()) {
+                                underflowCount++;
+                            } else {
+                                fifo->write(mDistributionBuffer, getFramesPerBurst());
+                            }
+                            clientFramesWritten = fifo->getWriteCounter();
+                        }
                     }
-                    sharedStream->markTransferTime(AudioClock::getNanoseconds());
+
+                    if (clientFramesWritten > 0) {
+                        // This timestamp represents the completion of data being written into the
+                        // client buffer. It is sent to the client and used in the timing model
+                        // to decide when data will be available to read.
+                        Timestamp timestamp(clientFramesWritten, AudioClock::getNanoseconds());
+                        streamShared->markTransferTime(timestamp);
+                    }
+
                 }
             }
         }
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.h b/services/oboeservice/AAudioServiceEndpointCapture.h
index 8a3d72f..971da9a 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.h
+++ b/services/oboeservice/AAudioServiceEndpointCapture.h
@@ -20,18 +20,18 @@
 #include "client/AudioStreamInternal.h"
 #include "client/AudioStreamInternalCapture.h"
 
+#include "AAudioServiceEndpointShared.h"
+#include "AAudioServiceStreamShared.h"
+
 namespace aaudio {
 
-class AAudioServiceEndpointCapture : public AAudioServiceEndpoint {
+class AAudioServiceEndpointCapture : public AAudioServiceEndpointShared {
 public:
     explicit AAudioServiceEndpointCapture(android::AAudioService &audioService);
     virtual ~AAudioServiceEndpointCapture();
 
-    aaudio_result_t open(const AAudioStreamConfiguration& configuration) override;
+    aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
 
-    AudioStreamInternal *getStreamInternal() override {
-        return &mStreamInternalCapture;
-    }
 
     void *callbackLoop() override;
 
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
new file mode 100644
index 0000000..4be25c8
--- /dev/null
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AAudioServiceEndpointMMAP"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <algorithm>
+#include <assert.h>
+#include <map>
+#include <mutex>
+#include <sstream>
+#include <utils/Singleton.h>
+#include <vector>
+
+
+#include "AAudioEndpointManager.h"
+#include "AAudioServiceEndpoint.h"
+
+#include "core/AudioStreamBuilder.h"
+#include "AAudioServiceEndpoint.h"
+#include "AAudioServiceStreamShared.h"
+#include "AAudioServiceEndpointPlay.h"
+#include "AAudioServiceEndpointMMAP.h"
+
+
+#define AAUDIO_BUFFER_CAPACITY_MIN    4 * 512
+#define AAUDIO_SAMPLE_RATE_DEFAULT    48000
+
+// This is an estimate of the time difference between the HW and the MMAP time.
+// TODO Get presentation timestamps from the HAL instead of using these estimates.
+#define OUTPUT_ESTIMATED_HARDWARE_OFFSET_NANOS  (3 * AAUDIO_NANOS_PER_MILLISECOND)
+#define INPUT_ESTIMATED_HARDWARE_OFFSET_NANOS   (-1 * AAUDIO_NANOS_PER_MILLISECOND)
+
+using namespace android;  // TODO just import names needed
+using namespace aaudio;   // TODO just import names needed
+
+AAudioServiceEndpointMMAP::AAudioServiceEndpointMMAP()
+        :  mMmapStream(nullptr) {}
+
+AAudioServiceEndpointMMAP::~AAudioServiceEndpointMMAP() {}
+
+std::string AAudioServiceEndpointMMAP::dump() const {
+    std::stringstream result;
+
+    result << "  MMAP: framesTransferred = " << mFramesTransferred.get();
+    result << ", HW nanos = " << mHardwareTimeOffsetNanos;
+    result << ", port handle = " << mPortHandle;
+    result << ", audio data FD = " << mAudioDataFileDescriptor;
+    result << "\n";
+
+    result << "    HW Offset Micros:     " <<
+                                      (getHardwareTimeOffsetNanos()
+                                       / AAUDIO_NANOS_PER_MICROSECOND) << "\n";
+
+    result << AAudioServiceEndpoint::dump();
+    return result.str();
+}
+
+aaudio_result_t AAudioServiceEndpointMMAP::open(const aaudio::AAudioStreamRequest &request) {
+    aaudio_result_t result = AAUDIO_OK;
+    const audio_attributes_t attributes = {
+            .content_type = AUDIO_CONTENT_TYPE_MUSIC,
+            .usage = AUDIO_USAGE_MEDIA,
+            .source = AUDIO_SOURCE_VOICE_RECOGNITION,
+            .flags = AUDIO_FLAG_LOW_LATENCY,
+            .tags = ""
+    };
+    audio_config_base_t config;
+    audio_port_handle_t deviceId;
+
+    int32_t burstMinMicros = AAudioProperty_getHardwareBurstMinMicros();
+    int32_t burstMicros = 0;
+
+    copyFrom(request.getConstantConfiguration());
+
+    mMmapClient.clientUid = request.getUserId();
+    mMmapClient.clientPid = request.getProcessId();
+    mMmapClient.packageName.setTo(String16(""));
+
+    mRequestedDeviceId = deviceId = getDeviceId();
+
+    // Fill in config
+    aaudio_format_t aaudioFormat = getFormat();
+    if (aaudioFormat == AAUDIO_UNSPECIFIED || aaudioFormat == AAUDIO_FORMAT_PCM_FLOAT) {
+        aaudioFormat = AAUDIO_FORMAT_PCM_I16;
+    }
+    config.format = AAudioConvert_aaudioToAndroidDataFormat(aaudioFormat);
+
+    int32_t aaudioSampleRate = getSampleRate();
+    if (aaudioSampleRate == AAUDIO_UNSPECIFIED) {
+        aaudioSampleRate = AAUDIO_SAMPLE_RATE_DEFAULT;
+    }
+    config.sample_rate = aaudioSampleRate;
+
+    int32_t aaudioSamplesPerFrame = getSamplesPerFrame();
+
+    aaudio_direction_t direction = getDirection();
+    if (direction == AAUDIO_DIRECTION_OUTPUT) {
+        config.channel_mask = (aaudioSamplesPerFrame == AAUDIO_UNSPECIFIED)
+                              ? AUDIO_CHANNEL_OUT_STEREO
+                              : audio_channel_out_mask_from_count(aaudioSamplesPerFrame);
+        mHardwareTimeOffsetNanos = OUTPUT_ESTIMATED_HARDWARE_OFFSET_NANOS; // frames at DAC later
+
+    } else if (direction == AAUDIO_DIRECTION_INPUT) {
+        config.channel_mask =  (aaudioSamplesPerFrame == AAUDIO_UNSPECIFIED)
+                               ? AUDIO_CHANNEL_IN_STEREO
+                               : audio_channel_in_mask_from_count(aaudioSamplesPerFrame);
+        mHardwareTimeOffsetNanos = INPUT_ESTIMATED_HARDWARE_OFFSET_NANOS; // frames at ADC earlier
+
+    } else {
+        ALOGE("openMmapStream - invalid direction = %d", direction);
+        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+    }
+
+    MmapStreamInterface::stream_direction_t streamDirection =
+            (direction == AAUDIO_DIRECTION_OUTPUT)
+            ? MmapStreamInterface::DIRECTION_OUTPUT
+            : MmapStreamInterface::DIRECTION_INPUT;
+
+    // Open HAL stream. Set mMmapStream
+    status_t status = MmapStreamInterface::openMmapStream(streamDirection,
+                                                          &attributes,
+                                                          &config,
+                                                          mMmapClient,
+                                                          &deviceId,
+                                                          this, // callback
+                                                          mMmapStream,
+                                                          &mPortHandle);
+    ALOGD("AAudioServiceEndpointMMAP::open() mMapClient.uid = %d, pid = %d => portHandle = %d\n",
+          mMmapClient.clientUid,  mMmapClient.clientPid, mPortHandle);
+    if (status != OK) {
+        ALOGE("openMmapStream returned status %d", status);
+        return AAUDIO_ERROR_UNAVAILABLE;
+    }
+
+    if (deviceId == AAUDIO_UNSPECIFIED) {
+        ALOGW("AAudioServiceEndpointMMAP::open() - openMmapStream() failed to set deviceId");
+    }
+    setDeviceId(deviceId);
+
+    // Create MMAP/NOIRQ buffer.
+    int32_t minSizeFrames = getBufferCapacity();
+    if (minSizeFrames <= 0) { // zero will get rejected
+        minSizeFrames = AAUDIO_BUFFER_CAPACITY_MIN;
+    }
+    status = mMmapStream->createMmapBuffer(minSizeFrames, &mMmapBufferinfo);
+    if (status != OK) {
+        ALOGE("AAudioServiceEndpointMMAP::open() - createMmapBuffer() failed with status %d %s",
+              status, strerror(-status));
+        result = AAUDIO_ERROR_UNAVAILABLE;
+        goto error;
+    } else {
+        ALOGD("createMmapBuffer status = %d, buffer_size = %d, burst_size %d"
+                      ", Sharable FD: %s",
+              status,
+              abs(mMmapBufferinfo.buffer_size_frames),
+              mMmapBufferinfo.burst_size_frames,
+              mMmapBufferinfo.buffer_size_frames < 0 ? "Yes" : "No");
+    }
+
+    setBufferCapacity(mMmapBufferinfo.buffer_size_frames);
+    // The audio HAL indicates if the shared memory fd can be shared outside of audioserver
+    // by returning a negative buffer size
+    if (getBufferCapacity() < 0) {
+        // Exclusive mode can be used by client or service.
+        setBufferCapacity(-getBufferCapacity());
+    } else {
+        // Exclusive mode can only be used by the service because the FD cannot be shared.
+        uid_t audioServiceUid = getuid();
+        if ((mMmapClient.clientUid != audioServiceUid) &&
+            getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
+            // Fallback is handled by caller but indicate what is possible in case
+            // this is used in the future
+            setSharingMode(AAUDIO_SHARING_MODE_SHARED);
+            ALOGW("AAudioServiceEndpointMMAP::open() - exclusive FD cannot be used by client");
+            result = AAUDIO_ERROR_UNAVAILABLE;
+            goto error;
+        }
+    }
+
+    // Get information about the stream and pass it back to the caller.
+    setSamplesPerFrame((direction == AAUDIO_DIRECTION_OUTPUT)
+                       ? audio_channel_count_from_out_mask(config.channel_mask)
+                       : audio_channel_count_from_in_mask(config.channel_mask));
+
+    // AAudio creates a copy of this FD and retains ownership of the copy.
+    // Assume that AudioFlinger will close the original shared_memory_fd.
+    mAudioDataFileDescriptor.reset(dup(mMmapBufferinfo.shared_memory_fd));
+    if (mAudioDataFileDescriptor.get() == -1) {
+        ALOGE("AAudioServiceEndpointMMAP::open() - could not dup shared_memory_fd");
+        result = AAUDIO_ERROR_INTERNAL;
+        goto error;
+    }
+    mFramesPerBurst = mMmapBufferinfo.burst_size_frames;
+    setFormat(AAudioConvert_androidToAAudioDataFormat(config.format));
+    setSampleRate(config.sample_rate);
+
+    // Scale up the burst size to meet the minimum equivalent in microseconds.
+    // This is to avoid waking the CPU too often when the HW burst is very small
+    // or at high sample rates.
+    do {
+        if (burstMicros > 0) {  // skip first loop
+            mFramesPerBurst *= 2;
+        }
+        burstMicros = mFramesPerBurst * static_cast<int64_t>(1000000) / getSampleRate();
+    } while (burstMicros < burstMinMicros);
+
+    ALOGD("AAudioServiceEndpointMMAP::open() original burst = %d, minMicros = %d, to burst = %d\n",
+          mMmapBufferinfo.burst_size_frames, burstMinMicros, mFramesPerBurst);
+
+    ALOGD("AAudioServiceEndpointMMAP::open() actual rate = %d, channels = %d"
+          ", deviceId = %d, capacity = %d\n",
+          getSampleRate(), getSamplesPerFrame(), deviceId, getBufferCapacity());
+
+    return result;
+
+error:
+    close();
+    return result;
+}
+
+aaudio_result_t AAudioServiceEndpointMMAP::close() {
+
+    if (mMmapStream != 0) {
+        ALOGD("AAudioServiceEndpointMMAP::close() clear() endpoint");
+        // Needs to be explicitly cleared or CTS will fail but it is not clear why.
+        mMmapStream.clear();
+        // Apparently the above close is asynchronous. An attempt to open a new device
+        // right after a close can fail. Also some callbacks may still be in flight!
+        // FIXME Make closing synchronous.
+        AudioClock::sleepForNanos(100 * AAUDIO_NANOS_PER_MILLISECOND);
+    }
+
+    return AAUDIO_OK;
+}
+
+aaudio_result_t AAudioServiceEndpointMMAP::startStream(sp<AAudioServiceStreamBase> stream,
+                                                   audio_port_handle_t *clientHandle) {
+    // Start the client on behalf of the AAudio service.
+    // Use the port handle that was provided by openMmapStream().
+    return startClient(mMmapClient, &mPortHandle);
+}
+
+aaudio_result_t AAudioServiceEndpointMMAP::stopStream(sp<AAudioServiceStreamBase> stream,
+                                                  audio_port_handle_t clientHandle) {
+    mFramesTransferred.reset32();
+    return stopClient(mPortHandle);
+}
+
+aaudio_result_t AAudioServiceEndpointMMAP::startClient(const android::AudioClient& client,
+                                                       audio_port_handle_t *clientHandle) {
+    if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
+    ALOGD("AAudioServiceEndpointMMAP::startClient(%p(uid=%d, pid=%d))",
+          &client, client.clientUid, client.clientPid);
+    audio_port_handle_t originalHandle =  *clientHandle;
+    status_t status = mMmapStream->start(client, clientHandle);
+    aaudio_result_t result = AAudioConvert_androidToAAudioResult(status);
+    ALOGD("AAudioServiceEndpointMMAP::startClient() , %d => %d returns %d",
+          originalHandle, *clientHandle, result);
+    return result;
+}
+
+aaudio_result_t AAudioServiceEndpointMMAP::stopClient(audio_port_handle_t clientHandle) {
+    if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
+    aaudio_result_t result = AAudioConvert_androidToAAudioResult(mMmapStream->stop(clientHandle));
+    ALOGD("AAudioServiceEndpointMMAP::stopClient(%d) returns %d", clientHandle, result);
+    return result;
+}
+
+// Get free-running DSP or DMA hardware position from the HAL.
+aaudio_result_t AAudioServiceEndpointMMAP::getFreeRunningPosition(int64_t *positionFrames,
+                                                                int64_t *timeNanos) {
+    struct audio_mmap_position position;
+    if (mMmapStream == nullptr) {
+        return AAUDIO_ERROR_NULL;
+    }
+    status_t status = mMmapStream->getMmapPosition(&position);
+    ALOGV("AAudioServiceEndpointMMAP::getFreeRunningPosition() status= %d, pos = %d, nanos = %lld\n",
+          status, position.position_frames, (long long) position.time_nanoseconds);
+    aaudio_result_t result = AAudioConvert_androidToAAudioResult(status);
+    if (result == AAUDIO_ERROR_UNAVAILABLE) {
+        ALOGW("sendCurrentTimestamp(): getMmapPosition() has no position data available");
+    } else if (result != AAUDIO_OK) {
+        ALOGE("sendCurrentTimestamp(): getMmapPosition() returned status %d", status);
+    } else {
+        // Convert 32-bit position to 64-bit position.
+        mFramesTransferred.update32(position.position_frames);
+        *positionFrames = mFramesTransferred.get();
+        *timeNanos = position.time_nanoseconds;
+    }
+    return result;
+}
+
+aaudio_result_t AAudioServiceEndpointMMAP::getTimestamp(int64_t *positionFrames,
+                                                    int64_t *timeNanos) {
+    return 0; // TODO
+}
+
+
+void AAudioServiceEndpointMMAP::onTearDown() {
+    ALOGD("AAudioServiceEndpointMMAP::onTearDown() called");
+    disconnectRegisteredStreams();
+};
+
+void AAudioServiceEndpointMMAP::onVolumeChanged(audio_channel_mask_t channels,
+                                              android::Vector<float> values) {
+    // TODO do we really need a different volume for each channel?
+    float volume = values[0];
+    ALOGD("AAudioServiceEndpointMMAP::onVolumeChanged() volume[0] = %f", volume);
+    std::lock_guard<std::mutex> lock(mLockStreams);
+    for(const auto stream : mRegisteredStreams) {
+        stream->onVolumeChanged(volume);
+    }
+};
+
+void AAudioServiceEndpointMMAP::onRoutingChanged(audio_port_handle_t deviceId) {
+    ALOGD("AAudioServiceEndpointMMAP::onRoutingChanged() called with %d, old = %d",
+          deviceId, getDeviceId());
+    if (getDeviceId() != AUDIO_PORT_HANDLE_NONE  && getDeviceId() != deviceId) {
+        disconnectRegisteredStreams();
+    }
+    setDeviceId(deviceId);
+};
+
+/**
+ * Get an immutable description of the data queue from the HAL.
+ */
+aaudio_result_t AAudioServiceEndpointMMAP::getDownDataDescription(AudioEndpointParcelable &parcelable)
+{
+    // Gather information on the data queue based on HAL info.
+    int32_t bytesPerFrame = calculateBytesPerFrame();
+    int32_t capacityInBytes = getBufferCapacity() * bytesPerFrame;
+    int fdIndex = parcelable.addFileDescriptor(mAudioDataFileDescriptor, capacityInBytes);
+    parcelable.mDownDataQueueParcelable.setupMemory(fdIndex, 0, capacityInBytes);
+    parcelable.mDownDataQueueParcelable.setBytesPerFrame(bytesPerFrame);
+    parcelable.mDownDataQueueParcelable.setFramesPerBurst(mFramesPerBurst);
+    parcelable.mDownDataQueueParcelable.setCapacityInFrames(getBufferCapacity());
+    return AAUDIO_OK;
+}
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
new file mode 100644
index 0000000..16b6269
--- /dev/null
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAUDIO_SERVICE_ENDPOINT_MMAP_H
+#define AAUDIO_SERVICE_ENDPOINT_MMAP_H
+
+#include <atomic>
+#include <functional>
+#include <mutex>
+#include <vector>
+
+#include "client/AudioStreamInternal.h"
+#include "client/AudioStreamInternalPlay.h"
+#include "binding/AAudioServiceMessage.h"
+#include "AAudioServiceEndpointShared.h"
+#include "AAudioServiceStreamShared.h"
+#include "AAudioServiceStreamMMAP.h"
+#include "AAudioMixer.h"
+#include "AAudioService.h"
+
+namespace aaudio {
+
+/**
+ * This is used by AAudioServiceStreamMMAP to access the MMAP devices
+ * through AudioFlinger.
+ */
+class AAudioServiceEndpointMMAP
+        : public AAudioServiceEndpoint
+        , public android::MmapStreamCallback {
+
+public:
+    AAudioServiceEndpointMMAP();
+
+    virtual ~AAudioServiceEndpointMMAP();
+
+    std::string dump() const override;
+
+    aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
+
+    aaudio_result_t close() override;
+
+    aaudio_result_t startStream(android::sp<AAudioServiceStreamBase> stream,
+                                audio_port_handle_t *clientHandle) override;
+
+    aaudio_result_t stopStream(android::sp<AAudioServiceStreamBase> stream,
+                               audio_port_handle_t clientHandle) override;
+
+    aaudio_result_t startClient(const android::AudioClient& client,
+                                        audio_port_handle_t *clientHandle)  override;
+
+    aaudio_result_t stopClient(audio_port_handle_t clientHandle)  override;
+
+    aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) override;
+
+    aaudio_result_t getTimestamp(int64_t *positionFrames, int64_t *timeNanos) override;
+
+    // -------------- Callback functions for MmapStreamCallback ---------------------
+    void onTearDown() override;
+
+    void onVolumeChanged(audio_channel_mask_t channels,
+                         android::Vector<float> values) override;
+
+    void onRoutingChanged(audio_port_handle_t deviceId) override;
+    // ------------------------------------------------------------------------------
+
+    aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable);
+
+    int64_t getHardwareTimeOffsetNanos() const {
+        return mHardwareTimeOffsetNanos;
+    }
+
+private:
+    MonotonicCounter                          mFramesTransferred;
+
+    // Interface to the AudioFlinger MMAP support.
+    android::sp<android::MmapStreamInterface> mMmapStream;
+    struct audio_mmap_buffer_info             mMmapBufferinfo;
+    audio_port_handle_t                       mPortHandle = AUDIO_PORT_HANDLE_NONE;
+
+    android::base::unique_fd                  mAudioDataFileDescriptor;
+
+    int64_t                                   mHardwareTimeOffsetNanos = 0; // TODO get from HAL
+
+};
+
+} /* namespace aaudio */
+
+#endif //AAUDIO_SERVICE_ENDPOINT_MMAP_H
+
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index b83b918..9b1833a 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AAudioService"
+#define LOG_TAG "AAudioServiceEndpointPlay"
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
@@ -33,6 +33,7 @@
 #include "AAudioServiceEndpoint.h"
 #include "AAudioServiceStreamShared.h"
 #include "AAudioServiceEndpointPlay.h"
+#include "AAudioServiceEndpointShared.h"
 
 using namespace android;  // TODO just import names needed
 using namespace aaudio;   // TODO just import names needed
@@ -41,13 +42,14 @@
 
 AAudioServiceEndpointPlay::AAudioServiceEndpointPlay(AAudioService &audioService)
         : mStreamInternalPlay(audioService, true) {
+    mStreamInternal = &mStreamInternalPlay;
 }
 
 AAudioServiceEndpointPlay::~AAudioServiceEndpointPlay() {
 }
 
-aaudio_result_t AAudioServiceEndpointPlay::open(const AAudioStreamConfiguration& configuration) {
-    aaudio_result_t result = AAudioServiceEndpoint::open(configuration);
+aaudio_result_t AAudioServiceEndpointPlay::open(const aaudio::AAudioStreamRequest &request) {
+    aaudio_result_t result = AAudioServiceEndpointShared::open(request);
     if (result == AAUDIO_OK) {
         mMixer.allocate(getStreamInternal()->getSamplesPerFrame(),
                         getStreamInternal()->getFramesPerBurst());
@@ -65,7 +67,6 @@
 
 // Mix data from each application stream and write result to the shared MMAP stream.
 void *AAudioServiceEndpointPlay::callbackLoop() {
-    int32_t underflowCount = 0;
     aaudio_result_t result = AAUDIO_OK;
     int64_t timeoutNanos = getStreamInternal()->calculateReasonableTimeout();
 
@@ -73,19 +74,54 @@
     while (mCallbackEnabled.load() && getStreamInternal()->isActive() && (result >= 0)) {
         // Mix data from each active stream.
         mMixer.clear();
-        { // use lock guard
+
+        { // brackets are for lock_guard
             int index = 0;
+            int64_t mmapFramesWritten = getStreamInternal()->getFramesWritten();
+
             std::lock_guard <std::mutex> lock(mLockStreams);
-            for (sp<AAudioServiceStreamShared> sharedStream : mRegisteredStreams) {
-                if (sharedStream->isRunning()) {
-                    FifoBuffer *fifo = sharedStream->getDataFifoBuffer();
-                    float volume = 1.0; // to match legacy volume
-                    bool underflowed = mMixer.mix(index, fifo, volume);
-                    underflowCount += underflowed ? 1 : 0;
-                    // TODO log underflows in each stream
-                    sharedStream->markTransferTime(AudioClock::getNanoseconds());
+            for (const auto clientStream : mRegisteredStreams) {
+                int64_t clientFramesRead = 0;
+
+                if (!clientStream->isRunning()) {
+                    continue;
                 }
-                index++;
+
+                sp<AAudioServiceStreamShared> streamShared =
+                        static_cast<AAudioServiceStreamShared *>(clientStream.get());
+
+                {
+                    // Lock the AudioFifo to protect against close.
+                    std::lock_guard <std::mutex> lock(streamShared->getAudioDataQueueLock());
+
+                    FifoBuffer *fifo = streamShared->getAudioDataFifoBuffer_l();
+                    if (fifo != nullptr) {
+
+                        // Determine offset between framePosition in client's stream
+                        // vs the underlying MMAP stream.
+                        clientFramesRead = fifo->getReadCounter();
+                        // These two indices refer to the same frame.
+                        int64_t positionOffset = mmapFramesWritten - clientFramesRead;
+                        streamShared->setTimestampPositionOffset(positionOffset);
+
+                        float volume = 1.0; // to match legacy volume
+                        bool underflowed = mMixer.mix(index, fifo, volume);
+                        if (underflowed) {
+                            streamShared->incrementXRunCount();
+                        }
+                        clientFramesRead = fifo->getReadCounter();
+                    }
+                }
+
+                if (clientFramesRead > 0) {
+                    // This timestamp represents the completion of data being read out of the
+                    // client buffer. It is sent to the client and used in the timing model
+                    // to decide when the client has room to write more data.
+                    Timestamp timestamp(clientFramesRead, AudioClock::getNanoseconds());
+                    streamShared->markTransferTime(timestamp);
+                }
+
+                index++; // just used for labelling tracks in systrace
             }
         }
 
@@ -93,7 +129,7 @@
         result = getStreamInternal()->write(mMixer.getOutputBuffer(),
                                             getFramesPerBurst(), timeoutNanos);
         if (result == AAUDIO_ERROR_DISCONNECTED) {
-            disconnectRegisteredStreams();
+            AAudioServiceEndpointShared::disconnectRegisteredStreams();
             break;
         } else if (result != getFramesPerBurst()) {
             ALOGW("AAudioServiceEndpoint(): callbackLoop() wrote %d / %d",
@@ -102,8 +138,5 @@
         }
     }
 
-    ALOGW_IF((underflowCount > 0),
-             "AAudioServiceEndpointPlay(): callbackLoop() had %d underflows", underflowCount);
-
     return NULL; // TODO review
 }
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.h b/services/oboeservice/AAudioServiceEndpointPlay.h
index c22f510..a0a383c 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.h
+++ b/services/oboeservice/AAudioServiceEndpointPlay.h
@@ -25,6 +25,7 @@
 #include "client/AudioStreamInternal.h"
 #include "client/AudioStreamInternalPlay.h"
 #include "binding/AAudioServiceMessage.h"
+#include "AAudioServiceEndpointShared.h"
 #include "AAudioServiceStreamShared.h"
 #include "AAudioServiceStreamMMAP.h"
 #include "AAudioMixer.h"
@@ -35,16 +36,12 @@
 /**
  * Contains a mixer and a stream for writing the result of the mix.
  */
-class AAudioServiceEndpointPlay : public AAudioServiceEndpoint {
+class AAudioServiceEndpointPlay : public AAudioServiceEndpointShared {
 public:
     explicit AAudioServiceEndpointPlay(android::AAudioService &audioService);
     virtual ~AAudioServiceEndpointPlay();
 
-    aaudio_result_t open(const AAudioStreamConfiguration& configuration) override;
-
-    AudioStreamInternal *getStreamInternal() override {
-        return &mStreamInternalPlay;
-    }
+    aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
 
     void *callbackLoop() override;
 
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
new file mode 100644
index 0000000..cd40066
--- /dev/null
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#define LOG_TAG "AAudioServiceEndpointShared"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+#include "binding/AAudioServiceMessage.h"
+#include "client/AudioStreamInternal.h"
+#include "client/AudioStreamInternalPlay.h"
+#include "core/AudioStreamBuilder.h"
+
+#include "AAudioServiceEndpointShared.h"
+#include "AAudioServiceStreamShared.h"
+#include "AAudioServiceStreamMMAP.h"
+#include "AAudioMixer.h"
+#include "AAudioService.h"
+
+using namespace android;
+using namespace aaudio;
+
+// This is the maximum size in frames. The effective size can be tuned smaller at runtime.
+#define DEFAULT_BUFFER_CAPACITY   (48 * 8)
+
+std::string AAudioServiceEndpointShared::dump() const {
+    std::stringstream result;
+
+    result << "  SHARED: sharing exclusive stream with handle = 0x"
+           << std::setfill('0') << std::setw(8)
+           << std::hex << mStreamInternal->getServiceHandle()
+           << std::dec << std::setfill(' ');
+    result << "\n";
+    result << "    Running Stream Count: " << mRunningStreamCount << "\n";
+
+    result << AAudioServiceEndpoint::dump();
+    return result.str();
+}
+
+// Share an AudioStreamInternal.
+aaudio_result_t AAudioServiceEndpointShared::open(const aaudio::AAudioStreamRequest &request) {
+    aaudio_result_t result = AAUDIO_OK;
+    const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
+
+    mRequestedDeviceId = configuration.getDeviceId();
+    setDirection(configuration.getDirection());
+
+    AudioStreamBuilder builder;
+    builder.setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
+    // Don't fall back to SHARED because that would cause recursion.
+    builder.setSharingModeMatchRequired(true);
+    builder.setDeviceId(mRequestedDeviceId);
+    builder.setFormat(configuration.getFormat());
+    builder.setSampleRate(configuration.getSampleRate());
+    builder.setSamplesPerFrame(configuration.getSamplesPerFrame());
+    builder.setDirection(configuration.getDirection());
+    builder.setBufferCapacity(DEFAULT_BUFFER_CAPACITY);
+
+    result = mStreamInternal->open(builder);
+
+    setSampleRate(mStreamInternal->getSampleRate());
+    setSamplesPerFrame(mStreamInternal->getSamplesPerFrame());
+    setDeviceId(mStreamInternal->getDeviceId());
+    mFramesPerBurst = mStreamInternal->getFramesPerBurst();
+
+    return result;
+}
+
+aaudio_result_t AAudioServiceEndpointShared::close() {
+    return getStreamInternal()->close();
+}
+
+// Glue between C and C++ callbacks.
+static void *aaudio_endpoint_thread_proc(void *context) {
+    AAudioServiceEndpointShared *endpoint = (AAudioServiceEndpointShared *) context;
+    if (endpoint != NULL) {
+        return endpoint->callbackLoop();
+    } else {
+        return NULL;
+    }
+}
+
+aaudio_result_t aaudio::AAudioServiceEndpointShared::startSharingThread_l() {
+    // Launch the callback loop thread.
+    int64_t periodNanos = getStreamInternal()->getFramesPerBurst()
+                          * AAUDIO_NANOS_PER_SECOND
+                          / getSampleRate();
+    mCallbackEnabled.store(true);
+    return getStreamInternal()->createThread(periodNanos, aaudio_endpoint_thread_proc, this);
+}
+
+aaudio_result_t aaudio::AAudioServiceEndpointShared::stopSharingThread() {
+    mCallbackEnabled.store(false);
+    aaudio_result_t result = getStreamInternal()->joinThread(NULL);
+    return result;
+}
+
+aaudio_result_t AAudioServiceEndpointShared::startStream(sp<AAudioServiceStreamBase> sharedStream,
+                                                         audio_port_handle_t *clientHandle) {
+    aaudio_result_t result = AAUDIO_OK;
+
+    {
+        std::lock_guard<std::mutex> lock(mLockStreams);
+        if (++mRunningStreamCount == 1) { // atomic
+            result = getStreamInternal()->requestStart();
+            if (result != AAUDIO_OK) {
+                --mRunningStreamCount;
+            } else {
+                result = startSharingThread_l();
+                if (result != AAUDIO_OK) {
+                    getStreamInternal()->requestStop();
+                    --mRunningStreamCount;
+                }
+            }
+        }
+    }
+
+    if (result == AAUDIO_OK) {
+        result = getStreamInternal()->startClient(sharedStream->getAudioClient(), clientHandle);
+        if (result != AAUDIO_OK) {
+            if (--mRunningStreamCount == 0) { // atomic
+                stopSharingThread();
+                getStreamInternal()->requestStop();
+            }
+        }
+    }
+
+    return result;
+}
+
+aaudio_result_t AAudioServiceEndpointShared::stopStream(sp<AAudioServiceStreamBase> sharedStream,
+                                                        audio_port_handle_t clientHandle) {
+    // Don't lock here because the disconnectRegisteredStreams also uses the lock.
+
+    // Ignore result.
+    (void) getStreamInternal()->stopClient(clientHandle);
+
+    if (--mRunningStreamCount == 0) { // atomic
+        stopSharingThread();
+        getStreamInternal()->requestStop();
+    }
+    return AAUDIO_OK;
+}
+
+// Get timestamp that was written by the real-time service thread, eg. mixer.
+aaudio_result_t AAudioServiceEndpointShared::getFreeRunningPosition(int64_t *positionFrames,
+                                                                  int64_t *timeNanos) {
+    if (mAtomicTimestamp.isValid()) {
+        Timestamp timestamp = mAtomicTimestamp.read();
+        *positionFrames = timestamp.getPosition();
+        *timeNanos = timestamp.getNanoseconds();
+        return AAUDIO_OK;
+    } else {
+        return AAUDIO_ERROR_UNAVAILABLE;
+    }
+}
+
+aaudio_result_t AAudioServiceEndpointShared::getTimestamp(int64_t *positionFrames,
+                                                          int64_t *timeNanos) {
+    return mStreamInternal->getTimestamp(CLOCK_MONOTONIC, positionFrames, timeNanos);
+}
diff --git a/services/oboeservice/AAudioServiceEndpointShared.h b/services/oboeservice/AAudioServiceEndpointShared.h
new file mode 100644
index 0000000..e3bd2c1
--- /dev/null
+++ b/services/oboeservice/AAudioServiceEndpointShared.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAUDIO_SERVICE_ENDPOINT_SHARED_H
+#define AAUDIO_SERVICE_ENDPOINT_SHARED_H
+
+#include <atomic>
+#include <mutex>
+
+#include "AAudioServiceEndpoint.h"
+#include "client/AudioStreamInternal.h"
+#include "client/AudioStreamInternalPlay.h"
+#include "AAudioServiceStreamShared.h"
+#include "AAudioServiceStreamMMAP.h"
+#include "AAudioService.h"
+
+namespace aaudio {
+
+/**
+ * This Service class corresponds to a Client stream that shares an MMAP device through a mixer
+ * or an input distributor.
+ */
+class AAudioServiceEndpointShared : public AAudioServiceEndpoint {
+
+public:
+
+    std::string dump() const override;
+
+    aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
+
+    aaudio_result_t close() override;
+
+    aaudio_result_t startStream(android::sp<AAudioServiceStreamBase> stream,
+                                audio_port_handle_t *clientHandle) override;
+
+    aaudio_result_t stopStream(android::sp<AAudioServiceStreamBase> stream,
+                               audio_port_handle_t clientHandle) override;
+
+    aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) override;
+
+    aaudio_result_t getTimestamp(int64_t *positionFrames, int64_t *timeNanos) override;
+
+    virtual void            *callbackLoop() = 0;
+
+    AudioStreamInternal *getStreamInternal() const {
+        return mStreamInternal;
+    };
+
+protected:
+
+    aaudio_result_t          startSharingThread_l();
+
+    aaudio_result_t          stopSharingThread();
+
+    // pointer to object statically allocated in subclasses
+    AudioStreamInternal     *mStreamInternal = nullptr;
+
+    std::atomic<bool>        mCallbackEnabled{false};
+
+    std::atomic<int>         mRunningStreamCount{0};
+};
+
+}
+
+#endif //AAUDIO_SERVICE_ENDPOINT_SHARED_H
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 5f7d179..e670129 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -18,12 +18,17 @@
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
+#include <iomanip>
+#include <iostream>
 #include <mutex>
 
 #include "binding/IAAudioService.h"
 #include "binding/AAudioServiceMessage.h"
 #include "utility/AudioClock.h"
 
+#include "AAudioEndpointManager.h"
+#include "AAudioService.h"
+#include "AAudioServiceEndpoint.h"
 #include "AAudioServiceStreamBase.h"
 #include "TimestampScheduler.h"
 
@@ -35,9 +40,11 @@
  * @return
  */
 
-AAudioServiceStreamBase::AAudioServiceStreamBase()
+AAudioServiceStreamBase::AAudioServiceStreamBase(AAudioService &audioService)
         : mUpMessageQueue(nullptr)
-        , mAAudioThread() {
+        , mTimestampThread()
+        , mAtomicTimestamp()
+        , mAudioService(audioService) {
     mMmapClient.clientUid = -1;
     mMmapClient.clientPid = -1;
     mMmapClient.packageName = String16("");
@@ -47,61 +54,143 @@
     ALOGD("AAudioServiceStreamBase::~AAudioServiceStreamBase() destroying %p", this);
     // If the stream is deleted when OPEN or in use then audio resources will leak.
     // This would indicate an internal error. So we want to find this ASAP.
-    LOG_ALWAYS_FATAL_IF(!(mState == AAUDIO_STREAM_STATE_CLOSED
-                        || mState == AAUDIO_STREAM_STATE_UNINITIALIZED
-                        || mState == AAUDIO_STREAM_STATE_DISCONNECTED),
-                        "service stream still open, state = %d", mState);
+    LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
+                        || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
+                        || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
+                        "service stream still open, state = %d", getState());
+}
+
+std::string AAudioServiceStreamBase::dumpHeader() {
+    return std::string("    T   Handle   UId Run State Format Burst Chan Capacity");
 }
 
 std::string AAudioServiceStreamBase::dump() const {
     std::stringstream result;
 
-    result << "      -------- handle = 0x" << std::hex << mHandle << std::dec << "\n";
-    result << "      state          = " << AAudio_convertStreamStateToText(mState) << "\n";
-    result << "      format         = " << mAudioFormat << "\n";
-    result << "      framesPerBurst = " << mFramesPerBurst << "\n";
-    result << "      channelCount   = " << mSamplesPerFrame << "\n";
-    result << "      capacityFrames = " << mCapacityInFrames << "\n";
-    result << "      owner uid      = " << mMmapClient.clientUid << "\n";
+    result << "    0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle
+           << std::dec << std::setfill(' ') ;
+    result << std::setw(6) << mMmapClient.clientUid;
+    result << std::setw(4) << (isRunning() ? "yes" : " no");
+    result << std::setw(6) << getState();
+    result << std::setw(7) << getFormat();
+    result << std::setw(6) << mFramesPerBurst;
+    result << std::setw(5) << getSamplesPerFrame();
+    result << std::setw(9) << getBufferCapacity();
 
     return result.str();
 }
 
 aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
-                     aaudio::AAudioStreamConfiguration &configurationOutput) {
+                                              aaudio_sharing_mode_t sharingMode) {
+    AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
+    aaudio_result_t result = AAUDIO_OK;
 
     mMmapClient.clientUid = request.getUserId();
     mMmapClient.clientPid = request.getProcessId();
-    mMmapClient.packageName.setTo(String16("")); // FIXME what should we do here?
+    mMmapClient.packageName.setTo(String16("")); // TODO What should we do here?
 
-    std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
-    if (mUpMessageQueue != nullptr) {
-        return AAUDIO_ERROR_INVALID_STATE;
-    } else {
+    // Limit scope of lock to avoid recursive lock in close().
+    {
+        std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
+        if (mUpMessageQueue != nullptr) {
+            ALOGE("AAudioServiceStreamBase::open() called twice");
+            return AAUDIO_ERROR_INVALID_STATE;
+        }
+
         mUpMessageQueue = new SharedRingBuffer();
-        return mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), QUEUE_UP_CAPACITY_COMMANDS);
+        result = mUpMessageQueue->allocate(sizeof(AAudioServiceMessage),
+                                           QUEUE_UP_CAPACITY_COMMANDS);
+        if (result != AAUDIO_OK) {
+            goto error;
+        }
+
+        mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService,
+                                                         request,
+                                                         sharingMode);
+        if (mServiceEndpoint == nullptr) {
+            ALOGE("AAudioServiceStreamBase::open() openEndpoint() failed");
+            result = AAUDIO_ERROR_UNAVAILABLE;
+            goto error;
+        }
+        mFramesPerBurst = mServiceEndpoint->getFramesPerBurst();
+        copyFrom(*mServiceEndpoint);
     }
+    return result;
+
+error:
+    close();
+    return result;
 }
 
 aaudio_result_t AAudioServiceStreamBase::close() {
-    if (mState != AAUDIO_STREAM_STATE_CLOSED) {
+    aaudio_result_t result = AAUDIO_OK;
+    if (getState() == AAUDIO_STREAM_STATE_CLOSED) {
+        return AAUDIO_OK;
+    }
+
+    stop();
+
+    if (mServiceEndpoint == nullptr) {
+        result = AAUDIO_ERROR_INVALID_STATE;
+    } else {
+        mServiceEndpoint->unregisterStream(this);
+        AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
+        mEndpointManager.closeEndpoint(mServiceEndpoint);
+        mServiceEndpoint.clear();
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
         stopTimestampThread();
-        std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
         delete mUpMessageQueue;
         mUpMessageQueue = nullptr;
-        mState = AAUDIO_STREAM_STATE_CLOSED;
     }
-    return AAUDIO_OK;
+
+    setState(AAUDIO_STREAM_STATE_CLOSED);
+    return result;
 }
 
+aaudio_result_t AAudioServiceStreamBase::startDevice() {
+    mClientHandle = AUDIO_PORT_HANDLE_NONE;
+    return mServiceEndpoint->startStream(this, &mClientHandle);
+}
+
+/**
+ * Start the flow of audio data.
+ *
+ * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
+ */
 aaudio_result_t AAudioServiceStreamBase::start() {
+    aaudio_result_t result = AAUDIO_OK;
     if (isRunning()) {
         return AAUDIO_OK;
     }
+
+    if (mServiceEndpoint == nullptr) {
+        ALOGE("AAudioServiceStreamBase::start() missing endpoint");
+        result = AAUDIO_ERROR_INVALID_STATE;
+        goto error;
+    }
+
+    // Start with fresh presentation timestamps.
+    mAtomicTimestamp.clear();
+
+    mClientHandle = AUDIO_PORT_HANDLE_NONE;
+    result = startDevice();
+    if (result != AAUDIO_OK) goto error;
+
+    // This should happen at the end of the start.
     sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
-    mState = AAUDIO_STREAM_STATE_STARTED;
+    setState(AAUDIO_STREAM_STATE_STARTED);
     mThreadEnabled.store(true);
-    return mAAudioThread.start(this);
+    result = mTimestampThread.start(this);
+    if (result != AAUDIO_OK) goto error;
+
+    return result;
+
+error:
+    disconnect();
+    return result;
 }
 
 aaudio_result_t AAudioServiceStreamBase::pause() {
@@ -109,15 +198,25 @@
     if (!isRunning()) {
         return result;
     }
+    if (mServiceEndpoint == nullptr) {
+        ALOGE("AAudioServiceStreamShared::pause() missing endpoint");
+        return AAUDIO_ERROR_INVALID_STATE;
+    }
+    result = mServiceEndpoint->stopStream(this, mClientHandle);
+    if (result != AAUDIO_OK) {
+        ALOGE("AAudioServiceStreamShared::pause() mServiceEndpoint returned %d", result);
+        disconnect(); // TODO should we return or pause Base first?
+    }
+
     sendCurrentTimestamp();
     mThreadEnabled.store(false);
-    result = mAAudioThread.stop();
+    result = mTimestampThread.stop();
     if (result != AAUDIO_OK) {
         disconnect();
         return result;
     }
     sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
-    mState = AAUDIO_STREAM_STATE_PAUSED;
+    setState(AAUDIO_STREAM_STATE_PAUSED);
     return result;
 }
 
@@ -126,15 +225,29 @@
     if (!isRunning()) {
         return result;
     }
-    // TODO wait for data to be played out
+
+    if (mServiceEndpoint == nullptr) {
+        ALOGE("AAudioServiceStreamShared::stop() missing endpoint");
+        return AAUDIO_ERROR_INVALID_STATE;
+    }
+
     sendCurrentTimestamp(); // warning - this calls a virtual function
     result = stopTimestampThread();
     if (result != AAUDIO_OK) {
         disconnect();
         return result;
     }
+
+    // TODO wait for data to be played out
+    result = mServiceEndpoint->stopStream(this, mClientHandle);
+    if (result != AAUDIO_OK) {
+        ALOGE("AAudioServiceStreamShared::stop() mServiceEndpoint returned %d", result);
+        disconnect();
+        // TODO what to do with result here?
+    }
+
     sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
-    mState = AAUDIO_STREAM_STATE_STOPPED;
+    setState(AAUDIO_STREAM_STATE_STOPPED);
     return result;
 }
 
@@ -142,14 +255,20 @@
     aaudio_result_t result = AAUDIO_OK;
     // clear flag that tells thread to loop
     if (mThreadEnabled.exchange(false)) {
-        result = mAAudioThread.stop();
+        result = mTimestampThread.stop();
     }
     return result;
 }
 
 aaudio_result_t AAudioServiceStreamBase::flush() {
+    if (getState() != AAUDIO_STREAM_STATE_PAUSED) {
+        ALOGE("AAudioServiceStreamBase::flush() stream not paused, state = %s",
+              AAudio_convertStreamStateToText(mState));
+        return AAUDIO_ERROR_INVALID_STATE;
+    }
+    // Data will get flushed when the client receives the FLUSHED event.
     sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
-    mState = AAUDIO_STREAM_STATE_FLUSHED;
+    setState(AAUDIO_STREAM_STATE_FLUSHED);
     return AAUDIO_OK;
 }
 
@@ -157,7 +276,7 @@
 void AAudioServiceStreamBase::run() {
     ALOGD("AAudioServiceStreamBase::run() entering ----------------");
     TimestampScheduler timestampScheduler;
-    timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
+    timestampScheduler.setBurstPeriod(mFramesPerBurst, getSampleRate());
     timestampScheduler.start(AudioClock::getNanoseconds());
     int64_t nextTime = timestampScheduler.nextAbsoluteTime();
     while(mThreadEnabled.load()) {
@@ -177,9 +296,9 @@
 }
 
 void AAudioServiceStreamBase::disconnect() {
-    if (mState != AAUDIO_STREAM_STATE_DISCONNECTED) {
+    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
         sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
-        mState = AAUDIO_STREAM_STATE_DISCONNECTED;
+        setState(AAUDIO_STREAM_STATE_DISCONNECTED);
     }
 }
 
@@ -195,7 +314,7 @@
 }
 
 aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
-    std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
+    std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
     if (mUpMessageQueue == nullptr) {
         ALOGE("writeUpMessageQueue(): mUpMessageQueue null! - stream not open");
         return AAUDIO_ERROR_NULL;
@@ -211,15 +330,31 @@
 
 aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
     AAudioServiceMessage command;
+    // Send a timestamp for the clock model.
     aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
                                                     &command.timestamp.timestamp);
     if (result == AAUDIO_OK) {
-    //    ALOGD("sendCurrentTimestamp(): position = %lld, nanos = %lld",
-    //          (long long) command.timestamp.position,
-    //          (long long) command.timestamp.timestamp);
-        command.what = AAudioServiceMessage::code::TIMESTAMP;
+        ALOGV("sendCurrentTimestamp() SERVICE  %8lld at %lld",
+              (long long) command.timestamp.position,
+              (long long) command.timestamp.timestamp);
+        command.what = AAudioServiceMessage::code::TIMESTAMP_SERVICE;
         result = writeUpMessageQueue(&command);
-    } else if (result == AAUDIO_ERROR_UNAVAILABLE) {
+
+        if (result == AAUDIO_OK) {
+            // Send a hardware timestamp for presentation time.
+            result = getHardwareTimestamp(&command.timestamp.position,
+                                          &command.timestamp.timestamp);
+            if (result == AAUDIO_OK) {
+                ALOGV("sendCurrentTimestamp() HARDWARE %8lld at %lld",
+                      (long long) command.timestamp.position,
+                      (long long) command.timestamp.timestamp);
+                command.what = AAudioServiceMessage::code::TIMESTAMP_HARDWARE;
+                result = writeUpMessageQueue(&command);
+            }
+        }
+    }
+
+    if (result == AAUDIO_ERROR_UNAVAILABLE) { // TODO review best error code
         result = AAUDIO_OK; // just not available yet, try again later
     }
     return result;
@@ -230,8 +365,19 @@
  * used to communicate with the underlying HAL or Service.
  */
 aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
-    // Gather information on the message queue.
-    mUpMessageQueue->fillParcelable(parcelable,
-                                    parcelable.mUpMessageQueueParcelable);
-    return getDownDataDescription(parcelable);
+    {
+        std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
+        if (mUpMessageQueue == nullptr) {
+            ALOGE("getDescription(): mUpMessageQueue null! - stream not open");
+            return AAUDIO_ERROR_NULL;
+        }
+        // Gather information on the message queue.
+        mUpMessageQueue->fillParcelable(parcelable,
+                                        parcelable.mUpMessageQueueParcelable);
+    }
+    return getAudioDataDescription(parcelable);
+}
+
+void AAudioServiceStreamBase::onVolumeChanged(float volume) {
+    sendServiceEvent(AAUDIO_SERVICE_EVENT_VOLUME, volume);
 }
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index cebefec..af435b4 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -20,6 +20,7 @@
 #include <assert.h>
 #include <mutex>
 
+#include <media/AudioClient.h>
 #include <utils/RefBase.h>
 
 #include "fifo/FifoBuffer.h"
@@ -27,71 +28,97 @@
 #include "binding/AudioEndpointParcelable.h"
 #include "binding/AAudioServiceMessage.h"
 #include "utility/AAudioUtilities.h"
-#include <media/AudioClient.h>
+#include "utility/AudioClock.h"
 
 #include "SharedRingBuffer.h"
 #include "AAudioThread.h"
 
+namespace android {
+    class AAudioService;
+}
+
 namespace aaudio {
 
+class AAudioServiceEndpoint;
+
 // We expect the queue to only have a few commands.
 // This should be way more than we need.
 #define QUEUE_UP_CAPACITY_COMMANDS (128)
 
 /**
- * Base class for a stream in the AAudio service.
+ * Each instance of AAudioServiceStreamBase corresponds to a client stream.
+ * It uses a subclass of AAudioServiceEndpoint to communicate with the underlying device or port.
  */
 class AAudioServiceStreamBase
     : public virtual android::RefBase
+    , public AAudioStreamParameters
     , public Runnable  {
 
 public:
-    AAudioServiceStreamBase();
+    AAudioServiceStreamBase(android::AAudioService &aAudioService);
+
     virtual ~AAudioServiceStreamBase();
 
     enum {
         ILLEGAL_THREAD_ID = 0
     };
 
-    std::string dump() const;
+    static std::string dumpHeader();
+
+    // does not include EOL
+    virtual std::string dump() const;
 
     // -------------------------------------------------------------------
     /**
      * Open the device.
      */
-    virtual aaudio_result_t open(const aaudio::AAudioStreamRequest &request,
-                                 aaudio::AAudioStreamConfiguration &configurationOutput) = 0;
+    virtual aaudio_result_t open(const aaudio::AAudioStreamRequest &request) = 0;
 
     virtual aaudio_result_t close();
 
     /**
-     * Start the flow of data.
+     * Start the flow of audio data.
+     *
+     * This is not guaranteed to be synchronous but it currently is.
+     * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
      */
     virtual aaudio_result_t start();
 
     /**
-     * Stop the flow of data such that start() can resume with loss of data.
-     */
+     * Stop the flow of data so that start() can resume without loss of data.
+     *
+     * This is not guaranteed to be synchronous but it currently is.
+     * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete.
+    */
     virtual aaudio_result_t pause();
 
     /**
-     * Stop the flow of data after data in buffer has played.
+     * Stop the flow of data after the currently queued data has finished playing.
+     *
+     * This is not guaranteed to be synchronous but it currently is.
+     * An AAUDIO_SERVICE_EVENT_STOPPED will be sent to the client when complete.
+     *
      */
     virtual aaudio_result_t stop();
 
     aaudio_result_t stopTimestampThread();
 
     /**
-     *  Discard any data held by the underlying HAL or Service.
+     * Discard any data held by the underlying HAL or Service.
+     *
+     * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete.
      */
     virtual aaudio_result_t flush();
 
+
     virtual aaudio_result_t startClient(const android::AudioClient& client __unused,
                                         audio_port_handle_t *clientHandle __unused) {
+        ALOGD("AAudioServiceStreamBase::startClient(%p, ...) AAUDIO_ERROR_UNAVAILABLE", &client);
         return AAUDIO_ERROR_UNAVAILABLE;
     }
 
     virtual aaudio_result_t stopClient(audio_port_handle_t clientHandle __unused) {
+        ALOGD("AAudioServiceStreamBase::stopClient(%d) AAUDIO_ERROR_UNAVAILABLE", clientHandle);
         return AAUDIO_ERROR_UNAVAILABLE;
     }
 
@@ -126,14 +153,14 @@
         return mFramesPerBurst;
     }
 
-    int32_t calculateBytesPerFrame() const {
-        return mSamplesPerFrame * AAudioConvert_formatToSizeInBytes(mAudioFormat);
-    }
-
     void run() override; // to implement Runnable
 
     void disconnect();
 
+    const android::AudioClient &getAudioClient() {
+        return mMmapClient;
+    }
+
     uid_t getOwnerUserId() const {
         return mMmapClient.clientUid;
     }
@@ -153,12 +180,26 @@
         return mState;
     }
 
+    void onVolumeChanged(float volume);
+
 protected:
 
+    /**
+     * Open the device.
+     */
+    aaudio_result_t open(const aaudio::AAudioStreamRequest &request,
+                         aaudio_sharing_mode_t sharingMode);
+
     void setState(aaudio_stream_state_t state) {
         mState = state;
     }
 
+    /**
+     * Device specific startup.
+     * @return AAUDIO_OK or negative error.
+     */
+    virtual aaudio_result_t startDevice();
+
     aaudio_result_t writeUpMessageQueue(AAudioServiceMessage *command);
 
     aaudio_result_t sendCurrentTimestamp();
@@ -170,27 +211,30 @@
      */
     virtual aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) = 0;
 
-    virtual aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) = 0;
+    virtual aaudio_result_t getHardwareTimestamp(int64_t *positionFrames, int64_t *timeNanos) = 0;
+
+    virtual aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) = 0;
 
     aaudio_stream_state_t   mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
 
     pid_t                   mRegisteredClientThread = ILLEGAL_THREAD_ID;
 
     SharedRingBuffer*       mUpMessageQueue;
-    std::mutex              mLockUpMessageQueue;
+    std::mutex              mUpMessageQueueLock;
 
-    AAudioThread            mAAudioThread;
+    AAudioThread            mTimestampThread;
     // This is used by one thread to tell another thread to exit. So it must be atomic.
-    std::atomic<bool>       mThreadEnabled;
+    std::atomic<bool>       mThreadEnabled{false};
 
-    aaudio_format_t         mAudioFormat = AAUDIO_FORMAT_UNSPECIFIED;
     int32_t                 mFramesPerBurst = 0;
-    int32_t                 mSamplesPerFrame = AAUDIO_UNSPECIFIED;
-    int32_t                 mSampleRate = AAUDIO_UNSPECIFIED;
-    int32_t                 mCapacityInFrames = AAUDIO_UNSPECIFIED;
-    android::AudioClient    mMmapClient;
+    android::AudioClient    mMmapClient; // set in open, used in MMAP start()
     audio_port_handle_t     mClientHandle = AUDIO_PORT_HANDLE_NONE;
 
+    SimpleDoubleBuffer<Timestamp>  mAtomicTimestamp;
+
+    android::AAudioService &mAudioService;
+    android::sp<AAudioServiceEndpoint> mServiceEndpoint;
+
 private:
     aaudio_handle_t         mHandle = -1;
 };
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index 08dd680..44ba1ca 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -19,225 +19,76 @@
 #include <utils/Log.h>
 
 #include <atomic>
+#include <iomanip>
+#include <iostream>
 #include <stdint.h>
 
 #include <utils/String16.h>
 #include <media/nbaio/AudioStreamOutSink.h>
 #include <media/MmapStreamInterface.h>
 
+#include "binding/AudioEndpointParcelable.h"
+#include "utility/AAudioUtilities.h"
+
+#include "AAudioServiceEndpointMMAP.h"
 #include "AAudioServiceStreamBase.h"
 #include "AAudioServiceStreamMMAP.h"
-#include "binding/AudioEndpointParcelable.h"
 #include "SharedMemoryProxy.h"
-#include "utility/AAudioUtilities.h"
 
 using android::base::unique_fd;
 using namespace android;
 using namespace aaudio;
 
-#define AAUDIO_BUFFER_CAPACITY_MIN    4 * 512
-#define AAUDIO_SAMPLE_RATE_DEFAULT    48000
-
 /**
  * Service Stream that uses an MMAP buffer.
  */
 
-AAudioServiceStreamMMAP::AAudioServiceStreamMMAP(const android::AudioClient& serviceClient,
+AAudioServiceStreamMMAP::AAudioServiceStreamMMAP(android::AAudioService &aAudioService,
                                                  bool inService)
-        : AAudioServiceStreamBase()
-        , mMmapStreamCallback(new MyMmapStreamCallback(*this))
-        , mPreviousFrameCounter(0)
-        , mMmapStream(nullptr)
-        , mServiceClient(serviceClient)
+        : AAudioServiceStreamBase(aAudioService)
         , mInService(inService) {
 }
 
 aaudio_result_t AAudioServiceStreamMMAP::close() {
-    if (mState == AAUDIO_STREAM_STATE_CLOSED) {
+    if (getState() == AAUDIO_STREAM_STATE_CLOSED) {
         return AAUDIO_OK;
     }
+
     stop();
-    if (mMmapStream != 0) {
-        mMmapStream.clear(); // TODO review. Is that all we have to do?
-        // Apparently the above close is asynchronous. An attempt to open a new device
-        // right after a close can fail. Also some callbacks may still be in flight!
-        // FIXME Make closing synchronous.
-        AudioClock::sleepForNanos(100 * AAUDIO_NANOS_PER_MILLISECOND);
-    }
 
     return AAudioServiceStreamBase::close();
 }
 
 // Open stream on HAL and pass information about the shared memory buffer back to the client.
-aaudio_result_t AAudioServiceStreamMMAP::open(const aaudio::AAudioStreamRequest &request,
-                                       aaudio::AAudioStreamConfiguration &configurationOutput) {
-    const audio_attributes_t attributes = {
-        .content_type = AUDIO_CONTENT_TYPE_MUSIC,
-        .usage = AUDIO_USAGE_MEDIA,
-        .source = AUDIO_SOURCE_VOICE_RECOGNITION,
-        .flags = AUDIO_FLAG_LOW_LATENCY,
-        .tags = ""
-    };
-    audio_config_base_t config;
+aaudio_result_t AAudioServiceStreamMMAP::open(const aaudio::AAudioStreamRequest &request) {
 
-    aaudio_result_t result = AAudioServiceStreamBase::open(request, configurationOutput);
+    sp<AAudioServiceStreamMMAP> keep(this);
+
+    aaudio_result_t result = AAudioServiceStreamBase::open(request,
+                                                           AAUDIO_SHARING_MODE_EXCLUSIVE);
     if (result != AAUDIO_OK) {
-        ALOGE("AAudioServiceStreamBase open returned %d", result);
         return result;
     }
 
-    const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
-    audio_port_handle_t deviceId = configurationInput.getDeviceId();
-    aaudio_direction_t direction = request.getDirection();
-
-    // Fill in config
-    aaudio_format_t aaudioFormat = configurationInput.getFormat();
-    if (aaudioFormat == AAUDIO_UNSPECIFIED || aaudioFormat == AAUDIO_FORMAT_PCM_FLOAT) {
-        aaudioFormat = AAUDIO_FORMAT_PCM_I16;
+    result = mServiceEndpoint->registerStream(keep);
+    if (result != AAUDIO_OK) {
+        goto error;
     }
-    config.format = AAudioConvert_aaudioToAndroidDataFormat(aaudioFormat);
-
-    int32_t aaudioSampleRate = configurationInput.getSampleRate();
-    if (aaudioSampleRate == AAUDIO_UNSPECIFIED) {
-        aaudioSampleRate = AAUDIO_SAMPLE_RATE_DEFAULT;
-    }
-    config.sample_rate = aaudioSampleRate;
-
-    int32_t aaudioSamplesPerFrame = configurationInput.getSamplesPerFrame();
-
-    if (direction == AAUDIO_DIRECTION_OUTPUT) {
-        config.channel_mask = (aaudioSamplesPerFrame == AAUDIO_UNSPECIFIED)
-                            ? AUDIO_CHANNEL_OUT_STEREO
-                            : audio_channel_out_mask_from_count(aaudioSamplesPerFrame);
-    } else if (direction == AAUDIO_DIRECTION_INPUT) {
-        config.channel_mask =  (aaudioSamplesPerFrame == AAUDIO_UNSPECIFIED)
-                            ? AUDIO_CHANNEL_IN_STEREO
-                            : audio_channel_in_mask_from_count(aaudioSamplesPerFrame);
-    } else {
-        ALOGE("openMmapStream - invalid direction = %d", direction);
-        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
-    }
-
-    MmapStreamInterface::stream_direction_t streamDirection = (direction == AAUDIO_DIRECTION_OUTPUT)
-        ? MmapStreamInterface::DIRECTION_OUTPUT : MmapStreamInterface::DIRECTION_INPUT;
-
-    // Open HAL stream.
-    status_t status = MmapStreamInterface::openMmapStream(streamDirection,
-                                                          &attributes,
-                                                          &config,
-                                                          mMmapClient,
-                                                          &deviceId,
-                                                          mMmapStreamCallback,
-                                                          mMmapStream,
-                                                          &mPortHandle);
-    if (status != OK) {
-        ALOGE("openMmapStream returned status %d", status);
-        return AAUDIO_ERROR_UNAVAILABLE;
-    }
-
-    if (deviceId == AAUDIO_UNSPECIFIED) {
-        ALOGW("AAudioServiceStreamMMAP::open() - openMmapStream() failed to set deviceId");
-    }
-
-    // Create MMAP/NOIRQ buffer.
-    int32_t minSizeFrames = configurationInput.getBufferCapacity();
-    if (minSizeFrames <= 0) { // zero will get rejected
-        minSizeFrames = AAUDIO_BUFFER_CAPACITY_MIN;
-    }
-    status = mMmapStream->createMmapBuffer(minSizeFrames, &mMmapBufferinfo);
-    if (status != OK) {
-        ALOGE("AAudioServiceStreamMMAP::open() - createMmapBuffer() returned status %d",
-              status);
-        return AAUDIO_ERROR_UNAVAILABLE;
-    } else {
-        ALOGD("createMmapBuffer status = %d, buffer_size = %d, burst_size %d"
-                ", Sharable FD: %s",
-              status,
-              abs(mMmapBufferinfo.buffer_size_frames),
-              mMmapBufferinfo.burst_size_frames,
-              mMmapBufferinfo.buffer_size_frames < 0 ? "Yes" : "No");
-    }
-
-    mCapacityInFrames = mMmapBufferinfo.buffer_size_frames;
-    // FIXME: the audio HAL indicates if the shared memory fd can be shared outside of audioserver
-    // by returning a negative buffer size
-    if (mCapacityInFrames < 0) {
-        // Exclusive mode is possible from any client
-        mCapacityInFrames = -mCapacityInFrames;
-    } else {
-        // exclusive mode is only possible if the final fd destination is inside audioserver
-        if ((mMmapClient.clientUid != mServiceClient.clientUid) &&
-                configurationInput.getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
-            // Fallback is handled by caller but indicate what is possible in case
-            // this is used in the future
-            configurationOutput.setSharingMode(AAUDIO_SHARING_MODE_SHARED);
-            return AAUDIO_ERROR_UNAVAILABLE;
-        }
-    }
-
-    // Get information about the stream and pass it back to the caller.
-    mSamplesPerFrame = (direction == AAUDIO_DIRECTION_OUTPUT)
-                           ? audio_channel_count_from_out_mask(config.channel_mask)
-                           : audio_channel_count_from_in_mask(config.channel_mask);
-
-    // AAudio creates a copy of this FD and retains ownership of the copy.
-    // Assume that AudioFlinger will close the original shared_memory_fd.
-    mAudioDataFileDescriptor.reset(dup(mMmapBufferinfo.shared_memory_fd));
-    if (mAudioDataFileDescriptor.get() == -1) {
-        ALOGE("AAudioServiceStreamMMAP::open() - could not dup shared_memory_fd");
-        return AAUDIO_ERROR_INTERNAL; // TODO review
-    }
-    mFramesPerBurst = mMmapBufferinfo.burst_size_frames;
-    mAudioFormat = AAudioConvert_androidToAAudioDataFormat(config.format);
-    mSampleRate = config.sample_rate;
-
-    // Scale up the burst size to meet the minimum equivalent in microseconds.
-    // This is to avoid waking the CPU too often when the HW burst is very small
-    // or at high sample rates.
-    int32_t burstMinMicros = AAudioProperty_getHardwareBurstMinMicros();
-    int32_t burstMicros = 0;
-    do {
-        if (burstMicros > 0) {  // skip first loop
-            mFramesPerBurst *= 2;
-        }
-        burstMicros = mFramesPerBurst * static_cast<int64_t>(1000000) / mSampleRate;
-    } while (burstMicros < burstMinMicros);
-
-    ALOGD("AAudioServiceStreamMMAP::open() original burst = %d, minMicros = %d, final burst = %d\n",
-          mMmapBufferinfo.burst_size_frames, burstMinMicros, mFramesPerBurst);
-
-    ALOGD("AAudioServiceStreamMMAP::open() actual rate = %d, channels = %d, deviceId = %d\n",
-          mSampleRate, mSamplesPerFrame, deviceId);
-
-    // Fill in AAudioStreamConfiguration
-    configurationOutput.setSampleRate(mSampleRate);
-    configurationOutput.setSamplesPerFrame(mSamplesPerFrame);
-    configurationOutput.setFormat(mAudioFormat);
-    configurationOutput.setDeviceId(deviceId);
 
     setState(AAUDIO_STREAM_STATE_OPEN);
+
+error:
     return AAUDIO_OK;
 }
 
 /**
  * Start the flow of data.
  */
-aaudio_result_t AAudioServiceStreamMMAP::start() {
-    if (isRunning()) {
-        return AAUDIO_OK;
-    }
-    if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
-    aaudio_result_t result;
-    status_t status = mMmapStream->start(mServiceClient, &mPortHandle);
-    if (status != OK) {
-        ALOGE("AAudioServiceStreamMMAP::start() mMmapStream->start() returned %d", status);
-        disconnect();
-        result = AAudioConvert_androidToAAudioResult(status);
-    } else {
-        result = AAudioServiceStreamBase::start();
-        if (!mInService && result == AAUDIO_OK) {
-            startClient(mMmapClient, &mClientHandle);
-        }
+aaudio_result_t AAudioServiceStreamMMAP::startDevice() {
+    aaudio_result_t result = AAudioServiceStreamBase::startDevice();
+    if (!mInService && result == AAUDIO_OK) {
+        // Note that this can sometimes take 200 to 300 msec for a cold start!
+        result = startClient(mMmapClient, &mClientHandle);
     }
     return result;
 }
@@ -249,104 +100,78 @@
     if (!isRunning()) {
         return AAUDIO_OK;
     }
-    if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
-    aaudio_result_t result1 = AAudioServiceStreamBase::pause();
+    aaudio_result_t result = AAudioServiceStreamBase::pause();
+    // TODO put before base::pause()?
     if (!mInService) {
-        stopClient(mClientHandle);
+        (void) stopClient(mClientHandle);
     }
-    status_t status = mMmapStream->stop(mPortHandle);
-    mFramesRead.reset32();
-    return (result1 != AAUDIO_OK) ? result1 : AAudioConvert_androidToAAudioResult(status);
+    return result;
 }
 
 aaudio_result_t AAudioServiceStreamMMAP::stop() {
     if (!isRunning()) {
         return AAUDIO_OK;
     }
-    if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
-    aaudio_result_t result1 = AAudioServiceStreamBase::stop();
+    aaudio_result_t result = AAudioServiceStreamBase::stop();
+    // TODO put before base::stop()?
     if (!mInService) {
-        stopClient(mClientHandle);
-    }
-    aaudio_result_t status = mMmapStream->stop(mPortHandle);
-    mFramesRead.reset32();
-    return (result1 != AAUDIO_OK) ? result1 :  AAudioConvert_androidToAAudioResult(status);
-}
-
-/**
- *  Discard any data held by the underlying HAL or Service.
- */
-aaudio_result_t AAudioServiceStreamMMAP::flush() {
-    if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
-    // TODO how do we flush an MMAP/NOIRQ buffer? sync pointers?
-    return AAudioServiceStreamBase::flush();;
-}
-
-aaudio_result_t AAudioServiceStreamMMAP::startClient(const android::AudioClient& client,
-                                                     audio_port_handle_t *clientHandle) {
-    return AAudioConvert_androidToAAudioResult(mMmapStream->start(client, clientHandle));
-}
-
-aaudio_result_t AAudioServiceStreamMMAP::stopClient(audio_port_handle_t clientHandle) {
-    return AAudioConvert_androidToAAudioResult(mMmapStream->stop(clientHandle));
-}
-
-aaudio_result_t AAudioServiceStreamMMAP::getFreeRunningPosition(int64_t *positionFrames,
-                                                                int64_t *timeNanos) {
-    struct audio_mmap_position position;
-    if (mMmapStream == nullptr) {
-        disconnect();
-        return AAUDIO_ERROR_NULL;
-    }
-    status_t status = mMmapStream->getMmapPosition(&position);
-    aaudio_result_t result = AAudioConvert_androidToAAudioResult(status);
-    if (result == AAUDIO_ERROR_UNAVAILABLE) {
-        ALOGW("sendCurrentTimestamp(): getMmapPosition() has no position data yet");
-    } else if (result != AAUDIO_OK) {
-        ALOGE("sendCurrentTimestamp(): getMmapPosition() returned status %d", status);
-        disconnect();
-    } else {
-        mFramesRead.update32(position.position_frames);
-        *positionFrames = mFramesRead.get();
-        *timeNanos = position.time_nanoseconds;
+        (void) stopClient(mClientHandle);
     }
     return result;
 }
 
-void AAudioServiceStreamMMAP::onTearDown() {
-    ALOGD("AAudioServiceStreamMMAP::onTearDown() called");
-    disconnect();
-};
+aaudio_result_t AAudioServiceStreamMMAP::startClient(const android::AudioClient& client,
+                                                       audio_port_handle_t *clientHandle) {
+    // Start the client on behalf of the application. Generate a new porthandle.
+    aaudio_result_t result = mServiceEndpoint->startClient(client, clientHandle);
+    return result;
+}
 
-void AAudioServiceStreamMMAP::onVolumeChanged(audio_channel_mask_t channels,
-                     android::Vector<float> values) {
-    // TODO do we really need a different volume for each channel?
-    float volume = values[0];
-    ALOGD("AAudioServiceStreamMMAP::onVolumeChanged() volume[0] = %f", volume);
-    sendServiceEvent(AAUDIO_SERVICE_EVENT_VOLUME, volume);
-};
+aaudio_result_t AAudioServiceStreamMMAP::stopClient(audio_port_handle_t clientHandle) {
+    aaudio_result_t result = mServiceEndpoint->stopClient(clientHandle);
+    return result;
+}
 
-void AAudioServiceStreamMMAP::onRoutingChanged(audio_port_handle_t deviceId) {
-    ALOGD("AAudioServiceStreamMMAP::onRoutingChanged() called with %d, old = %d",
-          deviceId, mDeviceId);
-    if (mDeviceId != AUDIO_PORT_HANDLE_NONE  && mDeviceId != deviceId) {
+// Get free-running DSP or DMA hardware position from the HAL.
+aaudio_result_t AAudioServiceStreamMMAP::getFreeRunningPosition(int64_t *positionFrames,
+                                                                  int64_t *timeNanos) {
+    sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP{
+            static_cast<AAudioServiceEndpointMMAP *>(mServiceEndpoint.get())};
+    aaudio_result_t result = serviceEndpointMMAP->getFreeRunningPosition(positionFrames, timeNanos);
+    if (result == AAUDIO_OK) {
+        Timestamp timestamp(*positionFrames, *timeNanos);
+        mAtomicTimestamp.write(timestamp);
+        *positionFrames = timestamp.getPosition();
+        *timeNanos = timestamp.getNanoseconds();
+    } else if (result != AAUDIO_ERROR_UNAVAILABLE) {
         disconnect();
     }
-    mDeviceId = deviceId;
-};
+    return result;
+}
+
+// Get timestamp that was written by getFreeRunningPosition()
+aaudio_result_t AAudioServiceStreamMMAP::getHardwareTimestamp(int64_t *positionFrames,
+                                                                int64_t *timeNanos) {
+    sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP{
+            static_cast<AAudioServiceEndpointMMAP *>(mServiceEndpoint.get())};
+    // TODO Get presentation timestamp from the HAL
+    if (mAtomicTimestamp.isValid()) {
+        Timestamp timestamp = mAtomicTimestamp.read();
+        *positionFrames = timestamp.getPosition();
+        *timeNanos = timestamp.getNanoseconds() + serviceEndpointMMAP->getHardwareTimeOffsetNanos();
+        return AAUDIO_OK;
+    } else {
+        return AAUDIO_ERROR_UNAVAILABLE;
+    }
+}
 
 /**
  * Get an immutable description of the data queue from the HAL.
  */
-aaudio_result_t AAudioServiceStreamMMAP::getDownDataDescription(AudioEndpointParcelable &parcelable)
+aaudio_result_t AAudioServiceStreamMMAP::getAudioDataDescription(
+        AudioEndpointParcelable &parcelable)
 {
-    // Gather information on the data queue based on HAL info.
-    int32_t bytesPerFrame = calculateBytesPerFrame();
-    int32_t capacityInBytes = mCapacityInFrames * bytesPerFrame;
-    int fdIndex = parcelable.addFileDescriptor(mAudioDataFileDescriptor, capacityInBytes);
-    parcelable.mDownDataQueueParcelable.setupMemory(fdIndex, 0, capacityInBytes);
-    parcelable.mDownDataQueueParcelable.setBytesPerFrame(bytesPerFrame);
-    parcelable.mDownDataQueueParcelable.setFramesPerBurst(mFramesPerBurst);
-    parcelable.mDownDataQueueParcelable.setCapacityInFrames(mCapacityInFrames);
-    return AAUDIO_OK;
+    sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP{
+            static_cast<AAudioServiceEndpointMMAP *>(mServiceEndpoint.get())};
+    return serviceEndpointMMAP->getDownDataDescription(parcelable);
 }
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index b69dc46..e2415d0 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -37,27 +37,20 @@
 
 namespace aaudio {
 
-    /**
-     * Manage one memory mapped buffer that originated from a HAL.
-     */
-class AAudioServiceStreamMMAP
-    : public AAudioServiceStreamBase
-    , public android::MmapStreamCallback {
+
+/**
+ * These corresponds to an EXCLUSIVE mode MMAP client stream.
+ * It has exclusive use of one AAudioServiceEndpointMMAP to communicate with the underlying
+ * device or port.
+ */
+class AAudioServiceStreamMMAP : public AAudioServiceStreamBase {
 
 public:
-    AAudioServiceStreamMMAP(const android::AudioClient& serviceClient, bool inService);
+    AAudioServiceStreamMMAP(android::AAudioService &aAudioService,
+                            bool inService);
     virtual ~AAudioServiceStreamMMAP() = default;
 
-    aaudio_result_t open(const aaudio::AAudioStreamRequest &request,
-                                 aaudio::AAudioStreamConfiguration &configurationOutput) override;
-
-    /**
-     * Start the flow of audio data.
-     *
-     * This is not guaranteed to be synchronous but it currently is.
-     * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
-     */
-    aaudio_result_t start() override;
+    aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
 
     /**
      * Stop the flow of data so that start() can resume without loss of data.
@@ -69,79 +62,34 @@
 
     aaudio_result_t stop() override;
 
-    /**
-     *  Discard any data held by the underlying HAL or Service.
-     *
-     * This is not guaranteed to be synchronous but it currently is.
-     * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete.
-     */
-    aaudio_result_t flush() override;
+    aaudio_result_t startClient(const android::AudioClient& client,
+                                audio_port_handle_t *clientHandle) override;
+
+    aaudio_result_t stopClient(audio_port_handle_t clientHandle) override;
 
     aaudio_result_t close() override;
 
-    virtual aaudio_result_t startClient(const android::AudioClient& client,
-                                        audio_port_handle_t *clientHandle);
-
-    virtual aaudio_result_t stopClient(audio_port_handle_t clientHandle);
-
     /**
      * Send a MMAP/NOIRQ buffer timestamp to the client.
      */
-    aaudio_result_t sendCurrentTimestamp();
-
-    // -------------- Callback functions ---------------------
-    void onTearDown() override;
-
-    void onVolumeChanged(audio_channel_mask_t channels,
-                         android::Vector<float> values) override;
-
-    void onRoutingChanged(audio_port_handle_t deviceId) override;
 
 protected:
 
-    aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) override;
+    aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) override;
 
     aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) override;
 
+    aaudio_result_t getHardwareTimestamp(int64_t *positionFrames, int64_t *timeNanos) override;
+
+    /**
+     * Device specific startup.
+     * @return AAUDIO_OK or negative error.
+     */
+    aaudio_result_t startDevice() override;
+
 private:
-    // This proxy class was needed to prevent a crash in AudioFlinger
-    // when the stream was closed.
-    class MyMmapStreamCallback : public android::MmapStreamCallback {
-    public:
-        explicit MyMmapStreamCallback(android::MmapStreamCallback &serviceCallback)
-            : mServiceCallback(serviceCallback){}
-        virtual ~MyMmapStreamCallback() = default;
 
-        void onTearDown() override {
-            mServiceCallback.onTearDown();
-        };
-
-        void onVolumeChanged(audio_channel_mask_t channels, android::Vector<float> values) override
-        {
-            mServiceCallback.onVolumeChanged(channels, values);
-        };
-
-        void onRoutingChanged(audio_port_handle_t deviceId) override {
-            mServiceCallback.onRoutingChanged(deviceId);
-        };
-
-    private:
-        android::MmapStreamCallback &mServiceCallback;
-    };
-
-    android::sp<MyMmapStreamCallback>   mMmapStreamCallback;
-    MonotonicCounter                    mFramesWritten;
-    MonotonicCounter                    mFramesRead;
-    int32_t                             mPreviousFrameCounter = 0;   // from HAL
-
-    // Interface to the AudioFlinger MMAP support.
-    android::sp<android::MmapStreamInterface> mMmapStream;
-    struct audio_mmap_buffer_info             mMmapBufferinfo;
-    audio_port_handle_t                       mPortHandle = AUDIO_PORT_HANDLE_NONE;
-    audio_port_handle_t                       mDeviceId = AUDIO_PORT_HANDLE_NONE;
-    android::AudioClient                      mServiceClient;
-    bool                                      mInService = false;
-    android::base::unique_fd                  mAudioDataFileDescriptor;
+    bool                     mInService = false;
 };
 
 } // namespace aaudio
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index 5654113..084f996 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -18,6 +18,8 @@
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
+#include <iomanip>
+#include <iostream>
 #include <mutex>
 
 #include <aaudio/AAudio.h>
@@ -40,8 +42,32 @@
 #define MAX_FRAMES_PER_BUFFER       (32 * 1024)
 
 AAudioServiceStreamShared::AAudioServiceStreamShared(AAudioService &audioService)
-    : mAudioService(audioService)
-    {
+    : AAudioServiceStreamBase(audioService)
+    , mTimestampPositionOffset(0)
+    , mXRunCount(0) {
+}
+
+std::string AAudioServiceStreamShared::dumpHeader() {
+    std::stringstream result;
+    result << AAudioServiceStreamBase::dumpHeader();
+    result << "    Write#     Read#   Avail   XRuns";
+    return result.str();
+}
+
+std::string AAudioServiceStreamShared::dump() const {
+    std::stringstream result;
+
+    result << AAudioServiceStreamBase::dump();
+
+    auto fifo = mAudioDataQueue->getFifoBuffer();
+    int32_t readCounter = fifo->getReadCounter();
+    int32_t writeCounter = fifo->getWriteCounter();
+    result << std::setw(10) << writeCounter;
+    result << std::setw(10) << readCounter;
+    result << std::setw(8) << (writeCounter - readCounter);
+    result << std::setw(8) << getXRunCount();
+
+    return result.str();
 }
 
 int32_t AAudioServiceStreamShared::calculateBufferCapacity(int32_t requestedCapacityFrames,
@@ -90,87 +116,72 @@
     return capacityInFrames;
 }
 
-aaudio_result_t AAudioServiceStreamShared::open(const aaudio::AAudioStreamRequest &request,
-                     aaudio::AAudioStreamConfiguration &configurationOutput)  {
+aaudio_result_t AAudioServiceStreamShared::open(const aaudio::AAudioStreamRequest &request)  {
 
     sp<AAudioServiceStreamShared> keep(this);
 
-    aaudio_result_t result = AAudioServiceStreamBase::open(request, configurationOutput);
+    aaudio_result_t result = AAudioServiceStreamBase::open(request, AAUDIO_SHARING_MODE_SHARED);
     if (result != AAUDIO_OK) {
         ALOGE("AAudioServiceStreamBase open() returned %d", result);
         return result;
     }
 
     const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
-    aaudio_direction_t direction = request.getDirection();
 
-    AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
-    mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, configurationOutput, direction);
-    if (mServiceEndpoint == nullptr) {
-        ALOGE("AAudioServiceStreamShared::open() mServiceEndPoint = %p", mServiceEndpoint);
-        return AAUDIO_ERROR_UNAVAILABLE;
-    }
 
     // Is the request compatible with the shared endpoint?
-    mAudioFormat = configurationInput.getFormat();
-    if (mAudioFormat == AAUDIO_FORMAT_UNSPECIFIED) {
-        mAudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
-    } else if (mAudioFormat != AAUDIO_FORMAT_PCM_FLOAT) {
-        ALOGE("AAudioServiceStreamShared::open() mAudioFormat = %d, need FLOAT", mAudioFormat);
+    setFormat(configurationInput.getFormat());
+    if (getFormat() == AAUDIO_FORMAT_UNSPECIFIED) {
+        setFormat(AAUDIO_FORMAT_PCM_FLOAT);
+    } else if (getFormat() != AAUDIO_FORMAT_PCM_FLOAT) {
+        ALOGE("AAudioServiceStreamShared::open() mAudioFormat = %d, need FLOAT", getFormat());
         result = AAUDIO_ERROR_INVALID_FORMAT;
         goto error;
     }
 
-    mSampleRate = configurationInput.getSampleRate();
-    if (mSampleRate == AAUDIO_UNSPECIFIED) {
-        mSampleRate = mServiceEndpoint->getSampleRate();
-    } else if (mSampleRate != mServiceEndpoint->getSampleRate()) {
+    setSampleRate(configurationInput.getSampleRate());
+    if (getSampleRate() == AAUDIO_UNSPECIFIED) {
+        setSampleRate(mServiceEndpoint->getSampleRate());
+    } else if (getSampleRate() != mServiceEndpoint->getSampleRate()) {
         ALOGE("AAudioServiceStreamShared::open() mSampleRate = %d, need %d",
-              mSampleRate, mServiceEndpoint->getSampleRate());
+              getSampleRate(), mServiceEndpoint->getSampleRate());
         result = AAUDIO_ERROR_INVALID_RATE;
         goto error;
     }
 
-    mSamplesPerFrame = configurationInput.getSamplesPerFrame();
-    if (mSamplesPerFrame == AAUDIO_UNSPECIFIED) {
-        mSamplesPerFrame = mServiceEndpoint->getSamplesPerFrame();
-    } else if (mSamplesPerFrame != mServiceEndpoint->getSamplesPerFrame()) {
+    setSamplesPerFrame(configurationInput.getSamplesPerFrame());
+    if (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) {
+        setSamplesPerFrame(mServiceEndpoint->getSamplesPerFrame());
+    } else if (getSamplesPerFrame() != mServiceEndpoint->getSamplesPerFrame()) {
         ALOGE("AAudioServiceStreamShared::open() mSamplesPerFrame = %d, need %d",
-              mSamplesPerFrame, mServiceEndpoint->getSamplesPerFrame());
+              getSamplesPerFrame(), mServiceEndpoint->getSamplesPerFrame());
         result = AAUDIO_ERROR_OUT_OF_RANGE;
         goto error;
     }
 
-    mFramesPerBurst = mServiceEndpoint->getFramesPerBurst();
-    ALOGD("AAudioServiceStreamShared::open() mSampleRate = %d, mFramesPerBurst = %d",
-          mSampleRate, mFramesPerBurst);
-
-    mCapacityInFrames = calculateBufferCapacity(configurationInput.getBufferCapacity(),
-                                     mFramesPerBurst);
-    if (mCapacityInFrames < 0) {
-        result = mCapacityInFrames; // negative error code
-        mCapacityInFrames = 0;
+    setBufferCapacity(calculateBufferCapacity(configurationInput.getBufferCapacity(),
+                                     mFramesPerBurst));
+    if (getBufferCapacity() < 0) {
+        result = getBufferCapacity(); // negative error code
+        setBufferCapacity(0);
         goto error;
     }
 
-    // Create audio data shared memory buffer for client.
-    mAudioDataQueue = new SharedRingBuffer();
-    result = mAudioDataQueue->allocate(calculateBytesPerFrame(), mCapacityInFrames);
-    if (result != AAUDIO_OK) {
-        ALOGE("AAudioServiceStreamShared::open() could not allocate FIFO with %d frames",
-              mCapacityInFrames);
-        result = AAUDIO_ERROR_NO_MEMORY;
-        goto error;
+    {
+        std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
+        // Create audio data shared memory buffer for client.
+        mAudioDataQueue = new SharedRingBuffer();
+        result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity());
+        if (result != AAUDIO_OK) {
+            ALOGE("AAudioServiceStreamShared::open() could not allocate FIFO with %d frames",
+                  getBufferCapacity());
+            result = AAUDIO_ERROR_NO_MEMORY;
+            goto error;
+        }
     }
 
     ALOGD("AAudioServiceStreamShared::open() actual rate = %d, channels = %d, deviceId = %d",
-          mSampleRate, mSamplesPerFrame, mServiceEndpoint->getDeviceId());
-
-    // Fill in configuration for client.
-    configurationOutput.setSampleRate(mSampleRate);
-    configurationOutput.setSamplesPerFrame(mSamplesPerFrame);
-    configurationOutput.setFormat(mAudioFormat);
-    configurationOutput.setDeviceId(mServiceEndpoint->getDeviceId());
+          getSampleRate(), getSamplesPerFrame(), mServiceEndpoint->getDeviceId());
 
     result = mServiceEndpoint->registerStream(keep);
     if (result != AAUDIO_OK) {
@@ -185,121 +196,30 @@
     return result;
 }
 
-/**
- * Start the flow of audio data.
- *
- * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
- */
-aaudio_result_t AAudioServiceStreamShared::start()  {
-    if (isRunning()) {
-        return AAUDIO_OK;
-    }
-    AAudioServiceEndpoint *endpoint = mServiceEndpoint;
-    if (endpoint == nullptr) {
-        return AAUDIO_ERROR_INVALID_STATE;
-    }
-    // For output streams, this will add the stream to the mixer.
-    aaudio_result_t result = endpoint->startStream(this);
-    if (result != AAUDIO_OK) {
-        ALOGE("AAudioServiceStreamShared::start() mServiceEndpoint returned %d", result);
-        disconnect();
-    } else {
-        result = endpoint->getStreamInternal()->startClient(mMmapClient, &mClientHandle);
-        if (result == AAUDIO_OK) {
-            result = AAudioServiceStreamBase::start();
-        }
-    }
-    return result;
-}
-
-/**
- * Stop the flow of data so that start() can resume without loss of data.
- *
- * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete.
-*/
-aaudio_result_t AAudioServiceStreamShared::pause()  {
-    if (!isRunning()) {
-        return AAUDIO_OK;
-    }
-    AAudioServiceEndpoint *endpoint = mServiceEndpoint;
-    if (endpoint == nullptr) {
-        return AAUDIO_ERROR_INVALID_STATE;
-    }
-    endpoint->getStreamInternal()->stopClient(mClientHandle);
-    aaudio_result_t result = endpoint->stopStream(this);
-    if (result != AAUDIO_OK) {
-        ALOGE("AAudioServiceStreamShared::pause() mServiceEndpoint returned %d", result);
-        disconnect(); // TODO should we return or pause Base first?
-    }
-    return AAudioServiceStreamBase::pause();
-}
-
-aaudio_result_t AAudioServiceStreamShared::stop()  {
-    if (!isRunning()) {
-        return AAUDIO_OK;
-    }
-    AAudioServiceEndpoint *endpoint = mServiceEndpoint;
-    if (endpoint == nullptr) {
-        return AAUDIO_ERROR_INVALID_STATE;
-    }
-    endpoint->getStreamInternal()->stopClient(mClientHandle);
-    aaudio_result_t result = endpoint->stopStream(this);
-    if (result != AAUDIO_OK) {
-        ALOGE("AAudioServiceStreamShared::stop() mServiceEndpoint returned %d", result);
-        disconnect();
-    }
-    return AAudioServiceStreamBase::stop();
-}
-
-/**
- *  Discard any data held by the underlying HAL or Service.
- *
- * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete.
- */
-aaudio_result_t AAudioServiceStreamShared::flush()  {
-    AAudioServiceEndpoint *endpoint = mServiceEndpoint;
-    if (endpoint == nullptr) {
-        return AAUDIO_ERROR_INVALID_STATE;
-    }
-    if (mState != AAUDIO_STREAM_STATE_PAUSED) {
-         ALOGE("AAudioServiceStreamShared::flush() stream not paused, state = %s",
-            AAudio_convertStreamStateToText(mState));
-        return AAUDIO_ERROR_INVALID_STATE;
-    }
-    // Data will get flushed when the client receives the FLUSHED event.
-    return AAudioServiceStreamBase::flush();
-}
 
 aaudio_result_t AAudioServiceStreamShared::close()  {
-    if (mState == AAUDIO_STREAM_STATE_CLOSED) {
-        return AAUDIO_OK;
-    }
+    aaudio_result_t result = AAudioServiceStreamBase::close();
 
-    stop();
-
-    AAudioServiceEndpoint *endpoint = mServiceEndpoint;
-    if (endpoint == nullptr) {
-        return AAUDIO_ERROR_INVALID_STATE;
-    }
-
-    endpoint->unregisterStream(this);
-
-    AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
-    mEndpointManager.closeEndpoint(endpoint);
-    mServiceEndpoint = nullptr;
-
-    if (mAudioDataQueue != nullptr) {
+    {
+        std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
         delete mAudioDataQueue;
         mAudioDataQueue = nullptr;
     }
-    return AAudioServiceStreamBase::close();
+
+    return result;
 }
 
 /**
  * Get an immutable description of the data queue created by this service.
  */
-aaudio_result_t AAudioServiceStreamShared::getDownDataDescription(AudioEndpointParcelable &parcelable)
+aaudio_result_t AAudioServiceStreamShared::getAudioDataDescription(
+        AudioEndpointParcelable &parcelable)
 {
+    std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
+    if (mAudioDataQueue == nullptr) {
+        ALOGE("getAudioDataDescription(): mUpMessageQueue null! - stream not open");
+        return AAUDIO_ERROR_NULL;
+    }
     // Gather information on the data queue.
     mAudioDataQueue->fillParcelable(parcelable,
                                     parcelable.mDownDataQueueParcelable);
@@ -307,15 +227,37 @@
     return AAUDIO_OK;
 }
 
-void AAudioServiceStreamShared::markTransferTime(int64_t nanoseconds) {
-    mMarkedPosition = mAudioDataQueue->getFifoBuffer()->getReadCounter();
-    mMarkedTime = nanoseconds;
+void AAudioServiceStreamShared::markTransferTime(Timestamp &timestamp) {
+    mAtomicTimestamp.write(timestamp);
 }
 
+// Get timestamp that was written by mixer or distributor.
 aaudio_result_t AAudioServiceStreamShared::getFreeRunningPosition(int64_t *positionFrames,
+                                                                  int64_t *timeNanos) {
+    // TODO Get presentation timestamp from the HAL
+    if (mAtomicTimestamp.isValid()) {
+        Timestamp timestamp = mAtomicTimestamp.read();
+        *positionFrames = timestamp.getPosition();
+        *timeNanos = timestamp.getNanoseconds();
+        return AAUDIO_OK;
+    } else {
+        return AAUDIO_ERROR_UNAVAILABLE;
+    }
+}
+
+// Get timestamp from lower level service.
+aaudio_result_t AAudioServiceStreamShared::getHardwareTimestamp(int64_t *positionFrames,
                                                                 int64_t *timeNanos) {
-    // TODO get these two numbers as an atomic pair
-    *positionFrames = mMarkedPosition;
-    *timeNanos = mMarkedTime;
-    return AAUDIO_OK;
+
+    int64_t position = 0;
+    aaudio_result_t result = mServiceEndpoint->getTimestamp(&position, timeNanos);
+    if (result == AAUDIO_OK) {
+        int64_t offset = mTimestampPositionOffset.load();
+        // TODO, do not go below starting value
+        position -= offset; // Offset from shared MMAP stream
+        ALOGV("getHardwareTimestamp() %8lld = %8lld - %8lld",
+              (long long) position, (long long) (position + offset), (long long) offset);
+    }
+    *positionFrames = position;
+    return result;
 }
diff --git a/services/oboeservice/AAudioServiceStreamShared.h b/services/oboeservice/AAudioServiceStreamShared.h
index 6b67337..8499ea5 100644
--- a/services/oboeservice/AAudioServiceStreamShared.h
+++ b/services/oboeservice/AAudioServiceStreamShared.h
@@ -46,53 +46,55 @@
     AAudioServiceStreamShared(android::AAudioService &aAudioService);
     virtual ~AAudioServiceStreamShared() = default;
 
-    aaudio_result_t open(const aaudio::AAudioStreamRequest &request,
-                         aaudio::AAudioStreamConfiguration &configurationOutput) override;
+    static std::string dumpHeader();
 
-    /**
-     * Start the flow of audio data.
-     *
-     * This is not guaranteed to be synchronous but it currently is.
-     * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
-     */
-    aaudio_result_t start() override;
+    std::string dump() const override;
 
-    /**
-     * Stop the flow of data so that start() can resume without loss of data.
-     *
-     * This is not guaranteed to be synchronous but it currently is.
-     * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete.
-    */
-    aaudio_result_t pause() override;
-
-    /**
-     * Stop the flow of data after data in buffer has played.
-     */
-    aaudio_result_t stop() override;
-
-    /**
-     *  Discard any data held by the underlying HAL or Service.
-     *
-     * This is not guaranteed to be synchronous but it currently is.
-     * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete.
-     */
-    aaudio_result_t flush() override;
+    aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
 
     aaudio_result_t close() override;
 
-    android::FifoBuffer *getDataFifoBuffer() { return mAudioDataQueue->getFifoBuffer(); }
+    /**
+     * This must be locked when calling getAudioDataFifoBuffer_l() and while
+     * using the FifoBuffer it returns.
+     */
+    std::mutex &getAudioDataQueueLock() {
+        return mAudioDataQueueLock;
+    }
+
+    /**
+     * This must only be call under getAudioDataQueueLock().
+     * @return
+     */
+    android::FifoBuffer *getAudioDataFifoBuffer_l() { return (mAudioDataQueue == nullptr)
+                                                      ? nullptr
+                                                      : mAudioDataQueue->getFifoBuffer(); }
 
     /* Keep a record of when a buffer transfer completed.
      * This allows for a more accurate timing model.
      */
-    void markTransferTime(int64_t nanoseconds);
+    void markTransferTime(Timestamp &timestamp);
+
+    void setTimestampPositionOffset(int64_t deltaFrames) {
+        mTimestampPositionOffset.store(deltaFrames);
+    }
+
+    void incrementXRunCount() {
+        mXRunCount++;
+    }
+
+    int32_t getXRunCount() const {
+        return mXRunCount.load();
+    }
 
 protected:
 
-    aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) override;
+    aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) override;
 
     aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) override;
 
+    aaudio_result_t getHardwareTimestamp(int64_t *positionFrames, int64_t *timeNanos) override;
+
     /**
      * @param requestedCapacityFrames
      * @param framesPerBurst
@@ -102,12 +104,12 @@
                                             int32_t framesPerBurst);
 
 private:
-    android::AAudioService  &mAudioService;
-    AAudioServiceEndpoint   *mServiceEndpoint = nullptr;
-    SharedRingBuffer        *mAudioDataQueue = nullptr;
+    SharedRingBuffer        *mAudioDataQueue = nullptr; // protected by mAudioDataQueueLock
+    std::mutex               mAudioDataQueueLock;
 
-    int64_t                  mMarkedPosition = 0;
-    int64_t                  mMarkedTime = 0;
+    std::atomic<int64_t>     mTimestampPositionOffset;
+    std::atomic<int32_t>     mXRunCount;
+
 };
 
 } /* namespace aaudio */
diff --git a/services/oboeservice/AAudioStreamTracker.cpp b/services/oboeservice/AAudioStreamTracker.cpp
new file mode 100644
index 0000000..ef88b34
--- /dev/null
+++ b/services/oboeservice/AAudioStreamTracker.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AAudioStreamTracker"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+#include <aaudio/AAudio.h>
+#include <utils/String16.h>
+
+#include "AAudioStreamTracker.h"
+
+using namespace android;
+using namespace aaudio;
+
+sp<AAudioServiceStreamBase> AAudioStreamTracker::removeStreamByHandle(
+        aaudio_handle_t streamHandle) {
+    std::lock_guard<std::mutex> lock(mHandleLock);
+    sp<AAudioServiceStreamBase> serviceStream;
+    auto it = mStreamsByHandle.find(streamHandle);
+    if (it != mStreamsByHandle.end()) {
+        serviceStream = it->second;
+        mStreamsByHandle.erase(it);
+    }
+    return serviceStream;
+}
+
+sp<AAudioServiceStreamBase> AAudioStreamTracker::getStreamByHandle(
+        aaudio_handle_t streamHandle) {
+    std::lock_guard<std::mutex> lock(mHandleLock);
+    sp<AAudioServiceStreamBase> serviceStream;
+    auto it = mStreamsByHandle.find(streamHandle);
+    if (it != mStreamsByHandle.end()) {
+        serviceStream = it->second;
+    }
+    return serviceStream;
+}
+
+// advance to next legal handle value
+__attribute__((no_sanitize("integer")))
+aaudio_handle_t AAudioStreamTracker::bumpHandle(aaudio_handle_t handle) {
+    handle++;
+    // Only use positive integers.
+    if (handle <= 0) {
+        handle = 1;
+    }
+    return handle;
+}
+
+aaudio_handle_t AAudioStreamTracker::addStreamForHandle(sp<AAudioServiceStreamBase> serviceStream) {
+    std::lock_guard<std::mutex> lock(mHandleLock);
+    aaudio_handle_t handle = mPreviousHandle.load();
+    // Assign a unique handle.
+    while (true) {
+        handle = bumpHandle(handle);
+        sp<AAudioServiceStreamBase> oldServiceStream = mStreamsByHandle[handle];
+        // Is this an unused handle? It would be extremely unlikely to wrap
+        // around and collide with a very old handle. But just in case.
+        if (oldServiceStream.get() == nullptr) {
+            mStreamsByHandle[handle] = serviceStream;
+            break;
+        }
+    }
+    mPreviousHandle.store(handle);
+    return handle;
+}
+
+std::string AAudioStreamTracker::dump() const {
+    std::stringstream result;
+    const bool isLocked = AAudio_tryUntilTrue(
+            [this]()->bool { return mHandleLock.try_lock(); } /* f */,
+            50 /* times */,
+            20 /* sleepMs */);
+    if (!isLocked) {
+        result << "AAudioStreamTracker may be deadlocked\n";
+    } else {
+        result << "Stream Handles:\n";
+        for (const auto&  it : mStreamsByHandle) {
+            aaudio_handle_t handle = it.second->getHandle();
+            result << "    0x" << std::setfill('0') << std::setw(8) << std::hex << handle
+                   << std::dec << std::setfill(' ') << "\n";
+        }
+
+        mHandleLock.unlock();
+    }
+    return result.str();
+}
diff --git a/services/oboeservice/AAudioStreamTracker.h b/services/oboeservice/AAudioStreamTracker.h
new file mode 100644
index 0000000..70d440d
--- /dev/null
+++ b/services/oboeservice/AAudioStreamTracker.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAUDIO_AAUDIO_STREAM_TRACKER_H
+#define AAUDIO_AAUDIO_STREAM_TRACKER_H
+
+#include <time.h>
+#include <pthread.h>
+
+#include <aaudio/AAudio.h>
+
+#include "binding/AAudioCommon.h"
+
+#include "AAudioServiceStreamBase.h"
+
+namespace aaudio {
+
+class AAudioStreamTracker {
+
+public:
+    /**
+     * Remove the stream associated with the handle.
+     * @param streamHandle
+     * @return strong pointer to the stream if found or to nullptr
+     */
+    android::sp<AAudioServiceStreamBase> removeStreamByHandle(aaudio_handle_t streamHandle);
+
+    /**
+     * Look up a stream based on the handle.
+     * @param streamHandle
+     * @return strong pointer to the stream if found or to nullptr
+     */
+    android::sp<aaudio::AAudioServiceStreamBase> getStreamByHandle(aaudio_handle_t streamHandle);
+
+    /**
+     * Store a strong pointer to the stream and return a unique handle for future reference.
+     * The handle is guaranteed not to collide with an existing stream.
+     * @param serviceStream
+     * @return handle for identifying the stream
+     */
+    aaudio_handle_t addStreamForHandle(android::sp<AAudioServiceStreamBase> serviceStream);
+
+    /**
+     * @return string that can be added to dumpsys
+     */
+    std::string dump() const;
+
+private:
+    static aaudio_handle_t bumpHandle(aaudio_handle_t handle);
+
+    // Track stream using a unique handle that wraps. Only use positive half.
+    mutable std::mutex                mHandleLock;
+    std::atomic<aaudio_handle_t>      mPreviousHandle{0};
+    std::map<aaudio_handle_t, android::sp<aaudio::AAudioServiceStreamBase>> mStreamsByHandle;
+};
+
+
+} /* namespace aaudio */
+
+#endif /* AAUDIO_AAUDIO_STREAM_TRACKER_H */
diff --git a/services/oboeservice/AAudioThread.cpp b/services/oboeservice/AAudioThread.cpp
index ebb50f8..c6fb57d 100644
--- a/services/oboeservice/AAudioThread.cpp
+++ b/services/oboeservice/AAudioThread.cpp
@@ -53,7 +53,7 @@
 
 aaudio_result_t AAudioThread::start(Runnable *runnable) {
     if (mHasThread) {
-        ALOGE("AAudioThread::start() - mHasThread.load() already true");
+        ALOGE("AAudioThread::start() - mHasThread already true");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     // mRunnable will be read by the new thread when it starts.
@@ -71,6 +71,7 @@
 
 aaudio_result_t AAudioThread::stop() {
     if (!mHasThread) {
+        ALOGE("AAudioThread::stop() but no thread running");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     int err = pthread_join(mThread, nullptr);
diff --git a/services/oboeservice/Android.mk b/services/oboeservice/Android.mk
index a896a7a..584b2ef 100644
--- a/services/oboeservice/Android.mk
+++ b/services/oboeservice/Android.mk
@@ -22,7 +22,6 @@
     $(TOP)/frameworks/av/media/libaaudio/src
 
 LOCAL_SRC_FILES += \
-    $(LIBAAUDIO_SRC_DIR)/utility/HandleTracker.cpp \
     SharedMemoryProxy.cpp \
     SharedRingBuffer.cpp \
     AAudioClientTracker.cpp \
@@ -31,10 +30,13 @@
     AAudioService.cpp \
     AAudioServiceEndpoint.cpp \
     AAudioServiceEndpointCapture.cpp \
+    AAudioServiceEndpointMMAP.cpp \
     AAudioServiceEndpointPlay.cpp \
+    AAudioServiceEndpointShared.cpp \
     AAudioServiceStreamBase.cpp \
     AAudioServiceStreamMMAP.cpp \
     AAudioServiceStreamShared.cpp \
+    AAudioStreamTracker.cpp \
     TimestampScheduler.cpp \
     AAudioThread.cpp
 
diff --git a/services/oboeservice/OWNERS b/services/oboeservice/OWNERS
new file mode 100644
index 0000000..f4d51f9
--- /dev/null
+++ b/services/oboeservice/OWNERS
@@ -0,0 +1 @@
+philburk@google.com
diff --git a/services/radio/Android.mk b/services/radio/Android.mk
deleted file mode 100644
index 1b50dc3..0000000
--- a/services/radio/Android.mk
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright 2014 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-
-LOCAL_SRC_FILES:= \
-    RadioService.cpp
-
-LOCAL_SHARED_LIBRARIES:= \
-    liblog \
-    libutils \
-    libbinder \
-    libcutils \
-    libaudioclient \
-    libhardware \
-    libradio \
-    libradio_metadata
-
-ifeq ($(USE_LEGACY_LOCAL_AUDIO_HAL),true)
-# libhardware configuration
-LOCAL_SRC_FILES +=               \
-    RadioHalLegacy.cpp
-else
-# Treble configuration
-
-LOCAL_SRC_FILES += \
-    HidlUtils.cpp \
-    RadioHalHidl.cpp
-
-LOCAL_SHARED_LIBRARIES += \
-    libhwbinder \
-    libhidlbase \
-    libhidltransport \
-    libbase \
-    libaudiohal \
-    android.hardware.broadcastradio@1.0
-endif
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_MODULE:= libradioservice
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/radio/HidlUtils.cpp b/services/radio/HidlUtils.cpp
deleted file mode 100644
index 6895377..0000000
--- a/services/radio/HidlUtils.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_TAG "HidlUtils"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <utils/misc.h>
-#include <system/radio_metadata.h>
-
-#include "HidlUtils.h"
-
-namespace android {
-
-using android::hardware::broadcastradio::V1_0::MetadataType;
-using android::hardware::broadcastradio::V1_0::Band;
-using android::hardware::broadcastradio::V1_0::Deemphasis;
-using android::hardware::broadcastradio::V1_0::Rds;
-
-//static
-int HidlUtils::convertHalResult(Result result)
-{
-    switch (result) {
-        case Result::OK:
-            return 0;
-        case Result::INVALID_ARGUMENTS:
-            return -EINVAL;
-        case Result::INVALID_STATE:
-            return -ENOSYS;
-        case Result::TIMEOUT:
-            return -ETIMEDOUT;
-        case Result::NOT_INITIALIZED:
-        default:
-            return -ENODEV;
-    }
-}
-
-
-//static
-void HidlUtils::convertBandConfigToHal(BandConfig *halConfig,
-                                       const radio_hal_band_config_t *config)
-{
-    halConfig->type = static_cast<Band>(config->type);
-    halConfig->antennaConnected = config->antenna_connected;
-    halConfig->lowerLimit = config->lower_limit;
-    halConfig->upperLimit = config->upper_limit;
-    halConfig->spacings.setToExternal(const_cast<unsigned int *>(&config->spacings[0]),
-                                       config->num_spacings * sizeof(uint32_t));
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-    halConfig->spacings.resize(config->num_spacings);
-
-    if (halConfig->type == Band::FM) {
-        halConfig->ext.fm.deemphasis = static_cast<Deemphasis>(config->fm.deemphasis);
-        halConfig->ext.fm.stereo = config->fm.stereo;
-        halConfig->ext.fm.rds = static_cast<Rds>(config->fm.rds);
-        halConfig->ext.fm.ta = config->fm.ta;
-        halConfig->ext.fm.af = config->fm.af;
-        halConfig->ext.fm.ea = config->fm.ea;
-    } else {
-        halConfig->ext.am.stereo = config->am.stereo;
-    }
-}
-
-//static
-void HidlUtils::convertPropertiesFromHal(radio_hal_properties_t *properties,
-                                         const Properties *halProperties)
-{
-    properties->class_id = static_cast<radio_class_t>(halProperties->classId);
-    strlcpy(properties->implementor, halProperties->implementor.c_str(), RADIO_STRING_LEN_MAX);
-    strlcpy(properties->product, halProperties->product.c_str(), RADIO_STRING_LEN_MAX);
-    strlcpy(properties->version, halProperties->version.c_str(), RADIO_STRING_LEN_MAX);
-    strlcpy(properties->serial, halProperties->serial.c_str(), RADIO_STRING_LEN_MAX);
-    properties->num_tuners = halProperties->numTuners;
-    properties->num_audio_sources = halProperties->numAudioSources;
-    properties->supports_capture = halProperties->supportsCapture;
-    properties->num_bands = halProperties->bands.size();
-
-    for (size_t i = 0; i < halProperties->bands.size(); i++) {
-        convertBandConfigFromHal(&properties->bands[i], &halProperties->bands[i]);
-    }
-}
-
-//static
-void HidlUtils::convertBandConfigFromHal(radio_hal_band_config_t *config,
-                                         const BandConfig *halConfig)
-{
-    config->type = static_cast<radio_band_t>(halConfig->type);
-    config->antenna_connected = halConfig->antennaConnected;
-    config->lower_limit = halConfig->lowerLimit;
-    config->upper_limit = halConfig->upperLimit;
-    config->num_spacings = halConfig->spacings.size();
-    if (config->num_spacings > RADIO_NUM_SPACINGS_MAX) {
-        config->num_spacings = RADIO_NUM_SPACINGS_MAX;
-    }
-    memcpy(config->spacings, halConfig->spacings.data(),
-           sizeof(uint32_t) * config->num_spacings);
-
-    if (halConfig->type == Band::FM) {
-        config->fm.deemphasis = static_cast<radio_deemphasis_t>(halConfig->ext.fm.deemphasis);
-        config->fm.stereo = halConfig->ext.fm.stereo;
-        config->fm.rds = static_cast<radio_rds_t>(halConfig->ext.fm.rds);
-        config->fm.ta = halConfig->ext.fm.ta;
-        config->fm.af = halConfig->ext.fm.af;
-        config->fm.ea = halConfig->ext.fm.ea;
-    } else {
-        config->am.stereo = halConfig->ext.am.stereo;
-    }
-}
-
-
-//static
-void HidlUtils::convertProgramInfoFromHal(radio_program_info_t *info,
-                                          const ProgramInfo *halInfo)
-{
-    info->channel = halInfo->channel;
-    info->sub_channel = halInfo->subChannel;
-    info->tuned = halInfo->tuned;
-    info->stereo = halInfo->stereo;
-    info->digital = halInfo->digital;
-    info->signal_strength = halInfo->signalStrength;
-    convertMetaDataFromHal(&info->metadata, halInfo->metadata,
-                           halInfo->channel, halInfo->subChannel);
-}
-
-// TODO(twasilczyk): drop unnecessary channel info
-//static
-void HidlUtils::convertMetaDataFromHal(radio_metadata_t **metadata,
-                                       const hidl_vec<MetaData>& halMetadata,
-                                       uint32_t channel __unused,
-                                       uint32_t subChannel __unused)
-{
-
-    if (metadata == nullptr || *metadata == nullptr) {
-        ALOGE("destination metadata buffer is a nullptr");
-        return;
-    }
-    for (size_t i = 0; i < halMetadata.size(); i++) {
-        radio_metadata_key_t key = static_cast<radio_metadata_key_t>(halMetadata[i].key);
-        radio_metadata_type_t type = static_cast<radio_metadata_key_t>(halMetadata[i].type);
-        radio_metadata_clock_t clock;
-
-        switch (type) {
-        case RADIO_METADATA_TYPE_INT:
-            radio_metadata_add_int(metadata, key, halMetadata[i].intValue);
-            break;
-        case RADIO_METADATA_TYPE_TEXT:
-            radio_metadata_add_text(metadata, key, halMetadata[i].stringValue.c_str());
-            break;
-        case RADIO_METADATA_TYPE_RAW:
-            radio_metadata_add_raw(metadata, key,
-                                   halMetadata[i].rawValue.data(),
-                                   halMetadata[i].rawValue.size());
-            break;
-        case RADIO_METADATA_TYPE_CLOCK:
-            clock.utc_seconds_since_epoch =
-                    halMetadata[i].clockValue.utcSecondsSinceEpoch;
-            clock.timezone_offset_in_minutes =
-                    halMetadata[i].clockValue.timezoneOffsetInMinutes;
-            radio_metadata_add_clock(metadata, key, &clock);
-            break;
-        default:
-            ALOGW("%s invalid metadata type %u",__FUNCTION__, halMetadata[i].type);
-            break;
-        }
-    }
-}
-
-}  // namespace android
diff --git a/services/radio/HidlUtils.h b/services/radio/HidlUtils.h
deleted file mode 100644
index c771060..0000000
--- a/services/radio/HidlUtils.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef ANDROID_HARDWARE_RADIO_HAL_HIDL_UTILS_H
-#define ANDROID_HARDWARE_RADIO_HAL_HIDL_UTILS_H
-
-#include <android/hardware/broadcastradio/1.0/types.h>
-#include <hardware/radio.h>
-
-namespace android {
-
-using android::hardware::hidl_vec;
-using android::hardware::broadcastradio::V1_0::Result;
-using android::hardware::broadcastradio::V1_0::Properties;
-using android::hardware::broadcastradio::V1_0::BandConfig;
-using android::hardware::broadcastradio::V1_0::ProgramInfo;
-using android::hardware::broadcastradio::V1_0::MetaData;
-
-class HidlUtils {
-public:
-    static int convertHalResult(Result result);
-    static void convertBandConfigFromHal(radio_hal_band_config_t *config,
-                                         const BandConfig *halConfig);
-    static void convertPropertiesFromHal(radio_hal_properties_t *properties,
-                                         const Properties *halProperties);
-    static void convertBandConfigToHal(BandConfig *halConfig,
-                                       const radio_hal_band_config_t *config);
-    static void convertProgramInfoFromHal(radio_program_info_t *info,
-                                          const ProgramInfo *halInfo);
-    static void convertMetaDataFromHal(radio_metadata_t **metadata,
-                                       const hidl_vec<MetaData>& halMetadata,
-                                       uint32_t channel,
-                                       uint32_t subChannel);
-};
-
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_RADIO_HAL_HIDL_UTILS_H
diff --git a/services/radio/OWNERS b/services/radio/OWNERS
deleted file mode 100644
index eb9549a..0000000
--- a/services/radio/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-elaurent@google.com
-hunga@google.com
-twasilczyk@google.com
diff --git a/services/radio/RadioHalHidl.cpp b/services/radio/RadioHalHidl.cpp
deleted file mode 100644
index f637275..0000000
--- a/services/radio/RadioHalHidl.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "RadioHalHidl"
-//#define LOG_NDEBUG 0
-
-#include <media/audiohal/hidl/HalDeathHandler.h>
-#include <utils/Log.h>
-#include <utils/misc.h>
-#include <system/RadioMetadataWrapper.h>
-#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
-
-#include "RadioHalHidl.h"
-#include "HidlUtils.h"
-
-namespace android {
-
-using android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
-using android::hardware::broadcastradio::V1_0::Class;
-using android::hardware::broadcastradio::V1_0::Direction;
-using android::hardware::broadcastradio::V1_0::Properties;
-
-
-/* static */
-sp<RadioInterface> RadioInterface::connectModule(radio_class_t classId)
-{
-    return new RadioHalHidl(classId);
-}
-
-int RadioHalHidl::getProperties(radio_hal_properties_t *properties)
-{
-    ALOGV("%s IN", __FUNCTION__);
-    sp<IBroadcastRadio> module = getService();
-    if (module == 0) {
-        return -ENODEV;
-    }
-    Properties halProperties;
-    Result halResult = Result::NOT_INITIALIZED;
-    Return<void> hidlReturn =
-            module->getProperties([&](Result result, const Properties& properties) {
-                    halResult = result;
-                    if (result == Result::OK) {
-                        halProperties = properties;
-                    }
-                });
-
-    if (halResult == Result::OK) {
-        HidlUtils::convertPropertiesFromHal(properties, &halProperties);
-    }
-    return HidlUtils::convertHalResult(halResult);
-}
-
-int RadioHalHidl::openTuner(const radio_hal_band_config_t *config,
-                            bool audio,
-                            sp<TunerCallbackInterface> callback,
-                            sp<TunerInterface>& tuner)
-{
-    sp<IBroadcastRadio> module = getService();
-    if (module == 0) {
-        return -ENODEV;
-    }
-    sp<Tuner> tunerImpl = new Tuner(callback, this);
-
-    BandConfig halConfig;
-    Result halResult = Result::NOT_INITIALIZED;
-    sp<ITuner> halTuner;
-
-    HidlUtils::convertBandConfigToHal(&halConfig, config);
-    Return<void> hidlReturn =
-            module->openTuner(halConfig, audio, tunerImpl,
-                              [&](Result result, const sp<ITuner>& tuner) {
-                    halResult = result;
-                    if (result == Result::OK) {
-                        halTuner = tuner;
-                    }
-                });
-
-    if (halResult == Result::OK) {
-        tunerImpl->setHalTuner(halTuner);
-        tuner = tunerImpl;
-    }
-
-    return HidlUtils::convertHalResult(halResult);
-}
-
-int RadioHalHidl::closeTuner(sp<TunerInterface>& tuner)
-{
-    sp<Tuner> tunerImpl = static_cast<Tuner *>(tuner.get());
-    sp<ITuner> clearTuner;
-    tunerImpl->setHalTuner(clearTuner);
-    return 0;
-}
-
-RadioHalHidl::RadioHalHidl(radio_class_t classId)
-    : mClassId(classId)
-{
-}
-
-RadioHalHidl::~RadioHalHidl()
-{
-}
-
-sp<IBroadcastRadio> RadioHalHidl::getService()
-{
-    if (mHalModule == 0) {
-        sp<IBroadcastRadioFactory> factory = IBroadcastRadioFactory::getService();
-        if (factory != 0) {
-            factory->connectModule(static_cast<Class>(mClassId),
-                               [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
-                if (retval == Result::OK) {
-                    mHalModule = result;
-                }
-            });
-        }
-    }
-    ALOGV("%s OUT module %p", __FUNCTION__, mHalModule.get());
-    return mHalModule;
-}
-
-void RadioHalHidl::clearService()
-{
-    ALOGV("%s IN module %p", __FUNCTION__, mHalModule.get());
-    mHalModule.clear();
-}
-
-
-int RadioHalHidl::Tuner::setConfiguration(const radio_hal_band_config_t *config)
-{
-    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
-
-    if (mHalTuner == 0) {
-        return -ENODEV;
-    }
-    BandConfig halConfig;
-    HidlUtils::convertBandConfigToHal(&halConfig, config);
-
-    Return<Result> hidlResult = mHalTuner->setConfiguration(halConfig);
-    return HidlUtils::convertHalResult(hidlResult);
-}
-
-int RadioHalHidl::Tuner::getConfiguration(radio_hal_band_config_t *config)
-{
-    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
-    if (mHalTuner == 0) {
-        return -ENODEV;
-    }
-    BandConfig halConfig;
-    Result halResult;
-    Return<void> hidlReturn =
-            mHalTuner->getConfiguration([&](Result result, const BandConfig& config) {
-                    halResult = result;
-                    if (result == Result::OK) {
-                        halConfig = config;
-                    }
-                });
-    if (hidlReturn.isOk() && halResult == Result::OK) {
-        HidlUtils::convertBandConfigFromHal(config, &halConfig);
-    }
-    return HidlUtils::convertHalResult(halResult);
-}
-
-int RadioHalHidl::Tuner::scan(radio_direction_t direction, bool skip_sub_channel)
-{
-    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
-    if (mHalTuner == 0) {
-        return -ENODEV;
-    }
-    Return<Result> hidlResult =
-            mHalTuner->scan(static_cast<Direction>(direction), skip_sub_channel);
-    return HidlUtils::convertHalResult(hidlResult);
-}
-
-int RadioHalHidl::Tuner::step(radio_direction_t direction, bool skip_sub_channel)
-{
-    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
-    if (mHalTuner == 0) {
-        return -ENODEV;
-    }
-    Return<Result> hidlResult =
-            mHalTuner->step(static_cast<Direction>(direction), skip_sub_channel);
-    return HidlUtils::convertHalResult(hidlResult);
-}
-
-int RadioHalHidl::Tuner::tune(unsigned int channel, unsigned int sub_channel)
-{
-    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
-    if (mHalTuner == 0) {
-        return -ENODEV;
-    }
-    Return<Result> hidlResult =
-            mHalTuner->tune(channel, sub_channel);
-    return HidlUtils::convertHalResult(hidlResult);
-}
-
-int RadioHalHidl::Tuner::cancel()
-{
-    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
-    if (mHalTuner == 0) {
-        return -ENODEV;
-    }
-    Return<Result> hidlResult = mHalTuner->cancel();
-    return HidlUtils::convertHalResult(hidlResult);
-}
-
-int RadioHalHidl::Tuner::getProgramInformation(radio_program_info_t *info)
-{
-    ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
-    if (mHalTuner == 0) {
-        return -ENODEV;
-    }
-    if (info == nullptr || info->metadata == nullptr) {
-        return BAD_VALUE;
-    }
-    ProgramInfo halInfo;
-    Result halResult;
-    Return<void> hidlReturn = mHalTuner->getProgramInformation(
-        [&](Result result, const ProgramInfo& info) {
-            halResult = result;
-            if (result == Result::OK) {
-                halInfo = info;
-            }
-        });
-    if (hidlReturn.isOk() && halResult == Result::OK) {
-        HidlUtils::convertProgramInfoFromHal(info, &halInfo);
-    }
-    return HidlUtils::convertHalResult(halResult);
-}
-
-Return<void> RadioHalHidl::Tuner::hardwareFailure()
-{
-    ALOGV("%s IN", __FUNCTION__);
-    handleHwFailure();
-    return Return<void>();
-}
-
-Return<void> RadioHalHidl::Tuner::configChange(Result result, const BandConfig& config)
-{
-    ALOGV("%s IN", __FUNCTION__);
-    radio_hal_event_t event;
-    memset(&event, 0, sizeof(radio_hal_event_t));
-    event.type = RADIO_EVENT_CONFIG;
-    event.status = HidlUtils::convertHalResult(result);
-    HidlUtils::convertBandConfigFromHal(&event.config, &config);
-    onCallback(&event);
-    return Return<void>();
-}
-
-Return<void> RadioHalHidl::Tuner::tuneComplete(Result result, const ProgramInfo& info)
-{
-    ALOGV("%s IN", __FUNCTION__);
-    radio_hal_event_t event = {};
-    RadioMetadataWrapper metadataWrapper(&event.info.metadata);
-
-    event.type = RADIO_EVENT_TUNED;
-    event.status = HidlUtils::convertHalResult(result);
-    HidlUtils::convertProgramInfoFromHal(&event.info, &info);
-    onCallback(&event);
-    return Return<void>();
-}
-
-Return<void> RadioHalHidl::Tuner::afSwitch(const ProgramInfo& info)
-{
-    ALOGV("%s IN", __FUNCTION__);
-    radio_hal_event_t event = {};
-    RadioMetadataWrapper metadataWrapper(&event.info.metadata);
-
-    event.type = RADIO_EVENT_AF_SWITCH;
-    HidlUtils::convertProgramInfoFromHal(&event.info, &info);
-    onCallback(&event);
-    return Return<void>();
-}
-
-Return<void> RadioHalHidl::Tuner::antennaStateChange(bool connected)
-{
-    ALOGV("%s IN", __FUNCTION__);
-    radio_hal_event_t event;
-    memset(&event, 0, sizeof(radio_hal_event_t));
-    event.type = RADIO_EVENT_ANTENNA;
-    event.on = connected;
-    onCallback(&event);
-    return Return<void>();
-}
-Return<void> RadioHalHidl::Tuner::trafficAnnouncement(bool active)
-{
-    ALOGV("%s IN", __FUNCTION__);
-    radio_hal_event_t event;
-    memset(&event, 0, sizeof(radio_hal_event_t));
-    event.type = RADIO_EVENT_TA;
-    event.on = active;
-    onCallback(&event);
-    return Return<void>();
-}
-Return<void> RadioHalHidl::Tuner::emergencyAnnouncement(bool active)
-{
-    ALOGV("%s IN", __FUNCTION__);
-    radio_hal_event_t event;
-    memset(&event, 0, sizeof(radio_hal_event_t));
-    event.type = RADIO_EVENT_EA;
-    event.on = active;
-    onCallback(&event);
-    return Return<void>();
-}
-Return<void> RadioHalHidl::Tuner::newMetadata(uint32_t channel, uint32_t subChannel,
-                                          const ::android::hardware::hidl_vec<MetaData>& metadata)
-{
-    ALOGV("%s IN", __FUNCTION__);
-    radio_hal_event_t event = {};
-    RadioMetadataWrapper metadataWrapper(&event.metadata);
-
-    event.type = RADIO_EVENT_METADATA;
-    HidlUtils::convertMetaDataFromHal(&event.metadata, metadata, channel, subChannel);
-    onCallback(&event);
-    return Return<void>();
-}
-
-
-RadioHalHidl::Tuner::Tuner(sp<TunerCallbackInterface> callback, sp<RadioHalHidl> module)
-    : TunerInterface(), mHalTuner(NULL), mCallback(callback), mParentModule(module)
-{
-    // Make sure the handler we are passing in only deals with const members,
-    // as it can be called on an arbitrary thread.
-    const auto& self = this;
-    HalDeathHandler::getInstance()->registerAtExitHandler(
-            this, [&self]() { self->sendHwFailureEvent(); });
-}
-
-
-RadioHalHidl::Tuner::~Tuner()
-{
-    HalDeathHandler::getInstance()->unregisterAtExitHandler(this);
-}
-
-void RadioHalHidl::Tuner::setHalTuner(sp<ITuner>& halTuner) {
-    if (mHalTuner != 0) {
-        mHalTuner->unlinkToDeath(HalDeathHandler::getInstance());
-    }
-    mHalTuner = halTuner;
-    if (mHalTuner != 0) {
-        mHalTuner->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
-    }
-}
-
-void RadioHalHidl::Tuner::handleHwFailure()
-{
-    ALOGV("%s IN", __FUNCTION__);
-    sp<RadioHalHidl> parentModule = mParentModule.promote();
-    if (parentModule != 0) {
-        parentModule->clearService();
-    }
-    sendHwFailureEvent();
-    mHalTuner.clear();
-}
-
-void RadioHalHidl::Tuner::sendHwFailureEvent() const
-{
-    radio_hal_event_t event;
-    memset(&event, 0, sizeof(radio_hal_event_t));
-    event.type = RADIO_EVENT_HW_FAILURE;
-    onCallback(&event);
-}
-
-void RadioHalHidl::Tuner::onCallback(radio_hal_event_t *halEvent) const
-{
-    if (mCallback != 0) {
-        mCallback->onEvent(halEvent);
-    }
-}
-
-} // namespace android
diff --git a/services/radio/RadioHalHidl.h b/services/radio/RadioHalHidl.h
deleted file mode 100644
index f98420d..0000000
--- a/services/radio/RadioHalHidl.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_HAL_HIDL_H
-#define ANDROID_HARDWARE_RADIO_HAL_HIDL_H
-
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-#include "RadioInterface.h"
-#include "TunerInterface.h"
-#include "TunerCallbackInterface.h"
-#include <android/hardware/broadcastradio/1.0/types.h>
-#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
-#include <android/hardware/broadcastradio/1.0/ITuner.h>
-#include <android/hardware/broadcastradio/1.0/ITunerCallback.h>
-
-namespace android {
-
-using android::hardware::Return;
-using android::hardware::broadcastradio::V1_0::Result;
-using android::hardware::broadcastradio::V1_0::IBroadcastRadio;
-using android::hardware::broadcastradio::V1_0::ITuner;
-using android::hardware::broadcastradio::V1_0::ITunerCallback;
-
-using android::hardware::broadcastradio::V1_0::BandConfig;
-using android::hardware::broadcastradio::V1_0::ProgramInfo;
-using android::hardware::broadcastradio::V1_0::MetaData;
-
-class RadioHalHidl : public RadioInterface
-{
-public:
-                    RadioHalHidl(radio_class_t classId);
-
-                    // RadioInterface
-        virtual int getProperties(radio_hal_properties_t *properties);
-        virtual int openTuner(const radio_hal_band_config_t *config,
-                              bool audio,
-                              sp<TunerCallbackInterface> callback,
-                              sp<TunerInterface>& tuner);
-        virtual int closeTuner(sp<TunerInterface>& tuner);
-
-        class Tuner  : public TunerInterface, public virtual ITunerCallback
-        {
-        public:
-                        Tuner(sp<TunerCallbackInterface> callback, sp<RadioHalHidl> module);
-
-                        // TunerInterface
-            virtual int setConfiguration(const radio_hal_band_config_t *config);
-            virtual int getConfiguration(radio_hal_band_config_t *config);
-            virtual int scan(radio_direction_t direction, bool skip_sub_channel);
-            virtual int step(radio_direction_t direction, bool skip_sub_channel);
-            virtual int tune(unsigned int channel, unsigned int sub_channel);
-            virtual int cancel();
-            virtual int getProgramInformation(radio_program_info_t *info);
-
-                        // ITunerCallback
-            virtual Return<void> hardwareFailure();
-            virtual Return<void> configChange(Result result, const BandConfig& config);
-            virtual Return<void> tuneComplete(Result result, const ProgramInfo& info);
-            virtual Return<void> afSwitch(const ProgramInfo& info);
-            virtual Return<void> antennaStateChange(bool connected);
-            virtual Return<void> trafficAnnouncement(bool active);
-            virtual Return<void> emergencyAnnouncement(bool active);
-            virtual Return<void> newMetadata(uint32_t channel, uint32_t subChannel,
-                                         const ::android::hardware::hidl_vec<MetaData>& metadata);
-
-            void setHalTuner(sp<ITuner>& halTuner);
-            sp<ITuner> getHalTuner() { return mHalTuner; }
-
-        private:
-            virtual          ~Tuner();
-
-                    void     onCallback(radio_hal_event_t *halEvent) const;
-                    void     handleHwFailure();
-                    void     sendHwFailureEvent() const;
-
-            sp<ITuner> mHalTuner;
-            const sp<TunerCallbackInterface> mCallback;
-            wp<RadioHalHidl> mParentModule;
-        };
-
-        sp<IBroadcastRadio> getService();
-        void clearService();
-
-private:
-        virtual         ~RadioHalHidl();
-
-                radio_class_t mClassId;
-                sp<IBroadcastRadio> mHalModule;
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_RADIO_HAL_HIDL_H
diff --git a/services/radio/RadioHalLegacy.cpp b/services/radio/RadioHalLegacy.cpp
deleted file mode 100644
index d50ccd4..0000000
--- a/services/radio/RadioHalLegacy.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "RadioHalLegacy"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <utils/misc.h>
-#include "RadioHalLegacy.h"
-
-namespace android {
-
-const char *RadioHalLegacy::sClassModuleNames[] = {
-    RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */
-    RADIO_HARDWARE_MODULE_ID_SAT,  /* corresponds to RADIO_CLASS_SAT */
-    RADIO_HARDWARE_MODULE_ID_DT,   /* corresponds to RADIO_CLASS_DT */
-};
-
-/* static */
-sp<RadioInterface> RadioInterface::connectModule(radio_class_t classId)
-{
-    return new RadioHalLegacy(classId);
-}
-
-RadioHalLegacy::RadioHalLegacy(radio_class_t classId)
-    : RadioInterface(), mClassId(classId), mHwDevice(NULL)
-{
-}
-
-void RadioHalLegacy::onFirstRef()
-{
-    const hw_module_t *mod;
-    int rc;
-    ALOGI("%s mClassId %d", __FUNCTION__, mClassId);
-
-    mHwDevice = NULL;
-
-    if ((mClassId < 0) ||
-            (mClassId >= NELEM(sClassModuleNames))) {
-        ALOGE("invalid class ID %d", mClassId);
-        return;
-    }
-
-    ALOGI("%s RADIO_HARDWARE_MODULE_ID %s %s",
-          __FUNCTION__, RADIO_HARDWARE_MODULE_ID, sClassModuleNames[mClassId]);
-
-    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, sClassModuleNames[mClassId], &mod);
-    if (rc != 0) {
-        ALOGE("couldn't load radio module %s.%s (%s)",
-              RADIO_HARDWARE_MODULE_ID, sClassModuleNames[mClassId], strerror(-rc));
-        return;
-    }
-    rc = radio_hw_device_open(mod, &mHwDevice);
-    if (rc != 0) {
-        ALOGE("couldn't open radio hw device in %s.%s (%s)",
-              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
-        mHwDevice = NULL;
-        return;
-    }
-    if (mHwDevice->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
-        ALOGE("wrong radio hw device version %04x", mHwDevice->common.version);
-        radio_hw_device_close(mHwDevice);
-        mHwDevice = NULL;
-    }
-}
-
-RadioHalLegacy::~RadioHalLegacy()
-{
-    if (mHwDevice != NULL) {
-        radio_hw_device_close(mHwDevice);
-    }
-}
-
-int RadioHalLegacy::getProperties(radio_hal_properties_t *properties)
-{
-    if (mHwDevice == NULL) {
-        return -ENODEV;
-    }
-
-    int rc = mHwDevice->get_properties(mHwDevice, properties);
-    if (rc != 0) {
-        ALOGE("could not read implementation properties");
-    }
-
-    return rc;
-}
-
-int RadioHalLegacy::openTuner(const radio_hal_band_config_t *config,
-                bool audio,
-                sp<TunerCallbackInterface> callback,
-                sp<TunerInterface>& tuner)
-{
-    if (mHwDevice == NULL) {
-        return -ENODEV;
-    }
-    sp<Tuner> tunerImpl = new Tuner(callback);
-
-    const struct radio_tuner *halTuner;
-    int rc = mHwDevice->open_tuner(mHwDevice, config, audio,
-                                   RadioHalLegacy::Tuner::callback, tunerImpl.get(),
-                                   &halTuner);
-    if (rc == 0) {
-        tunerImpl->setHalTuner(halTuner);
-        tuner = tunerImpl;
-    }
-    return rc;
-}
-
-int RadioHalLegacy::closeTuner(sp<TunerInterface>& tuner)
-{
-    if (mHwDevice == NULL) {
-        return -ENODEV;
-    }
-    if (tuner == 0) {
-        return -EINVAL;
-    }
-    sp<Tuner> tunerImpl = (Tuner *)tuner.get();
-    return mHwDevice->close_tuner(mHwDevice, tunerImpl->getHalTuner());
-}
-
-int RadioHalLegacy::Tuner::setConfiguration(const radio_hal_band_config_t *config)
-{
-    if (mHalTuner == NULL) {
-        return -ENODEV;
-    }
-    return mHalTuner->set_configuration(mHalTuner, config);
-}
-
-int RadioHalLegacy::Tuner::getConfiguration(radio_hal_band_config_t *config)
-{
-    if (mHalTuner == NULL) {
-        return -ENODEV;
-    }
-    return mHalTuner->get_configuration(mHalTuner, config);
-}
-
-int RadioHalLegacy::Tuner::scan(radio_direction_t direction, bool skip_sub_channel)
-{
-    if (mHalTuner == NULL) {
-        return -ENODEV;
-    }
-    return mHalTuner->scan(mHalTuner, direction, skip_sub_channel);
-}
-
-int RadioHalLegacy::Tuner::step(radio_direction_t direction, bool skip_sub_channel)
-{
-    if (mHalTuner == NULL) {
-        return -ENODEV;
-    }
-    return mHalTuner->step(mHalTuner, direction, skip_sub_channel);
-}
-
-int RadioHalLegacy::Tuner::tune(unsigned int channel, unsigned int sub_channel)
-{
-    if (mHalTuner == NULL) {
-        return -ENODEV;
-    }
-    return mHalTuner->tune(mHalTuner, channel, sub_channel);
-}
-
-int RadioHalLegacy::Tuner::cancel()
-{
-    if (mHalTuner == NULL) {
-        return -ENODEV;
-    }
-    return mHalTuner->cancel(mHalTuner);
-}
-
-int RadioHalLegacy::Tuner::getProgramInformation(radio_program_info_t *info)
-{
-    if (mHalTuner == NULL) {
-        return -ENODEV;
-    }
-    return mHalTuner->get_program_information(mHalTuner, info);
-}
-
-void RadioHalLegacy::Tuner::onCallback(radio_hal_event_t *halEvent)
-{
-    if (mCallback != 0) {
-        mCallback->onEvent(halEvent);
-    }
-}
-
-//static
-void RadioHalLegacy::Tuner::callback(radio_hal_event_t *halEvent, void *cookie)
-{
-    wp<RadioHalLegacy::Tuner> weak = wp<RadioHalLegacy::Tuner>((RadioHalLegacy::Tuner *)cookie);
-    sp<RadioHalLegacy::Tuner> tuner = weak.promote();
-    if (tuner != 0) {
-        tuner->onCallback(halEvent);
-    }
-}
-
-RadioHalLegacy::Tuner::Tuner(sp<TunerCallbackInterface> callback)
-    : TunerInterface(), mHalTuner(NULL), mCallback(callback)
-{
-}
-
-
-RadioHalLegacy::Tuner::~Tuner()
-{
-}
-
-
-} // namespace android
diff --git a/services/radio/RadioHalLegacy.h b/services/radio/RadioHalLegacy.h
deleted file mode 100644
index 7d4831b..0000000
--- a/services/radio/RadioHalLegacy.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_HAL_LEGACY_H
-#define ANDROID_HARDWARE_RADIO_HAL_LEGACY_H
-
-#include <utils/RefBase.h>
-#include <hardware/radio.h>
-#include "RadioInterface.h"
-#include "TunerInterface.h"
-#include "TunerCallbackInterface.h"
-
-namespace android {
-
-class RadioHalLegacy : public RadioInterface
-{
-public:
-        RadioHalLegacy(radio_class_t classId);
-
-        // RadioInterface
-        virtual int getProperties(radio_hal_properties_t *properties);
-        virtual int openTuner(const radio_hal_band_config_t *config,
-                        bool audio,
-                        sp<TunerCallbackInterface> callback,
-                        sp<TunerInterface>& tuner);
-        virtual int closeTuner(sp<TunerInterface>& tuner);
-
-        // RefBase
-        virtual void onFirstRef();
-
-        class Tuner  : public TunerInterface
-        {
-        public:
-                        Tuner(sp<TunerCallbackInterface> callback);
-
-            virtual int setConfiguration(const radio_hal_band_config_t *config);
-            virtual int getConfiguration(radio_hal_band_config_t *config);
-            virtual int scan(radio_direction_t direction, bool skip_sub_channel);
-            virtual int step(radio_direction_t direction, bool skip_sub_channel);
-            virtual int tune(unsigned int channel, unsigned int sub_channel);
-            virtual int cancel();
-            virtual int getProgramInformation(radio_program_info_t *info);
-
-            static void callback(radio_hal_event_t *halEvent, void *cookie);
-                   void onCallback(radio_hal_event_t *halEvent);
-
-            void setHalTuner(const struct radio_tuner *halTuner) { mHalTuner = halTuner; }
-            const struct radio_tuner *getHalTuner() { return mHalTuner; }
-
-        private:
-            virtual      ~Tuner();
-
-            const struct radio_tuner    *mHalTuner;
-            sp<TunerCallbackInterface>  mCallback;
-        };
-
-protected:
-        virtual     ~RadioHalLegacy();
-
-private:
-        static const char * sClassModuleNames[];
-
-        radio_class_t mClassId;
-        struct radio_hw_device  *mHwDevice;
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_RADIO_HAL_LEGACY_H
diff --git a/services/radio/RadioInterface.h b/services/radio/RadioInterface.h
deleted file mode 100644
index fcfb4d5..0000000
--- a/services/radio/RadioInterface.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_INTERFACE_H
-#define ANDROID_HARDWARE_RADIO_INTERFACE_H
-
-#include <utils/RefBase.h>
-#include <system/radio.h>
-#include "TunerInterface.h"
-#include "TunerCallbackInterface.h"
-
-namespace android {
-
-class RadioInterface : public virtual RefBase
-{
-public:
-        /* get a sound trigger HAL instance */
-        static sp<RadioInterface> connectModule(radio_class_t classId);
-
-        /*
-         * Retrieve implementation properties.
-         *
-         * arguments:
-         * - properties: where to return the module properties
-         *
-         * returns:
-         *  0 if no error
-         *  -EINVAL if invalid arguments are passed
-         */
-        virtual int getProperties(radio_hal_properties_t *properties) = 0;
-
-        /*
-         * Open a tuner interface for the requested configuration.
-         * If no other tuner is opened, this will activate the radio module.
-         *
-         * arguments:
-         * - config: the band configuration to apply
-         * - audio: this tuner will be used for live radio listening and should be connected to
-         * the radio audio source.
-         * - callback: the event callback
-         * - cookie: the cookie to pass when calling the callback
-         * - tuner: where to return the tuner interface
-         *
-         * returns:
-         *  0 if HW was powered up and configuration could be applied
-         *  -EINVAL if configuration requested is invalid
-         *  -ENOSYS if called out of sequence
-         *
-         * Callback function with event RADIO_EVENT_CONFIG MUST be called once the
-         * configuration is applied or a failure occurs or after a time out.
-         */
-        virtual int openTuner(const radio_hal_band_config_t *config,
-                        bool audio,
-                        sp<TunerCallbackInterface> callback,
-                        sp<TunerInterface>& tuner) = 0;
-
-        /*
-         * Close a tuner interface.
-         * If the last tuner is closed, the radio module is deactivated.
-         *
-         * arguments:
-         * - tuner: the tuner interface to close
-         *
-         * returns:
-         *  0 if powered down successfully.
-         *  -EINVAL if an invalid argument is passed
-         *  -ENOSYS if called out of sequence
-         */
-        virtual int closeTuner(sp<TunerInterface>& tuner) = 0;
-
-protected:
-        RadioInterface() {}
-        virtual     ~RadioInterface() {}
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_RADIO_INTERFACE_H
diff --git a/services/radio/RadioRegions.h b/services/radio/RadioRegions.h
deleted file mode 100644
index d40ee83..0000000
--- a/services/radio/RadioRegions.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_REGIONS_H
-#define ANDROID_HARDWARE_RADIO_REGIONS_H
-
-namespace android {
-
-#define RADIO_BAND_LOWER_FM_ITU1    87500
-#define RADIO_BAND_UPPER_FM_ITU1    108000
-#define RADIO_BAND_SPACING_FM_ITU1  100
-
-#define RADIO_BAND_LOWER_FM_ITU2    87900
-#define RADIO_BAND_UPPER_FM_ITU2    107900
-#define RADIO_BAND_SPACING_FM_ITU2  200
-
-#define RADIO_BAND_LOWER_FM_JAPAN    76000
-#define RADIO_BAND_UPPER_FM_JAPAN    90000
-#define RADIO_BAND_SPACING_FM_JAPAN  100
-
-#define RADIO_BAND_LOWER_FM_OIRT    65800
-#define RADIO_BAND_UPPER_FM_OIRT    74000
-#define RADIO_BAND_SPACING_FM_OIRT  10
-
-#define RADIO_BAND_LOWER_LW         153
-#define RADIO_BAND_UPPER_LW         279
-#define RADIO_BAND_SPACING_LW       9
-
-#define RADIO_BAND_LOWER_MW_IUT1    531
-#define RADIO_BAND_UPPER_MW_ITU1    1611
-#define RADIO_BAND_SPACING_MW_ITU1  9
-
-#define RADIO_BAND_LOWER_MW_IUT2    540
-#define RADIO_BAND_UPPER_MW_ITU2    1610
-#define RADIO_BAND_SPACING_MW_ITU2  10
-
-#define RADIO_BAND_LOWER_SW         2300
-#define RADIO_BAND_UPPER_SW         26100
-#define RADIO_BAND_SPACING_SW       5
-
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-#endif
-
-const radio_band_config_t sKnownRegionConfigs[] = {
-    {   // FM ITU 1
-        RADIO_REGION_ITU_1,
-        {
-        RADIO_BAND_FM,
-            false,
-            RADIO_BAND_LOWER_FM_ITU1,
-            RADIO_BAND_UPPER_FM_ITU1,
-            1,
-            {RADIO_BAND_SPACING_FM_ITU1},
-            {
-                {
-                RADIO_DEEMPHASIS_50,
-                true,
-                RADIO_RDS_WORLD,
-                true,
-                true,
-                true,
-                }
-            }
-        }
-    },
-    {   // FM Americas
-        RADIO_REGION_ITU_2,
-        {
-        RADIO_BAND_FM,
-            false,
-            RADIO_BAND_LOWER_FM_ITU2,
-            RADIO_BAND_UPPER_FM_ITU2,
-            1,
-            {RADIO_BAND_SPACING_FM_ITU2},
-            {
-                {
-                RADIO_DEEMPHASIS_75,
-                true,
-                RADIO_RDS_US,
-                true,
-                true,
-                true,
-                }
-            }
-        }
-    },
-    {   // FM Japan
-        RADIO_REGION_JAPAN,
-        {
-        RADIO_BAND_FM,
-            false,
-            RADIO_BAND_LOWER_FM_JAPAN,
-            RADIO_BAND_UPPER_FM_JAPAN,
-            1,
-            {RADIO_BAND_SPACING_FM_JAPAN},
-            {
-                {
-                RADIO_DEEMPHASIS_50,
-                true,
-                RADIO_RDS_WORLD,
-                true,
-                true,
-                true,
-                }
-            }
-        }
-    },
-    {   // FM Korea
-        RADIO_REGION_KOREA,
-        {
-        RADIO_BAND_FM,
-            false,
-            RADIO_BAND_LOWER_FM_ITU1,
-            RADIO_BAND_UPPER_FM_ITU1,
-            1,
-            {RADIO_BAND_SPACING_FM_ITU1},
-            {
-                {
-                RADIO_DEEMPHASIS_75,
-                true,
-                RADIO_RDS_WORLD,
-                true,
-                true,
-                true,
-                }
-            }
-        }
-    },
-    {   // FM OIRT
-        RADIO_REGION_OIRT,
-        {
-        RADIO_BAND_FM,
-            false,
-            RADIO_BAND_LOWER_FM_OIRT,
-            RADIO_BAND_UPPER_FM_OIRT,
-            1,
-            {RADIO_BAND_SPACING_FM_OIRT},
-            {
-                {
-                RADIO_DEEMPHASIS_50,
-                true,
-                RADIO_RDS_WORLD,
-                true,
-                true,
-                true,
-                }
-            }
-        }
-    },
-    {   // FM US HD radio
-        RADIO_REGION_ITU_2,
-        {
-            RADIO_BAND_FM_HD,
-            false,
-            RADIO_BAND_LOWER_FM_ITU2,
-            RADIO_BAND_UPPER_FM_ITU2,
-            1,
-            {RADIO_BAND_SPACING_FM_ITU2},
-            {
-                {
-                RADIO_DEEMPHASIS_75,
-                true,
-                RADIO_RDS_US,
-                true,
-                true,
-                true,
-                }
-            }
-        }
-    },
-    {   // AM LW
-        RADIO_REGION_ITU_1,
-        {
-            RADIO_BAND_AM,
-            false,
-            RADIO_BAND_LOWER_LW,
-            RADIO_BAND_UPPER_LW,
-            1,
-            {RADIO_BAND_SPACING_LW},
-            {
-            }
-        }
-    },
-    {   // AM SW
-        RADIO_REGION_ITU_1,
-        {
-            RADIO_BAND_AM,
-            false,
-            RADIO_BAND_LOWER_SW,
-            RADIO_BAND_UPPER_SW,
-            1,
-            {RADIO_BAND_SPACING_SW},
-            {
-            }
-        }
-    },
-    {   // AM MW ITU1
-        RADIO_REGION_ITU_1,
-        {
-            RADIO_BAND_AM,
-            false,
-            RADIO_BAND_LOWER_MW_IUT1,
-            RADIO_BAND_UPPER_MW_ITU1,
-            1,
-            {RADIO_BAND_SPACING_MW_ITU1},
-            {
-            }
-        }
-    },
-    {   // AM MW ITU2
-        RADIO_REGION_ITU_2,
-        {
-            RADIO_BAND_AM,
-            false,
-            RADIO_BAND_LOWER_MW_IUT2,
-            RADIO_BAND_UPPER_MW_ITU2,
-            1,
-            {RADIO_BAND_SPACING_MW_ITU2},
-            {
-            }
-        }
-    }
-};
-
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_RADIO_REGIONS_H
diff --git a/services/radio/RadioService.cpp b/services/radio/RadioService.cpp
deleted file mode 100644
index beb7c09..0000000
--- a/services/radio/RadioService.cpp
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "RadioService"
-//#define LOG_NDEBUG 0
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <pthread.h>
-
-#include <system/audio.h>
-#include <system/audio_policy.h>
-#include <system/radio.h>
-#include <system/radio_metadata.h>
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-#include <hardware/hardware.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <binder/IServiceManager.h>
-#include <binder/MemoryBase.h>
-#include <binder/MemoryHeapBase.h>
-#include <binder/PermissionCache.h>
-#include <hardware/radio.h>
-#include <media/AudioSystem.h>
-#include "RadioService.h"
-#include "RadioRegions.h"
-
-namespace android {
-
-static const char kRadioTunerAudioDeviceName[] = "Radio tuner source";
-
-static const String16 RADIO_PERMISSION("android.permission.ACCESS_FM_RADIO");
-
-RadioService::RadioService()
-    : BnRadioService(), mNextUniqueId(1)
-{
-    ALOGI("%s", __FUNCTION__);
-}
-
-void RadioService::onFirstRef()
-{
-    ALOGI("%s", __FUNCTION__);
-
-    sp<RadioInterface> dev = RadioInterface::connectModule(RADIO_CLASS_AM_FM);
-
-    if (dev == 0) {
-        return;
-    }
-    struct radio_hal_properties halProperties;
-    int rc = dev->getProperties(&halProperties);
-    if (rc != 0) {
-        ALOGE("could not read implementation properties");
-        return;
-    }
-
-    radio_properties_t properties;
-    properties.handle =
-            (radio_handle_t)android_atomic_inc(&mNextUniqueId);
-    convertProperties(&properties, &halProperties);
-
-    ALOGI("loaded default module %s, ver %s, handle %d", properties.product,
-        properties.version, properties.handle);
-
-    sp<Module> module = new Module(dev, properties);
-    mModules.add(properties.handle, module);
-}
-
-RadioService::~RadioService()
-{
-}
-
-status_t RadioService::listModules(struct radio_properties *properties,
-                             uint32_t *numModules)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    ALOGV("listModules");
-
-    AutoMutex lock(mServiceLock);
-    if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
-        return BAD_VALUE;
-    }
-    uint32_t maxModules = *numModules;
-    *numModules = mModules.size();
-    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
-        properties[i] = mModules.valueAt(i)->properties();
-    }
-    return NO_ERROR;
-}
-
-status_t RadioService::attach(radio_handle_t handle,
-                        const sp<IRadioClient>& client,
-                        const struct radio_band_config *config,
-                        bool withAudio,
-                        sp<IRadio>& radio)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);
-
-    AutoMutex lock(mServiceLock);
-    radio.clear();
-    if (client == 0) {
-        return BAD_VALUE;
-    }
-    ssize_t index = mModules.indexOfKey(handle);
-    if (index < 0) {
-        return BAD_VALUE;
-    }
-    sp<Module> module = mModules.valueAt(index);
-
-    if (config == NULL) {
-        config = module->getDefaultConfig();
-        if (config == NULL) {
-            return INVALID_OPERATION;
-        }
-    }
-    ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);
-
-    radio = module->addClient(client, config, withAudio);
-
-    if (radio == 0) {
-        return NO_INIT;
-    }
-    return NO_ERROR;
-}
-
-
-static const int kDumpLockRetries = 50;
-static const int kDumpLockSleep = 60000;
-
-static bool tryLock(Mutex& mutex)
-{
-    bool locked = false;
-    for (int i = 0; i < kDumpLockRetries; ++i) {
-        if (mutex.tryLock() == NO_ERROR) {
-            locked = true;
-            break;
-        }
-        usleep(kDumpLockSleep);
-    }
-    return locked;
-}
-
-status_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
-    String8 result;
-    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
-        result.appendFormat("Permission Denial: can't dump RadioService");
-        write(fd, result.string(), result.size());
-    } else {
-        bool locked = tryLock(mServiceLock);
-        // failed to lock - RadioService is probably deadlocked
-        if (!locked) {
-            result.append("RadioService may be deadlocked\n");
-            write(fd, result.string(), result.size());
-        }
-
-        if (locked) mServiceLock.unlock();
-    }
-    return NO_ERROR;
-}
-
-status_t RadioService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
-    return BnRadioService::onTransact(code, data, reply, flags);
-}
-
-
-/* static */
-void RadioService::convertProperties(radio_properties_t *properties,
-                                     const radio_hal_properties_t *halProperties)
-{
-    memset(properties, 0, sizeof(struct radio_properties));
-    properties->class_id = halProperties->class_id;
-    strlcpy(properties->implementor, halProperties->implementor,
-            RADIO_STRING_LEN_MAX);
-    strlcpy(properties->product, halProperties->product,
-            RADIO_STRING_LEN_MAX);
-    strlcpy(properties->version, halProperties->version,
-            RADIO_STRING_LEN_MAX);
-    strlcpy(properties->serial, halProperties->serial,
-            RADIO_STRING_LEN_MAX);
-    properties->num_tuners = halProperties->num_tuners;
-    properties->num_audio_sources = halProperties->num_audio_sources;
-    properties->supports_capture = halProperties->supports_capture;
-
-    for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
-        const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
-        size_t j;
-        for (j = 0; j < halProperties->num_bands; j++) {
-            const radio_hal_band_config_t *halBand = &halProperties->bands[j];
-            size_t k;
-            if (band->type != halBand->type) continue;
-            if (band->lower_limit < halBand->lower_limit) continue;
-            if (band->upper_limit > halBand->upper_limit) continue;
-            for (k = 0; k < halBand->num_spacings; k++) {
-                if (band->spacings[0] == halBand->spacings[k]) break;
-            }
-            if (k == halBand->num_spacings) continue;
-            if (band->type == RADIO_BAND_AM) break;
-            if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
-            if (halBand->fm.rds == 0) break;
-            if ((band->fm.rds & halBand->fm.rds) != 0) break;
-        }
-        if (j == halProperties->num_bands) continue;
-
-        ALOGI("convertProperties() Adding band type %d region %d",
-              sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);
-
-        memcpy(&properties->bands[properties->num_bands++],
-               &sKnownRegionConfigs[i],
-               sizeof(radio_band_config_t));
-    }
-}
-
-#undef LOG_TAG
-#define LOG_TAG "RadioService::CallbackThread"
-
-RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
-    : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
-{
-}
-
-RadioService::CallbackThread::~CallbackThread()
-{
-    mEventQueue.clear();
-}
-
-void RadioService::CallbackThread::onFirstRef()
-{
-    run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
-}
-
-bool RadioService::CallbackThread::threadLoop()
-{
-    while (!exitPending()) {
-        sp<IMemory> eventMemory;
-        sp<ModuleClient> moduleClient;
-        {
-            Mutex::Autolock _l(mCallbackLock);
-            while (mEventQueue.isEmpty() && !exitPending()) {
-                ALOGV("CallbackThread::threadLoop() sleep");
-                mCallbackCond.wait(mCallbackLock);
-                ALOGV("CallbackThread::threadLoop() wake up");
-            }
-            if (exitPending()) {
-                break;
-            }
-            eventMemory = mEventQueue[0];
-            mEventQueue.removeAt(0);
-            moduleClient = mModuleClient.promote();
-        }
-        if (moduleClient != 0) {
-            moduleClient->onCallbackEvent(eventMemory);
-            eventMemory.clear();
-        }
-    }
-    return false;
-}
-
-void RadioService::CallbackThread::exit()
-{
-    Mutex::Autolock _l(mCallbackLock);
-    requestExit();
-    mCallbackCond.broadcast();
-}
-
-sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
-{
-    sp<IMemory> eventMemory;
-
-    // The event layout in shared memory is:
-    // sizeof(struct radio_event) bytes : the event itself
-    // 4 bytes                          : metadata size or 0
-    // N bytes                          : metadata if present
-    uint32_t metadataOffset = sizeof(struct radio_event) + sizeof(uint32_t);
-    uint32_t metadataSize = 0;
-
-    switch (halEvent->type) {
-    case RADIO_EVENT_TUNED:
-    case RADIO_EVENT_AF_SWITCH:
-        if (radio_metadata_check(halEvent->info.metadata) == 0) {
-            metadataSize = (uint32_t)radio_metadata_get_size(halEvent->info.metadata);
-        }
-        break;
-    case RADIO_EVENT_METADATA:
-        if (radio_metadata_check(halEvent->metadata) != 0) {
-            return eventMemory;
-        }
-        metadataSize = (uint32_t)radio_metadata_get_size(halEvent->metadata);
-        break;
-    default:
-        break;
-    }
-
-    eventMemory = mMemoryDealer->allocate(metadataOffset + metadataSize);
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        eventMemory.clear();
-        return eventMemory;
-    }
-
-    struct radio_event *event = (struct radio_event *)eventMemory->pointer();
-
-    *(uint32_t *)((uint8_t *)event + metadataOffset - sizeof(uint32_t)) = metadataSize;
-
-    event->type = halEvent->type;
-    event->status = halEvent->status;
-
-    switch (event->type) {
-    case RADIO_EVENT_CONFIG:
-        event->config.band = halEvent->config;
-        break;
-    case RADIO_EVENT_TUNED:
-    case RADIO_EVENT_AF_SWITCH:
-        event->info = halEvent->info;
-        if (metadataSize != 0) {
-            memcpy((uint8_t *)event + metadataOffset, halEvent->info.metadata, metadataSize);
-        }
-        break;
-    case RADIO_EVENT_TA:
-    case RADIO_EVENT_EA:
-    case RADIO_EVENT_ANTENNA:
-    case RADIO_EVENT_CONTROL:
-        event->on = halEvent->on;
-        break;
-    case RADIO_EVENT_METADATA:
-        if (metadataSize != 0) {
-            memcpy((uint8_t *)event + metadataOffset, halEvent->metadata, metadataSize);
-        }
-        break;
-    case RADIO_EVENT_HW_FAILURE:
-    default:
-        break;
-    }
-
-    return eventMemory;
-}
-
-void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
- {
-     sp<IMemory> eventMemory = prepareEvent(event);
-     if (eventMemory == 0) {
-         return;
-     }
-
-     AutoMutex lock(mCallbackLock);
-     mEventQueue.add(eventMemory);
-     mCallbackCond.signal();
-     ALOGV("%s DONE", __FUNCTION__);
-}
-
-
-#undef LOG_TAG
-#define LOG_TAG "RadioService::Module"
-
-RadioService::Module::Module(sp<RadioInterface> hwDevice, radio_properties properties)
- : mHwDevice(hwDevice), mProperties(properties), mMute(true)
-{
-}
-
-RadioService::Module::~Module() {
-    mHwDevice.clear();
-    mModuleClients.clear();
-}
-
-status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
-    String8 result;
-    return NO_ERROR;
-}
-
-sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
-                                    const struct radio_band_config *config,
-                                    bool audio)
-{
-    ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
-
-    AutoMutex lock(mLock);
-    sp<ModuleClient> moduleClient;
-    int ret;
-
-    if (mHwDevice == 0) {
-        return moduleClient;
-    }
-
-    for (size_t i = 0; i < mModuleClients.size(); i++) {
-        if (mModuleClients[i]->client() == client) {
-            // client already connected: reject
-            return moduleClient;
-        }
-    }
-    moduleClient = new ModuleClient(this, client, config, audio);
-
-    struct radio_hal_band_config halConfig;
-    halConfig = config->band;
-
-    // Tuner preemption logic:
-    // There is a limited amount of tuners and a limited amount of radio audio sources per module.
-    // The minimum is one tuner and one audio source.
-    // The numbers of tuners and sources are indicated in the module properties.
-    // NOTE: current framework implementation only supports one radio audio source.
-    // It is possible to open more than one tuner at a time but only one tuner can be connected
-    // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
-    // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
-    // and can use the audio source if requested.
-    // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
-    // indicating loss of control.
-    // - If the newly connected client requests the audio source (audio == true):
-    //    - if an audio source is available
-    //          no problem
-    //    - if not:
-    //          the oldest client in the list using audio is preempted.
-    // - If the newly connected client does not request the audio source (audio == false):
-    //    - if a tuner is available
-    //          no problem
-    //    - if not:
-    //          The oldest client not using audio is preempted first and if none is found the
-    //          the oldest client using audio is preempted.
-    // Each time a tuner using the audio source is opened or closed, the audio policy manager is
-    // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
-
-    sp<ModuleClient> oldestTuner;
-    sp<ModuleClient> oldestAudio;
-    size_t allocatedTuners = 0;
-    size_t allocatedAudio = 0;
-    for (size_t i = 0; i < mModuleClients.size(); i++) {
-        if (mModuleClients[i]->getTuner() != NULL) {
-            if (mModuleClients[i]->audio()) {
-                if (oldestAudio == 0) {
-                    oldestAudio = mModuleClients[i];
-                }
-                allocatedAudio++;
-            } else {
-                if (oldestTuner == 0) {
-                    oldestTuner = mModuleClients[i];
-                }
-                allocatedTuners++;
-            }
-        }
-    }
-
-    sp<TunerInterface> halTuner;
-    sp<ModuleClient> preemtedClient;
-    if (audio) {
-        if (allocatedAudio >= mProperties.num_audio_sources) {
-            ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
-            preemtedClient = oldestAudio;
-        }
-    } else {
-        if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
-            if (allocatedTuners != 0) {
-                ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
-                preemtedClient = oldestTuner;
-            } else {
-                ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
-                preemtedClient = oldestAudio;
-            }
-        }
-    }
-    if (preemtedClient != 0) {
-        halTuner = preemtedClient->getTuner();
-        sp<TunerInterface> clear;
-        preemtedClient->setTuner(clear);
-        mHwDevice->closeTuner(halTuner);
-        if (preemtedClient->audio()) {
-            notifyDeviceConnection(false, "");
-        }
-    }
-
-    ret = mHwDevice->openTuner(&halConfig, audio,
-                               moduleClient,
-                               halTuner);
-    if (ret == 0) {
-        ALOGV("addClient() setTuner %p", halTuner.get());
-        moduleClient->setTuner(halTuner);
-        mModuleClients.add(moduleClient);
-        if (audio) {
-            notifyDeviceConnection(true, "");
-        }
-        ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
-    } else {
-        ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
-        moduleClient.clear();
-    }
-
-    return moduleClient;
-}
-
-void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
-    ALOGV("removeClient()");
-    AutoMutex lock(mLock);
-    int ret;
-    ssize_t index = -1;
-
-    for (size_t i = 0; i < mModuleClients.size(); i++) {
-        if (mModuleClients[i] == moduleClient) {
-            index = i;
-            break;
-        }
-    }
-    if (index == -1) {
-        return;
-    }
-
-    mModuleClients.removeAt(index);
-    sp<TunerInterface> halTuner = moduleClient->getTuner();
-    if (halTuner == NULL) {
-        return;
-    }
-
-    if (mHwDevice != 0) {
-        mHwDevice->closeTuner(halTuner);
-    }
-
-    if (moduleClient->audio()) {
-        notifyDeviceConnection(false, "");
-    }
-
-    mMute = true;
-
-    if (mModuleClients.isEmpty()) {
-        return;
-    }
-
-    if (mHwDevice == 0) {
-        return;
-    }
-
-    // Tuner reallocation logic:
-    // When a client is removed and was controlling a tuner, this tuner will be allocated to a
-    // previously preempted client. This client will be notified by a callback with
-    // RADIO_EVENT_CONTROL indicating gain of control.
-    // - If a preempted client is waiting for an audio source and one becomes available:
-    //    Allocate the tuner to the most recently added client waiting for an audio source
-    // - If not:
-    //    Allocate the tuner to the most recently added client.
-    // Each time a tuner using the audio source is opened or closed, the audio policy manager is
-    // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
-
-    sp<ModuleClient> youngestClient;
-    sp<ModuleClient> youngestClientAudio;
-    size_t allocatedTuners = 0;
-    size_t allocatedAudio = 0;
-    for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
-        if (mModuleClients[i]->getTuner() == NULL) {
-            if (mModuleClients[i]->audio()) {
-                if (youngestClientAudio == 0) {
-                    youngestClientAudio = mModuleClients[i];
-                }
-            } else {
-                if (youngestClient == 0) {
-                    youngestClient = mModuleClients[i];
-                }
-            }
-        } else {
-            if (mModuleClients[i]->audio()) {
-                allocatedAudio++;
-            } else {
-                allocatedTuners++;
-            }
-        }
-    }
-
-    ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
-                "removeClient() removed client but no tuner available");
-
-    ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
-                "removeClient() removed audio client but no tuner with audio available");
-
-    if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
-        youngestClient = youngestClientAudio;
-    }
-
-    ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
-
-    struct radio_hal_band_config halConfig = youngestClient->halConfig();
-    ret = mHwDevice->openTuner(&halConfig, youngestClient->audio(),
-                                moduleClient,
-                                halTuner);
-
-    if (ret == 0) {
-        youngestClient->setTuner(halTuner);
-        if (youngestClient->audio()) {
-            notifyDeviceConnection(true, "");
-        }
-    }
-}
-
-status_t RadioService::Module::setMute(bool mute)
-{
-    Mutex::Autolock _l(mLock);
-    if (mute != mMute) {
-        mMute = mute;
-        //TODO notifify audio policy manager of media activity on radio audio device
-    }
-    return NO_ERROR;
-}
-
-status_t RadioService::Module::getMute(bool *mute)
-{
-    Mutex::Autolock _l(mLock);
-    *mute = mMute;
-    return NO_ERROR;
-}
-
-
-const struct radio_band_config *RadioService::Module::getDefaultConfig() const
-{
-    if (mProperties.num_bands == 0) {
-        return NULL;
-    }
-    return &mProperties.bands[0];
-}
-
-void RadioService::Module::notifyDeviceConnection(bool connected,
-                                                  const char *address) {
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
-    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
-                                          connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
-                                                  AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                          address, kRadioTunerAudioDeviceName);
-    IPCThreadState::self()->restoreCallingIdentity(token);
-}
-
-#undef LOG_TAG
-#define LOG_TAG "RadioService::ModuleClient"
-
-RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
-                                         const sp<IRadioClient>& client,
-                                         const struct radio_band_config *config,
-                                         bool audio)
- : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(0)
-{
-}
-
-void RadioService::ModuleClient::onFirstRef()
-{
-    mCallbackThread = new CallbackThread(this);
-    IInterface::asBinder(mClient)->linkToDeath(this);
-}
-
-RadioService::ModuleClient::~ModuleClient() {
-    if (mClient != 0) {
-        IInterface::asBinder(mClient)->unlinkToDeath(this);
-        mClient.clear();
-    }
-    if (mCallbackThread != 0) {
-        mCallbackThread->exit();
-    }
-}
-
-void RadioService::ModuleClient::onEvent(radio_hal_event_t *halEvent)
-{
-    mCallbackThread->sendEvent(halEvent);
-}
-
-status_t RadioService::ModuleClient::dump(int fd __unused,
-                                             const Vector<String16>& args __unused) {
-    String8 result;
-    return NO_ERROR;
-}
-
-void RadioService::ModuleClient::detach() {
-    ALOGV("%s", __FUNCTION__);
-    sp<ModuleClient> strongMe = this;
-    {
-        AutoMutex lock(mLock);
-        if (mClient != 0) {
-            IInterface::asBinder(mClient)->unlinkToDeath(this);
-            mClient.clear();
-        }
-    }
-    sp<Module> module = mModule.promote();
-    if (module == 0) {
-        return;
-    }
-    module->removeClient(this);
-}
-
-radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
-{
-    AutoMutex lock(mLock);
-    ALOGV("%s locked", __FUNCTION__);
-    return mConfig.band;
-}
-
-sp<TunerInterface>& RadioService::ModuleClient::getTuner()
-{
-    AutoMutex lock(mLock);
-    ALOGV("%s locked", __FUNCTION__);
-    return mTuner;
-}
-
-void RadioService::ModuleClient::setTuner(sp<TunerInterface>& tuner)
-{
-    ALOGV("%s %p", __FUNCTION__, this);
-
-    AutoMutex lock(mLock);
-    mTuner = tuner;
-    ALOGV("%s locked", __FUNCTION__);
-
-    radio_hal_event_t event;
-    event.type = RADIO_EVENT_CONTROL;
-    event.status = 0;
-    event.on = mTuner != 0;
-    mCallbackThread->sendEvent(&event);
-    ALOGV("%s DONE", __FUNCTION__);
-
-}
-
-status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    AutoMutex lock(mLock);
-    status_t status = NO_ERROR;
-    ALOGV("%s locked", __FUNCTION__);
-
-    if (mTuner != 0) {
-        struct radio_hal_band_config halConfig;
-        halConfig = config->band;
-        status = (status_t)mTuner->setConfiguration(&halConfig);
-        if (status == NO_ERROR) {
-            mConfig = *config;
-        }
-    } else {
-        mConfig = *config;
-        status = INVALID_OPERATION;
-    }
-
-    return status;
-}
-
-status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    AutoMutex lock(mLock);
-    status_t status = NO_ERROR;
-    ALOGV("%s locked", __FUNCTION__);
-
-    if (mTuner != 0) {
-        struct radio_hal_band_config halConfig;
-        status = (status_t)mTuner->getConfiguration(&halConfig);
-        if (status == NO_ERROR) {
-            mConfig.band = halConfig;
-        }
-    }
-    *config = mConfig;
-
-    return status;
-}
-
-status_t RadioService::ModuleClient::setMute(bool mute)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    sp<Module> module;
-    {
-        Mutex::Autolock _l(mLock);
-        ALOGV("%s locked", __FUNCTION__);
-        if (mTuner == 0 || !mAudio) {
-            return INVALID_OPERATION;
-        }
-        module = mModule.promote();
-        if (module == 0) {
-            return NO_INIT;
-        }
-    }
-    module->setMute(mute);
-    return NO_ERROR;
-}
-
-status_t RadioService::ModuleClient::getMute(bool *mute)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    sp<Module> module;
-    {
-        Mutex::Autolock _l(mLock);
-        ALOGV("%s locked", __FUNCTION__);
-        module = mModule.promote();
-        if (module == 0) {
-            return NO_INIT;
-        }
-    }
-    return module->getMute(mute);
-}
-
-status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    AutoMutex lock(mLock);
-    ALOGV("%s locked", __FUNCTION__);
-    status_t status;
-    if (mTuner != 0) {
-        status = (status_t)mTuner->scan(direction, skipSubChannel);
-    } else {
-        status = INVALID_OPERATION;
-    }
-    return status;
-}
-
-status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    AutoMutex lock(mLock);
-    ALOGV("%s locked", __FUNCTION__);
-    status_t status;
-    if (mTuner != 0) {
-        status = (status_t)mTuner->step(direction, skipSubChannel);
-    } else {
-        status = INVALID_OPERATION;
-    }
-    return status;
-}
-
-status_t RadioService::ModuleClient::tune(uint32_t channel, uint32_t subChannel)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    AutoMutex lock(mLock);
-    ALOGV("%s locked", __FUNCTION__);
-    status_t status;
-    if (mTuner != 0) {
-        status = (status_t)mTuner->tune(channel, subChannel);
-    } else {
-        status = INVALID_OPERATION;
-    }
-    return status;
-}
-
-status_t RadioService::ModuleClient::cancel()
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    AutoMutex lock(mLock);
-    ALOGV("%s locked", __FUNCTION__);
-    status_t status;
-    if (mTuner != 0) {
-        status = (status_t)mTuner->cancel();
-    } else {
-        status = INVALID_OPERATION;
-    }
-    return status;
-}
-
-status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    AutoMutex lock(mLock);
-    ALOGV("%s locked", __FUNCTION__);
-    status_t status;
-    if (mTuner != NULL) {
-        status = (status_t)mTuner->getProgramInformation(info);
-    } else {
-        status = INVALID_OPERATION;
-    }
-
-    return status;
-}
-
-status_t RadioService::ModuleClient::hasControl(bool *hasControl)
-{
-    if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
-        return PERMISSION_DENIED;
-    }
-    Mutex::Autolock lock(mLock);
-    ALOGV("%s locked", __FUNCTION__);
-    *hasControl = mTuner != 0;
-    return NO_ERROR;
-}
-
-void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
-{
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        return;
-    }
-
-    sp<IRadioClient> client;
-    {
-        AutoMutex lock(mLock);
-        ALOGV("%s locked", __FUNCTION__);
-        radio_event_t *event = (radio_event_t *)eventMemory->pointer();
-        switch (event->type) {
-        case RADIO_EVENT_CONFIG:
-            mConfig.band = event->config.band;
-            event->config.region = mConfig.region;
-            break;
-        default:
-            break;
-        }
-
-        client = mClient;
-    }
-    if (client != 0) {
-        client->onEvent(eventMemory);
-    }
-}
-
-
-void RadioService::ModuleClient::binderDied(
-    const wp<IBinder> &who __unused) {
-    ALOGW("client binder died for client %p", this);
-    detach();
-}
-
-}; // namespace android
diff --git a/services/radio/RadioService.h b/services/radio/RadioService.h
deleted file mode 100644
index 444eb7a..0000000
--- a/services/radio/RadioService.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_SERVICE_H
-#define ANDROID_HARDWARE_RADIO_SERVICE_H
-
-#include <utils/Vector.h>
-//#include <binder/AppOpsManager.h>
-#include <binder/MemoryDealer.h>
-#include <binder/BinderService.h>
-#include <binder/IAppOpsCallback.h>
-#include <radio/IRadioService.h>
-#include <radio/IRadio.h>
-#include <radio/IRadioClient.h>
-#include <system/radio.h>
-#include <hardware/radio.h>
-#include "RadioInterface.h"
-#include "TunerInterface.h"
-#include "TunerCallbackInterface.h"
-
-namespace android {
-
-class MemoryHeapBase;
-
-class RadioService :
-    public BinderService<RadioService>,
-    public BnRadioService
-{
-    friend class BinderService<RadioService>;
-
-public:
-    class ModuleClient;
-    class Module;
-
-    static char const* getServiceName() { return "media.radio"; }
-
-                        RadioService();
-    virtual             ~RadioService();
-
-    // IRadioService
-    virtual status_t listModules(struct radio_properties *properties,
-                                 uint32_t *numModules);
-
-    virtual status_t attach(radio_handle_t handle,
-                            const sp<IRadioClient>& client,
-                            const struct radio_band_config *config,
-                            bool withAudio,
-                            sp<IRadio>& radio);
-
-    virtual status_t    onTransact(uint32_t code, const Parcel& data,
-                                   Parcel* reply, uint32_t flags);
-
-    virtual status_t    dump(int fd, const Vector<String16>& args);
-
-
-    class Module : public virtual RefBase {
-    public:
-
-       Module(sp<RadioInterface> hwDevice,
-              struct radio_properties properties);
-
-       virtual ~Module();
-
-               sp<ModuleClient> addClient(const sp<IRadioClient>& client,
-                                  const struct radio_band_config *config,
-                                  bool audio);
-
-               void removeClient(const sp<ModuleClient>& moduleClient);
-
-               status_t setMute(bool mute);
-
-               status_t getMute(bool *mute);
-
-       virtual status_t dump(int fd, const Vector<String16>& args);
-
-       sp<RadioInterface> hwDevice() const { return mHwDevice; }
-       const struct radio_properties properties() const { return mProperties; }
-       const struct radio_band_config *getDefaultConfig() const ;
-
-    private:
-
-       void notifyDeviceConnection(bool connected, const char *address);
-
-        Mutex                         mLock;          // protects  mModuleClients
-        sp<RadioInterface>            mHwDevice;      // HAL hardware device
-        const struct radio_properties mProperties;    // cached hardware module properties
-        Vector< sp<ModuleClient> >    mModuleClients; // list of attached clients
-        bool                          mMute;          // radio audio source state
-                                                      // when unmuted, audio is routed to the
-                                                      // output device selected for media use case.
-    }; // class Module
-
-    class CallbackThread : public Thread {
-    public:
-
-        explicit CallbackThread(const wp<ModuleClient>& moduleClient);
-
-        virtual ~CallbackThread();
-
-
-        // Thread virtuals
-        virtual bool threadLoop();
-
-        // RefBase
-        virtual void onFirstRef();
-
-                void exit();
-
-                void sendEvent(radio_hal_event_t *halEvent);
-                sp<IMemory> prepareEvent(radio_hal_event_t *halEvent);
-
-    private:
-        wp<ModuleClient>      mModuleClient;    // client module the thread belongs to
-        Condition             mCallbackCond;    // condition signaled when a new event is posted
-        Mutex                 mCallbackLock;    // protects mEventQueue
-        Vector< sp<IMemory> > mEventQueue;      // pending callback events
-        sp<MemoryDealer>      mMemoryDealer;    // shared memory for callback event
-    }; // class CallbackThread
-
-    class ModuleClient : public BnRadio,
-                   public IBinder::DeathRecipient,
-                   public TunerCallbackInterface {
-    public:
-
-       ModuleClient(const sp<Module>& module,
-              const sp<IRadioClient>& client,
-              const struct radio_band_config *config,
-              bool audio);
-
-       virtual ~ModuleClient();
-
-       // IRadio
-       virtual void detach();
-
-       virtual status_t setConfiguration(const struct radio_band_config *config);
-
-       virtual status_t getConfiguration(struct radio_band_config *config);
-
-       virtual status_t setMute(bool mute);
-
-       virtual status_t getMute(bool *mute);
-
-       virtual status_t scan(radio_direction_t direction, bool skipSubChannel);
-
-       virtual status_t step(radio_direction_t direction, bool skipSubChannel);
-
-       virtual status_t tune(unsigned int channel, unsigned int subChannel);
-
-       virtual status_t cancel();
-
-       virtual status_t getProgramInformation(struct radio_program_info *info);
-
-       virtual status_t hasControl(bool *hasControl);
-
-       virtual status_t dump(int fd, const Vector<String16>& args);
-
-               sp<IRadioClient> client() const { return mClient; }
-               wp<Module> module() const { return mModule; }
-               radio_hal_band_config_t halConfig() const;
-               sp<CallbackThread> callbackThread() const { return mCallbackThread; }
-               void setTuner(sp<TunerInterface>& tuner);
-               sp<TunerInterface>& getTuner();
-               bool audio() const { return mAudio; }
-
-               void onCallbackEvent(const sp<IMemory>& event);
-
-       virtual void onFirstRef();
-
-
-       // IBinder::DeathRecipient implementation
-       virtual void        binderDied(const wp<IBinder> &who);
-
-       // TunerCallbackInterface
-       virtual void onEvent(radio_hal_event_t *event);
-
-    private:
-
-        mutable Mutex               mLock;           // protects mClient, mConfig and mTuner
-        wp<Module>                  mModule;         // The module this client is attached to
-        sp<IRadioClient>            mClient;         // event callback binder interface
-        radio_band_config_t         mConfig;         // current band configuration
-        sp<CallbackThread>          mCallbackThread; // event callback thread
-        const bool                  mAudio;
-        sp<TunerInterface>          mTuner;        // HAL tuner interface. NULL indicates that
-                                                    // this client does not have control on any
-                                                    // tuner
-    }; // class ModuleClient
-
-
-    static void callback(radio_hal_event_t *halEvent, void *cookie);
-
-private:
-
-    virtual void onFirstRef();
-
-    static void convertProperties(radio_properties_t *properties,
-                                  const radio_hal_properties_t *halProperties);
-    Mutex               mServiceLock;   // protects mModules
-    volatile int32_t    mNextUniqueId;  // for module ID allocation
-    DefaultKeyedVector< radio_handle_t, sp<Module> > mModules;
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_RADIO_SERVICE_H
diff --git a/services/radio/TunerCallbackInterface.h b/services/radio/TunerCallbackInterface.h
deleted file mode 100644
index 4973cce..0000000
--- a/services/radio/TunerCallbackInterface.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_TUNER_CALLBACK_INTERFACE_H
-#define ANDROID_HARDWARE_TUNER_CALLBACK_INTERFACE_H
-
-#include <utils/RefBase.h>
-#include <system/radio.h>
-
-namespace android {
-
-class TunerCallbackInterface : public virtual RefBase
-{
-public:
-    virtual void onEvent(radio_hal_event_t *event) = 0;
-
-protected:
-                 TunerCallbackInterface() {}
-    virtual      ~TunerCallbackInterface() {}
-
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_TUNER_CALLBACK_INTERFACE_H
diff --git a/services/radio/TunerInterface.h b/services/radio/TunerInterface.h
deleted file mode 100644
index 4e657d3..0000000
--- a/services/radio/TunerInterface.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_TUNER_INTERFACE_H
-#define ANDROID_HARDWARE_TUNER_INTERFACE_H
-
-#include <utils/RefBase.h>
-#include <system/radio.h>
-
-namespace android {
-
-class TunerInterface : public virtual RefBase
-{
-public:
-        /*
-         * Apply current radio band configuration (band, range, channel spacing ...).
-         *
-         * arguments:
-         * - config: the band configuration to apply
-         *
-         * returns:
-         *  0 if configuration could be applied
-         *  -EINVAL if configuration requested is invalid
-         *
-         * Automatically cancels pending scan, step or tune.
-         *
-         * Callback function with event RADIO_EVENT_CONFIG MUST be called once the
-         * configuration is applied or a failure occurs or after a time out.
-         */
-    virtual int setConfiguration(const radio_hal_band_config_t *config) = 0;
-
-        /*
-         * Retrieve current radio band configuration.
-         *
-         * arguments:
-         * - config: where to return the band configuration
-         *
-         * returns:
-         *  0 if valid configuration is returned
-         *  -EINVAL if invalid arguments are passed
-         */
-    virtual int getConfiguration(radio_hal_band_config_t *config) = 0;
-
-        /*
-         * Start scanning up to next valid station.
-         * Must be called when a valid configuration has been applied.
-         *
-         * arguments:
-         * - direction: RADIO_DIRECTION_UP or RADIO_DIRECTION_DOWN
-         * - skip_sub_channel: valid for HD radio or digital radios only: ignore sub channels
-         *  (e.g SPS for HD radio).
-         *
-         * returns:
-         *  0 if scan successfully started
-         *  -ENOSYS if called out of sequence
-         *  -ENODEV if another error occurs
-         *
-         * Automatically cancels pending scan, step or tune.
-         *
-         *  Callback function with event RADIO_EVENT_TUNED MUST be called once
-         *  locked on a station or after a time out or full frequency scan if
-         *  no station found. The event status should indicate if a valid station
-         *  is tuned or not.
-         */
-    virtual int scan(radio_direction_t direction, bool skip_sub_channel) = 0;
-
-        /*
-         * Move one channel spacing up or down.
-         * Must be called when a valid configuration has been applied.
-         *
-         * arguments:
-         * - direction: RADIO_DIRECTION_UP or RADIO_DIRECTION_DOWN
-         * - skip_sub_channel: valid for HD radio or digital radios only: ignore sub channels
-         *  (e.g SPS for HD radio).
-         *
-         * returns:
-         *  0 if step successfully started
-         *  -ENOSYS if called out of sequence
-         *  -ENODEV if another error occurs
-         *
-         * Automatically cancels pending scan, step or tune.
-         *
-         * Callback function with event RADIO_EVENT_TUNED MUST be called once
-         * step completed or after a time out. The event status should indicate
-         * if a valid station is tuned or not.
-         */
-    virtual int step(radio_direction_t direction, bool skip_sub_channel) = 0;
-
-        /*
-         * Tune to specified frequency.
-         * Must be called when a valid configuration has been applied.
-         *
-         * arguments:
-         * - channel: channel to tune to. A frequency in kHz for AM/FM/HD Radio bands.
-         * - sub_channel: valid for HD radio or digital radios only: (e.g SPS number for HD radio).
-         *
-         * returns:
-         *  0 if tune successfully started
-         *  -ENOSYS if called out of sequence
-         *  -EINVAL if invalid arguments are passed
-         *  -ENODEV if another error occurs
-         *
-         * Automatically cancels pending scan, step or tune.
-         *
-         * Callback function with event RADIO_EVENT_TUNED MUST be called once
-         * tuned or after a time out. The event status should indicate
-         * if a valid station is tuned or not.
-         */
-    virtual int tune(unsigned int channel, unsigned int sub_channel) = 0;
-
-        /*
-         * Cancel a scan, step or tune operation.
-         * Must be called while a scan, step or tune operation is pending
-         * (callback not yet sent).
-         *
-         * returns:
-         *  0 if successful
-         *  -ENOSYS if called out of sequence
-         *  -ENODEV if another error occurs
-         *
-         * The callback is not sent.
-         */
-    virtual int cancel() = 0;
-
-        /*
-         * Retrieve current station information.
-         *
-         * arguments:
-         * - info: where to return the program info.
-         * If info->metadata is NULL. no meta data should be returned.
-         * If meta data must be returned, they should be added to or cloned to
-         * info->metadata, not passed from a newly created meta data buffer.
-         *
-         * returns:
-         *  0 if tuned and information available
-         *  -EINVAL if invalid arguments are passed
-         *  -ENODEV if another error occurs
-         */
-    virtual int getProgramInformation(radio_program_info_t *info) = 0;
-
-protected:
-                TunerInterface() {}
-    virtual     ~TunerInterface() {}
-
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_TUNER_INTERFACE_H
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 5b8d990..22519a3 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -89,7 +89,8 @@
                              uint32_t *numModules)
 {
     ALOGV("listModules");
-    if (!captureHotwordAllowed()) {
+    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
         return PERMISSION_DENIED;
     }
 
@@ -110,7 +111,8 @@
                         sp<ISoundTrigger>& moduleInterface)
 {
     ALOGV("attach module %d", handle);
-    if (!captureHotwordAllowed()) {
+    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
         return PERMISSION_DENIED;
     }
 
@@ -528,37 +530,45 @@
 void SoundTriggerHwService::Module::detach(const sp<ModuleClient>& moduleClient)
 {
     ALOGV("Module::detach()");
-    AutoMutex lock(mLock);
-    ssize_t index = -1;
+    Vector<audio_session_t> releasedSessions;
 
-    for (size_t i = 0; i < mModuleClients.size(); i++) {
-        if (mModuleClients[i] == moduleClient) {
-            index = i;
-            break;
-        }
-    }
-    if (index == -1) {
-        return;
-    }
+    {
+        AutoMutex lock(mLock);
+        ssize_t index = -1;
 
-    ALOGV("remove client %p", moduleClient.get());
-    mModuleClients.removeAt(index);
-
-    // Iterate in reverse order as models are removed from list inside the loop.
-    for (size_t i = mModels.size(); i > 0; i--) {
-        sp<Model> model = mModels.valueAt(i - 1);
-        if (moduleClient == model->mModuleClient) {
-            mModels.removeItemsAt(i - 1);
-            ALOGV("detach() unloading model %d", model->mHandle);
-            if (mHalInterface != 0) {
-                if (model->mState == Model::STATE_ACTIVE) {
-                    mHalInterface->stopRecognition(model->mHandle);
-                }
-                mHalInterface->unloadSoundModel(model->mHandle);
+        for (size_t i = 0; i < mModuleClients.size(); i++) {
+            if (mModuleClients[i] == moduleClient) {
+                index = i;
+                break;
             }
-            AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
-            mHalInterface->unloadSoundModel(model->mHandle);
         }
+        if (index == -1) {
+            return;
+        }
+
+        ALOGV("remove client %p", moduleClient.get());
+        mModuleClients.removeAt(index);
+
+        // Iterate in reverse order as models are removed from list inside the loop.
+        for (size_t i = mModels.size(); i > 0; i--) {
+            sp<Model> model = mModels.valueAt(i - 1);
+            if (moduleClient == model->mModuleClient) {
+                mModels.removeItemsAt(i - 1);
+                ALOGV("detach() unloading model %d", model->mHandle);
+                if (mHalInterface != 0) {
+                    if (model->mState == Model::STATE_ACTIVE) {
+                        mHalInterface->stopRecognition(model->mHandle);
+                    }
+                    mHalInterface->unloadSoundModel(model->mHandle);
+                }
+                releasedSessions.add(model->mCaptureSession);
+            }
+        }
+    }
+
+    for (size_t i = 0; i < releasedSessions.size(); i++) {
+        // do not call AudioSystem methods with mLock held
+        AudioSystem::releaseSoundTriggerSession(releasedSessions[i]);
     }
 }
 
@@ -593,61 +603,71 @@
         return BAD_VALUE;
     }
 
-    AutoMutex lock(mLock);
-
-    if (mModels.size() >= mDescriptor.properties.max_sound_models) {
-        ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
-              mDescriptor.properties.max_sound_models);
-        return INVALID_OPERATION;
-    }
-
-    status_t status = mHalInterface->loadSoundModel(sound_model,
-                                                  SoundTriggerHwService::soundModelCallback,
-                                                  this, handle);
-
-    if (status != NO_ERROR) {
-        return status;
-    }
     audio_session_t session;
     audio_io_handle_t ioHandle;
     audio_devices_t device;
-
-    status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
+    // do not call AudioSystem methods with mLock held
+    status_t status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
     if (status != NO_ERROR) {
         return status;
     }
 
-    sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
-                                moduleClient);
-    mModels.replaceValueFor(*handle, model);
+    {
+        AutoMutex lock(mLock);
 
+        if (mModels.size() >= mDescriptor.properties.max_sound_models) {
+            ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
+                  mDescriptor.properties.max_sound_models);
+            status = INVALID_OPERATION;
+            goto exit;
+        }
+
+        status = mHalInterface->loadSoundModel(sound_model,
+                                                      SoundTriggerHwService::soundModelCallback,
+                                                      this, handle);
+        if (status != NO_ERROR) {
+            goto exit;
+        }
+
+        sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
+                                    moduleClient);
+        mModels.replaceValueFor(*handle, model);
+    }
+exit:
+    if (status != NO_ERROR) {
+        // do not call AudioSystem methods with mLock held
+        AudioSystem::releaseSoundTriggerSession(session);
+    }
     return status;
 }
 
 status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
 {
     ALOGV("unloadSoundModel() model handle %d", handle);
-    AutoMutex lock(mLock);
-    return unloadSoundModel_l(handle);
-}
+    status_t status;
+    audio_session_t session;
 
-status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
-{
-    if (mHalInterface == 0) {
-        return NO_INIT;
+    {
+        AutoMutex lock(mLock);
+        if (mHalInterface == 0) {
+            return NO_INIT;
+        }
+        ssize_t index = mModels.indexOfKey(handle);
+        if (index < 0) {
+            return BAD_VALUE;
+        }
+        sp<Model> model = mModels.valueAt(index);
+        mModels.removeItem(handle);
+        if (model->mState == Model::STATE_ACTIVE) {
+            mHalInterface->stopRecognition(model->mHandle);
+            model->mState = Model::STATE_IDLE;
+        }
+        status = mHalInterface->unloadSoundModel(handle);
+        session = model->mCaptureSession;
     }
-    ssize_t index = mModels.indexOfKey(handle);
-    if (index < 0) {
-        return BAD_VALUE;
-    }
-    sp<Model> model = mModels.valueAt(index);
-    mModels.removeItem(handle);
-    if (model->mState == Model::STATE_ACTIVE) {
-        mHalInterface->stopRecognition(model->mHandle);
-        model->mState = Model::STATE_IDLE;
-    }
-    AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
-    return mHalInterface->unloadSoundModel(handle);
+    // do not call AudioSystem methods with mLock held
+    AudioSystem::releaseSoundTriggerSession(session);
+    return status;
 }
 
 status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
@@ -838,7 +858,7 @@
         }
 
         const bool supports_stop_all =
-                (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() == ENOSYS);
+                (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() != -ENOSYS);
 
         for (size_t i = 0; i < mModels.size(); i++) {
             sp<Model> model = mModels.valueAt(i);
@@ -942,7 +962,8 @@
 
 void SoundTriggerHwService::ModuleClient::detach() {
     ALOGV("detach()");
-    if (!captureHotwordAllowed()) {
+    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
         return;
     }
 
@@ -965,7 +986,8 @@
                                 sound_model_handle_t *handle)
 {
     ALOGV("loadSoundModel() handle");
-    if (!captureHotwordAllowed()) {
+    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
         return PERMISSION_DENIED;
     }
 
@@ -979,7 +1001,8 @@
 status_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle)
 {
     ALOGV("unloadSoundModel() model handle %d", handle);
-    if (!captureHotwordAllowed()) {
+    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
         return PERMISSION_DENIED;
     }
 
@@ -994,7 +1017,8 @@
                                  const sp<IMemory>& dataMemory)
 {
     ALOGV("startRecognition() model handle %d", handle);
-    if (!captureHotwordAllowed()) {
+    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
         return PERMISSION_DENIED;
     }
 
@@ -1008,7 +1032,8 @@
 status_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle)
 {
     ALOGV("stopRecognition() model handle %d", handle);
-    if (!captureHotwordAllowed()) {
+    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
         return PERMISSION_DENIED;
     }
 
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
index 60ebb35..95efc4b 100644
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -140,8 +140,6 @@
 
     private:
 
-        status_t unloadSoundModel_l(sound_model_handle_t handle);
-
         Mutex                                  mLock;
         wp<SoundTriggerHwService>              mService;
         sp<SoundTriggerHalInterface>           mHalInterface;