Merge "Fix dst rect calculation"
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index a5937fd..af8ec06 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -37,9 +37,11 @@
 
 namespace.platform.isolated = true
 
-namespace.platform.search.paths = /system/${LIB}
+namespace.platform.search.paths  = /system/${LIB}
+namespace.platform.search.paths += /apex/com.android.runtime/${LIB}
 namespace.platform.asan.search.paths  = /data/asan/system/${LIB}
 namespace.platform.asan.search.paths +=           /system/${LIB}
+namespace.platform.asan.search.paths += /apex/com.android.runtime/${LIB}
 
 # /system/lib/libc.so, etc are symlinks to /apex/com.android.lib/lib/bionic/libc.so, etc.
 # Add /apex/... pat to the permitted paths because linker uses realpath(3)
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 334f879..320c499 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -17,6 +17,10 @@
 
     srcs: ["main_cameraserver.cpp"],
 
+    header_libs: [
+        "libmedia_headers",
+    ],
+
     shared_libs: [
         "libcameraservice",
         "liblog",
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index d24cb81..46a8dae 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -29,7 +29,7 @@
 #include "ACameraCaptureSession.inc"
 
 ACameraDevice::~ACameraDevice() {
-    mDevice->stopLooper();
+    mDevice->stopLooperAndDisconnect();
 }
 
 namespace android {
@@ -112,19 +112,7 @@
     }
 }
 
-// Device close implementaiton
-CameraDevice::~CameraDevice() {
-    sp<ACameraCaptureSession> session = mCurrentSession.promote();
-    {
-        Mutex::Autolock _l(mDeviceLock);
-        if (!isClosed()) {
-            disconnectLocked(session);
-        }
-        LOG_ALWAYS_FATAL_IF(mCbLooper != nullptr,
-                "CameraDevice looper should've been stopped before ~CameraDevice");
-        mCurrentSession = nullptr;
-    }
-}
+CameraDevice::~CameraDevice() { }
 
 void
 CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
@@ -892,8 +880,14 @@
     return;
 }
 
-void CameraDevice::stopLooper() {
+void CameraDevice::stopLooperAndDisconnect() {
     Mutex::Autolock _l(mDeviceLock);
+    sp<ACameraCaptureSession> session = mCurrentSession.promote();
+    if (!isClosed()) {
+        disconnectLocked(session);
+    }
+    mCurrentSession = nullptr;
+
     if (mCbLooper != nullptr) {
       mCbLooper->unregisterHandler(mHandler->id());
       mCbLooper->stop();
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 7a35bf0..6c2ceb3 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -40,6 +40,7 @@
 
 #include <camera/NdkCameraManager.h>
 #include <camera/NdkCameraCaptureSession.h>
+
 #include "ACameraMetadata.h"
 
 namespace android {
@@ -110,7 +111,7 @@
     inline ACameraDevice* getWrapper() const { return mWrapper; };
 
     // Stop the looper thread and unregister the handler
-    void stopLooper();
+    void stopLooperAndDisconnect();
 
   private:
     friend ACameraCaptureSession;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 35c8355..e511a3f 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -45,7 +45,7 @@
 using namespace android;
 
 ACameraDevice::~ACameraDevice() {
-    mDevice->stopLooper();
+    mDevice->stopLooperAndDisconnect();
 }
 
 namespace android {
@@ -125,19 +125,7 @@
     }
 }
 
-// Device close implementaiton
-CameraDevice::~CameraDevice() {
-    sp<ACameraCaptureSession> session = mCurrentSession.promote();
-    {
-        Mutex::Autolock _l(mDeviceLock);
-        if (!isClosed()) {
-            disconnectLocked(session);
-        }
-        mCurrentSession = nullptr;
-        LOG_ALWAYS_FATAL_IF(mCbLooper != nullptr,
-            "CameraDevice looper should've been stopped before ~CameraDevice");
-    }
-}
+CameraDevice::~CameraDevice() { }
 
 void
 CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
@@ -1388,6 +1376,7 @@
             // before cbh goes out of scope and causing we call the session
             // destructor while holding device lock
             cbh.mSession.clear();
+
             postSessionMsgAndCleanup(msg);
         }
 
@@ -1400,8 +1389,13 @@
     }
 }
 
-void CameraDevice::stopLooper() {
+void CameraDevice::stopLooperAndDisconnect() {
     Mutex::Autolock _l(mDeviceLock);
+    sp<ACameraCaptureSession> session = mCurrentSession.promote();
+    if (!isClosed()) {
+        disconnectLocked(session);
+    }
+    mCurrentSession = nullptr;
     if (mCbLooper != nullptr) {
       mCbLooper->unregisterHandler(mHandler->id());
       mCbLooper->stop();
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index 3328a85..7fc699e 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -36,6 +36,7 @@
 
 #include <camera/NdkCameraManager.h>
 #include <camera/NdkCameraCaptureSession.h>
+
 #include "ACameraMetadata.h"
 #include "utils.h"
 
@@ -134,10 +135,11 @@
     inline ACameraDevice* getWrapper() const { return mWrapper; };
 
     // Stop the looper thread and unregister the handler
-    void stopLooper();
+    void stopLooperAndDisconnect();
 
   private:
     friend ACameraCaptureSession;
+    friend ACameraDevice;
 
     camera_status_t checkCameraClosedOrErrorLocked() const;
 
@@ -387,7 +389,6 @@
             mDevice(new android::acam::CameraDevice(id, cb, std::move(chars), this)) {}
 
     ~ACameraDevice();
-
     /*******************
      * NDK public APIs *
      *******************/
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 37de30a..7ab0124 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -24,6 +24,7 @@
 #include <algorithm>
 #include <mutex>
 #include <string>
+#include <variant>
 #include <vector>
 #include <stdio.h>
 #include <stdio.h>
@@ -49,6 +50,7 @@
 static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
 
 using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+using ConfiguredWindows = std::set<native_handle_t *>;
 
 class CameraHelper {
    public:
@@ -60,9 +62,12 @@
         const char* physicalCameraId;
         native_handle_t* anw;
     };
-    int initCamera(native_handle_t* imgReaderAnw,
+
+    // Retaining the error code in case the caller needs to analyze it.
+    std::variant<int, ConfiguredWindows> initCamera(native_handle_t* imgReaderAnw,
             const std::vector<PhysicalImgReaderInfo>& physicalImgReaders,
             bool usePhysicalSettings) {
+        ConfiguredWindows configuredWindows;
         if (imgReaderAnw == nullptr) {
             ALOGE("Cannot initialize camera before image reader get initialized.");
             return -1;
@@ -78,7 +83,7 @@
         ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice);
         if (ret != AMEDIA_OK || mDevice == nullptr) {
             ALOGE("Failed to open camera, ret=%d, mDevice=%p.", ret, mDevice);
-            return -1;
+            return ret;
         }
 
         // Create capture session
@@ -97,8 +102,9 @@
             ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
             return ret;
         }
-
+        configuredWindows.insert(mImgReaderAnw);
         std::vector<const char*> idPointerList;
+        std::set<const native_handle_t*> physicalStreamMap;
         for (auto& physicalStream : physicalImgReaders) {
             ACaptureSessionOutput* sessionOutput = nullptr;
             ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
@@ -112,21 +118,25 @@
                 ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
                 return ret;
             }
-            mExtraOutputs.push_back(sessionOutput);
+            ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
+            if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
+                ALOGW("ACameraDevice_isSessionConfigurationSupported failed, ret=%d camera id %s",
+                      ret, mCameraId);
+                ACaptureSessionOutputContainer_remove(mOutputs, sessionOutput);
+                ACaptureSessionOutput_free(sessionOutput);
+                continue;
+            }
+            configuredWindows.insert(physicalStream.anw);
             // Assume that at most one physical stream per physical camera.
             mPhysicalCameraIds.push_back(physicalStream.physicalCameraId);
             idPointerList.push_back(physicalStream.physicalCameraId);
+            physicalStreamMap.insert(physicalStream.anw);
+            mSessionPhysicalOutputs.push_back(sessionOutput);
         }
         ACameraIdList cameraIdList;
         cameraIdList.numCameras = idPointerList.size();
         cameraIdList.cameraIds = idPointerList.data();
 
-        ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
-        if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
-            ALOGE("ACameraDevice_isSessionConfigurationSupported failed, ret=%d", ret);
-            return ret;
-        }
-
         ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
         if (ret != AMEDIA_OK) {
             ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
@@ -157,6 +167,10 @@
         }
 
         for (auto& physicalStream : physicalImgReaders) {
+            if (physicalStreamMap.find(physicalStream.anw) == physicalStreamMap.end()) {
+                ALOGI("Skipping physicalStream anw=%p", physicalStream.anw);
+                continue;
+            }
             ACameraOutputTarget* outputTarget = nullptr;
             ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget);
             if (ret != AMEDIA_OK) {
@@ -168,11 +182,11 @@
                 ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
                 return ret;
             }
-            mReqExtraOutputs.push_back(outputTarget);
+            mReqPhysicalOutputs.push_back(outputTarget);
         }
 
         mIsCameraReady = true;
-        return 0;
+        return configuredWindows;
     }
 
 
@@ -184,10 +198,10 @@
             ACameraOutputTarget_free(mReqImgReaderOutput);
             mReqImgReaderOutput = nullptr;
         }
-        for (auto& outputTarget : mReqExtraOutputs) {
+        for (auto& outputTarget : mReqPhysicalOutputs) {
             ACameraOutputTarget_free(outputTarget);
         }
-        mReqExtraOutputs.clear();
+        mReqPhysicalOutputs.clear();
         if (mStillRequest) {
             ACaptureRequest_free(mStillRequest);
             mStillRequest = nullptr;
@@ -201,10 +215,10 @@
             ACaptureSessionOutput_free(mImgReaderOutput);
             mImgReaderOutput = nullptr;
         }
-        for (auto& extraOutput : mExtraOutputs) {
+        for (auto& extraOutput : mSessionPhysicalOutputs) {
             ACaptureSessionOutput_free(extraOutput);
         }
-        mExtraOutputs.clear();
+        mSessionPhysicalOutputs.clear();
         if (mOutputs) {
             ACaptureSessionOutputContainer_free(mOutputs);
             mOutputs = nullptr;
@@ -262,13 +276,13 @@
     // Capture session
     ACaptureSessionOutputContainer* mOutputs = nullptr;
     ACaptureSessionOutput* mImgReaderOutput = nullptr;
-    std::vector<ACaptureSessionOutput*> mExtraOutputs;
+    std::vector<ACaptureSessionOutput*> mSessionPhysicalOutputs;
 
     ACameraCaptureSession* mSession = nullptr;
     // Capture request
     ACaptureRequest* mStillRequest = nullptr;
     ACameraOutputTarget* mReqImgReaderOutput = nullptr;
-    std::vector<ACameraOutputTarget*> mReqExtraOutputs;
+    std::vector<ACameraOutputTarget*> mReqPhysicalOutputs;
 
     bool mIsCameraReady = false;
     const char* mCameraId;
@@ -581,9 +595,11 @@
         }
 
         CameraHelper cameraHelper(id, mCameraManager);
-        ret = cameraHelper.initCamera(testCase.getNativeWindow(),
-                {}/*physicalImageReaders*/, false/*usePhysicalSettings*/);
-        if (ret < 0) {
+        std::variant<int, ConfiguredWindows> retInit =
+                cameraHelper.initCamera(testCase.getNativeWindow(), {}/*physicalImageReaders*/,
+                                        false/*usePhysicalSettings*/);
+        int *retp = std::get_if<int>(&retInit);
+        if (retp) {
             ALOGE("Unable to initialize camera helper");
             return false;
         }
@@ -751,10 +767,15 @@
         physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
         physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
 
-        int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(),
-                physicalImgReaderInfo, usePhysicalSettings);
-        ASSERT_EQ(ret, 0);
-
+        std::variant<int, ConfiguredWindows> retInit =
+                cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo,
+                                        usePhysicalSettings);
+        int *retp = std::get_if<int>(&retInit);
+        ASSERT_EQ(retp, nullptr);
+        ConfiguredWindows *configuredWindowsp = std::get_if<ConfiguredWindows>(&retInit);
+        ASSERT_NE(configuredWindowsp, nullptr);
+        ASSERT_LE(configuredWindowsp->size(), testCases.size());
+        int ret = 0;
         if (!cameraHelper.isCameraReady()) {
             ALOGW("Camera is not ready after successful initialization. It's either due to camera "
                   "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
@@ -776,9 +797,15 @@
                 break;
             }
         }
-        ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount);
-        ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount);
-        ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount);
+        for(auto &testCase : testCases) {
+            auto it = configuredWindowsp->find(testCase->getNativeWindow());
+            if (it == configuredWindowsp->end()) {
+                continue;
+            }
+            ALOGI("Testing window %p", testCase->getNativeWindow());
+            ASSERT_EQ(testCase->getAcquiredImageCount(), pictureCount);
+        }
+
         ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
 
         ACameraMetadata_free(staticMetadata);
diff --git a/cmds/screenrecord/Android.bp b/cmds/screenrecord/Android.bp
index 86476cd..6bdbab1 100644
--- a/cmds/screenrecord/Android.bp
+++ b/cmds/screenrecord/Android.bp
@@ -24,6 +24,10 @@
         "Program.cpp",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
     shared_libs: [
         "libstagefright",
         "libmedia",
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index df28842..f2a71b3 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -52,7 +52,7 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaMuxer.h>
 #include <media/stagefright/PersistentSurface.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 
 #include "screenrecord.h"
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 0c8d44a..defc94f 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -3,14 +3,15 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=       \
+        AudioPlayer.cpp \
         stagefright.cpp \
         jpeg.cpp        \
         SineSource.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-        libstagefright libmedia libmedia_omx libutils libbinder \
+        libstagefright libmedia libmedia_codeclist libutils libbinder \
         libstagefright_foundation libjpeg libui libgui libcutils liblog \
-        libhidlbase \
+        libhidlbase libdatasource libaudioclient \
         android.hardware.media.omx@1.0 \
 
 LOCAL_C_INCLUDES:= \
@@ -31,14 +32,16 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
+        AudioPlayer.cpp \
         SineSource.cpp    \
         record.cpp
 
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia liblog libutils libbinder \
-        libstagefright_foundation
+        libstagefright_foundation libdatasource libaudioclient
 
 LOCAL_C_INCLUDES:= \
+        frameworks/av/camera/include \
         frameworks/av/media/libstagefright \
         frameworks/native/include/media/openmax \
         frameworks/native/include/media/hardware
@@ -56,12 +59,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        SineSource.cpp    \
+        AudioPlayer.cpp \
         recordvideo.cpp
 
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia liblog libutils libbinder \
-        libstagefright_foundation
+        libstagefright_foundation libaudioclient
 
 LOCAL_C_INCLUDES:= \
         frameworks/av/media/libstagefright \
@@ -82,12 +85,13 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
+        AudioPlayer.cpp \
         SineSource.cpp    \
         audioloop.cpp
 
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia liblog libutils libbinder \
-        libstagefright_foundation
+        libstagefright_foundation libaudioclient
 
 LOCAL_C_INCLUDES:= \
         frameworks/av/media/libstagefright \
@@ -110,7 +114,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libui libgui \
-        libstagefright_foundation libmedia libcutils
+        libstagefright_foundation libmedia libcutils libdatasource
 
 LOCAL_C_INCLUDES:= \
         frameworks/av/media/libstagefright \
@@ -132,6 +136,9 @@
         codec.cpp               \
         SimplePlayer.cpp        \
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediadrm_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libstagefright_foundation \
         libmedia libmedia_omx libaudioclient libui libgui libcutils
@@ -158,17 +165,18 @@
         filters/saturation.rscript \
         mediafilter.cpp \
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediadrm_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright \
         liblog \
         libutils \
         libbinder \
         libstagefright_foundation \
-        libmedia \
         libmedia_omx \
         libui \
         libgui \
-        libcutils \
         libRScpp \
 
 LOCAL_C_INCLUDES:= \
diff --git a/media/libstagefright/AudioPlayer.cpp b/cmds/stagefright/AudioPlayer.cpp
similarity index 99%
rename from media/libstagefright/AudioPlayer.cpp
rename to cmds/stagefright/AudioPlayer.cpp
index 199b57b..208713d 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/cmds/stagefright/AudioPlayer.cpp
@@ -28,12 +28,13 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALookup.h>
 #include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
 
+#include "AudioPlayer.h"
+
 namespace android {
 
 AudioPlayer::AudioPlayer(
diff --git a/media/libstagefright/include/media/stagefright/AudioPlayer.h b/cmds/stagefright/AudioPlayer.h
similarity index 100%
rename from media/libstagefright/include/media/stagefright/AudioPlayer.h
rename to cmds/stagefright/AudioPlayer.h
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index afb7db3..f4b8164 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -23,7 +23,7 @@
 #include <gui/Surface.h>
 
 #include <media/AudioTrack.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaHTTPService.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index d4f2e8d..bd274d8 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -29,11 +29,11 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/AMRWriter.h>
-#include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/AudioSource.h>
 #include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/SimpleDecodingSource.h>
+#include "AudioPlayer.h"
 #include "SineSource.h"
 
 using namespace android;
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index e5a4337..f2d1c29 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -23,7 +23,7 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IMediaPlayerService.h>
 #include <media/MediaCodecBuffer.h>
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index 2cf6955..66302b0 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -24,9 +24,9 @@
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
 #include <media/MediaCodecBuffer.h>
+#include <mediadrm/ICrypto.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 95a16f3..37091c4 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -17,12 +17,11 @@
 #include "SineSource.h"
 
 #include <binder/ProcessState.h>
+#include <datasource/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/CameraSource.h>
-#include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaCodecSource.h>
@@ -33,6 +32,8 @@
 #include <media/stagefright/SimpleDecodingSource.h>
 #include <media/MediaPlayerInterface.h>
 
+#include "AudioPlayer.h"
+
 using namespace android;
 
 static const int32_t kAudioBitRate = 12200;
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
index a63b9b9..01a178e 100644
--- a/cmds/stagefright/recordvideo.cpp
+++ b/cmds/stagefright/recordvideo.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#include "SineSource.h"
-
 #include <inttypes.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -25,8 +23,8 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index bf36be0..9ba6ee1 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -31,18 +31,15 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
 #include <media/MediaSource.h>
-#include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IMediaPlayerService.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
-#include "include/NuCachedSource2.h"
-#include <media/stagefright/AudioPlayer.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/JPEGSource.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaCodec.h>
@@ -69,6 +66,8 @@
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
 
+#include "AudioPlayer.h"
+
 using namespace android;
 
 static long gNumRepetitions;
@@ -1086,7 +1085,7 @@
         const char *filename = argv[k];
 
         sp<DataSource> dataSource =
-            DataSourceFactory::CreateFromURI(NULL /* httpService */, filename);
+            DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, filename);
 
         if (strncasecmp(filename, "sine:", 5) && dataSource == NULL) {
             fprintf(stderr, "Unable to create data source.\n");
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index 35bdbc0..22e2ef3 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -21,6 +21,7 @@
 #include <binder/ProcessState.h>
 #include <cutils/properties.h> // for property_get
 
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IStreamSource.h>
@@ -28,7 +29,6 @@
 #include <media/MediaSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MPEG2TSWriter.h>
 #include <media/stagefright/MediaExtractor.h>
@@ -164,7 +164,7 @@
     : mCurrentBufferIndex(-1),
       mCurrentBufferOffset(0) {
     sp<DataSource> dataSource =
-        DataSourceFactory::CreateFromURI(NULL /* httpService */, filename);
+        DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, filename);
 
     CHECK(dataSource != NULL);
 
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index c29d004..84f2f6d 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -2,6 +2,15 @@
 // libmediadrm
 //
 
+cc_library_headers {
+    name: "libmediadrm_headers",
+
+    export_include_dirs: [
+        "interface"
+    ],
+
+}
+
 cc_library_shared {
     name: "libmediadrm",
 
@@ -17,6 +26,19 @@
         "CryptoHal.cpp",
     ],
 
+    local_include_dirs: [
+        "include",
+        "interface"
+    ],
+
+    export_include_dirs: [
+        "include"
+    ],
+
+    header_libs: [
+        "libmedia_headers",
+    ],
+
     shared_libs: [
         "libbinder",
         "libcutils",
@@ -49,10 +71,17 @@
         "protos/metrics.proto",
     ],
 
+    local_include_dirs: [
+        "include"
+    ],
+
     proto: {
         export_proto_headers: true,
         type: "lite",
     },
+    header_libs: [
+        "libmedia_headers",
+    ],
     shared_libs: [
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
@@ -80,10 +109,17 @@
         "protos/metrics.proto",
     ],
 
+    local_include_dirs: [
+        "include"
+    ],
+
     proto: {
         export_proto_headers: true,
         type: "full",
     },
+    header_libs: [
+        "libmedia_headers",
+    ],
     shared_libs: [
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 919f4ee..e79fd4b 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -895,9 +895,8 @@
 status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
         Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
     Mutex::Autolock autoLock(mLock);
-    EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
-
     INIT_CHECK();
+    EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
diff --git a/media/libmedia/include/media/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
similarity index 100%
rename from media/libmedia/include/media/CryptoHal.h
rename to drm/libmediadrm/include/mediadrm/CryptoHal.h
diff --git a/media/libmedia/include/media/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
similarity index 100%
rename from media/libmedia/include/media/DrmHal.h
rename to drm/libmediadrm/include/mediadrm/DrmHal.h
diff --git a/media/libmedia/include/media/DrmMetrics.h b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
similarity index 100%
rename from media/libmedia/include/media/DrmMetrics.h
rename to drm/libmediadrm/include/mediadrm/DrmMetrics.h
diff --git a/media/libmedia/include/media/DrmPluginPath.h b/drm/libmediadrm/include/mediadrm/DrmPluginPath.h
similarity index 100%
rename from media/libmedia/include/media/DrmPluginPath.h
rename to drm/libmediadrm/include/mediadrm/DrmPluginPath.h
diff --git a/media/libmedia/include/media/DrmSessionClientInterface.h b/drm/libmediadrm/include/mediadrm/DrmSessionClientInterface.h
similarity index 100%
rename from media/libmedia/include/media/DrmSessionClientInterface.h
rename to drm/libmediadrm/include/mediadrm/DrmSessionClientInterface.h
diff --git a/media/libmedia/include/media/DrmSessionManager.h b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
similarity index 100%
rename from media/libmedia/include/media/DrmSessionManager.h
rename to drm/libmediadrm/include/mediadrm/DrmSessionManager.h
diff --git a/media/libmedia/include/media/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
similarity index 100%
rename from media/libmedia/include/media/IDrm.h
rename to drm/libmediadrm/include/mediadrm/IDrm.h
diff --git a/media/libmedia/include/media/IDrmClient.h b/drm/libmediadrm/include/mediadrm/IDrmClient.h
similarity index 100%
rename from media/libmedia/include/media/IDrmClient.h
rename to drm/libmediadrm/include/mediadrm/IDrmClient.h
diff --git a/media/libmedia/include/media/IMediaDrmService.h b/drm/libmediadrm/include/mediadrm/IMediaDrmService.h
similarity index 100%
rename from media/libmedia/include/media/IMediaDrmService.h
rename to drm/libmediadrm/include/mediadrm/IMediaDrmService.h
diff --git a/media/libmedia/include/media/SharedLibrary.h b/drm/libmediadrm/include/mediadrm/SharedLibrary.h
similarity index 100%
rename from media/libmedia/include/media/SharedLibrary.h
rename to drm/libmediadrm/include/mediadrm/SharedLibrary.h
diff --git a/media/libmedia/include/media/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
similarity index 100%
rename from media/libmedia/include/media/ICrypto.h
rename to drm/libmediadrm/interface/mediadrm/ICrypto.h
diff --git a/drm/libmediadrm/tests/Android.bp b/drm/libmediadrm/tests/Android.bp
index 9e0115e..2e39943 100644
--- a/drm/libmediadrm/tests/Android.bp
+++ b/drm/libmediadrm/tests/Android.bp
@@ -3,8 +3,8 @@
 cc_test {
     name: "CounterMetric_test",
     srcs: ["CounterMetric_test.cpp"],
+    header_libs: ["libmedia_headers"],
     shared_libs: ["libmediadrm"],
-    include_dirs: ["frameworks/av/include/media"],
     cflags: [
       "-Werror",
       "-Wall",
@@ -14,6 +14,9 @@
 cc_test {
     name: "DrmMetrics_test",
     srcs: ["DrmMetrics_test.cpp"],
+    header_libs: [
+        "libmedia_headers"
+    ],
     shared_libs: [
       "android.hardware.drm@1.0",
       "android.hardware.drm@1.1",
@@ -28,7 +31,7 @@
     ],
     static_libs: ["libgmock"],
     include_dirs: [
-      "frameworks/av/include/media",
+      "frameworks/av/drm/libmediadrm/include",
     ],
     cflags: [
         // Suppress unused parameter and no error options. These cause problems
@@ -40,12 +43,14 @@
 cc_test {
     name: "EventMetric_test",
     srcs: ["EventMetric_test.cpp"],
+    header_libs: [
+        "libmedia_headers"
+    ],
     shared_libs: [
       "liblog",
       "libmediadrm",
       "libutils",
     ],
-    include_dirs: ["frameworks/av/include/media"],
     cflags: [
       "-Werror",
       "-Wall",
diff --git a/drm/libmediadrm/tests/CounterMetric_test.cpp b/drm/libmediadrm/tests/CounterMetric_test.cpp
index 6bca0da..c2becb4 100644
--- a/drm/libmediadrm/tests/CounterMetric_test.cpp
+++ b/drm/libmediadrm/tests/CounterMetric_test.cpp
@@ -16,7 +16,7 @@
 
 #include <gtest/gtest.h>
 
-#include "CounterMetric.h"
+#include <media/CounterMetric.h>
 
 namespace android {
 
diff --git a/drm/libmediadrm/tests/EventMetric_test.cpp b/drm/libmediadrm/tests/EventMetric_test.cpp
index eb6c4f6..b3c3f62 100644
--- a/drm/libmediadrm/tests/EventMetric_test.cpp
+++ b/drm/libmediadrm/tests/EventMetric_test.cpp
@@ -16,7 +16,7 @@
 
 #include <gtest/gtest.h>
 
-#include "EventMetric.h"
+#include <media/EventMetric.h>
 
 namespace android {
 
diff --git a/include/camera b/include/camera
deleted file mode 120000
index 00848e3..0000000
--- a/include/camera
+++ /dev/null
@@ -1 +0,0 @@
-../camera/include/camera/
\ No newline at end of file
diff --git a/include/cpustats b/include/cpustats
deleted file mode 120000
index 4a02d41..0000000
--- a/include/cpustats
+++ /dev/null
@@ -1 +0,0 @@
-../media/libcpustats/include/cpustats/
\ No newline at end of file
diff --git a/include/media/AVSyncSettings.h b/include/media/AVSyncSettings.h
deleted file mode 120000
index bbe211f..0000000
--- a/include/media/AVSyncSettings.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/AVSyncSettings.h
\ No newline at end of file
diff --git a/include/media/AudioAttributes.h b/include/media/AudioAttributes.h
deleted file mode 120000
index 27ba471..0000000
--- a/include/media/AudioAttributes.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioAttributes.h
\ No newline at end of file
diff --git a/include/media/AudioBufferProvider.h b/include/media/AudioBufferProvider.h
deleted file mode 120000
index c4d6e79..0000000
--- a/include/media/AudioBufferProvider.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioBufferProvider.h
\ No newline at end of file
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/include/media/AudioCommonTypes.h b/include/media/AudioCommonTypes.h
deleted file mode 120000
index ae7c99a..0000000
--- a/include/media/AudioCommonTypes.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioCommonTypes.h
\ No newline at end of file
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
deleted file mode 120000
index bf52955..0000000
--- a/include/media/AudioEffect.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioEffect.h
\ No newline at end of file
diff --git a/include/media/AudioIoDescriptor.h b/include/media/AudioIoDescriptor.h
deleted file mode 120000
index 68f54c9..0000000
--- a/include/media/AudioIoDescriptor.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioIoDescriptor.h
\ No newline at end of file
diff --git a/include/media/AudioMixer.h b/include/media/AudioMixer.h
deleted file mode 120000
index de839c6..0000000
--- a/include/media/AudioMixer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioMixer.h
\ No newline at end of file
diff --git a/include/media/AudioParameter.h b/include/media/AudioParameter.h
deleted file mode 120000
index a5889e5..0000000
--- a/include/media/AudioParameter.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioParameter.h
\ No newline at end of file
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
deleted file mode 120000
index dd4cd53..0000000
--- a/include/media/AudioPolicy.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioPolicy.h
\ No newline at end of file
diff --git a/include/media/AudioProductStrategy.h b/include/media/AudioProductStrategy.h
deleted file mode 120000
index 6bfaf11..0000000
--- a/include/media/AudioProductStrategy.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioProductStrategy.h
\ No newline at end of file
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
deleted file mode 120000
index 7939dd3..0000000
--- a/include/media/AudioRecord.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioRecord.h
\ No newline at end of file
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
deleted file mode 120000
index 9fad2b7..0000000
--- a/include/media/AudioSystem.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioSystem.h
\ No newline at end of file
diff --git a/include/media/AudioTimestamp.h b/include/media/AudioTimestamp.h
deleted file mode 120000
index b6b9278..0000000
--- a/include/media/AudioTimestamp.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioTimestamp.h
\ No newline at end of file
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
deleted file mode 120000
index 303bfcd..0000000
--- a/include/media/AudioTrack.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioTrack.h
\ No newline at end of file
diff --git a/include/media/AudioVolumeGroup.h b/include/media/AudioVolumeGroup.h
deleted file mode 120000
index d6f1c99..0000000
--- a/include/media/AudioVolumeGroup.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioVolumeGroup.h
\ No newline at end of file
diff --git a/include/media/BufferProviders.h b/include/media/BufferProviders.h
deleted file mode 120000
index 779bb15..0000000
--- a/include/media/BufferProviders.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/BufferProviders.h
\ No newline at end of file
diff --git a/include/media/BufferingSettings.h b/include/media/BufferingSettings.h
deleted file mode 120000
index 409203f..0000000
--- a/include/media/BufferingSettings.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/BufferingSettings.h
\ No newline at end of file
diff --git a/include/media/CharacterEncodingDetector.h b/include/media/CharacterEncodingDetector.h
deleted file mode 120000
index 2b28387..0000000
--- a/include/media/CharacterEncodingDetector.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/CharacterEncodingDetector.h
\ No newline at end of file
diff --git a/include/media/CounterMetric.h b/include/media/CounterMetric.h
deleted file mode 120000
index baba043..0000000
--- a/include/media/CounterMetric.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/CounterMetric.h
\ No newline at end of file
diff --git a/include/media/EventLog.h b/include/media/EventLog.h
deleted file mode 120000
index 9b2c4bf..0000000
--- a/include/media/EventLog.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/utils/include/mediautils/EventLog.h
\ No newline at end of file
diff --git a/include/media/EventMetric.h b/include/media/EventMetric.h
deleted file mode 120000
index 5707d9a..0000000
--- a/include/media/EventMetric.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/EventMetric.h
\ No newline at end of file
diff --git a/include/media/ExtendedAudioBufferProvider.h b/include/media/ExtendedAudioBufferProvider.h
deleted file mode 120000
index 99d3c13..0000000
--- a/include/media/ExtendedAudioBufferProvider.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/ExtendedAudioBufferProvider.h
\ No newline at end of file
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
deleted file mode 120000
index ef6f5be..0000000
--- a/include/media/IAudioFlinger.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioFlinger.h
\ No newline at end of file
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
deleted file mode 120000
index dc481e8..0000000
--- a/include/media/IAudioFlingerClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioFlingerClient.h
\ No newline at end of file
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
deleted file mode 120000
index 08101fc..0000000
--- a/include/media/IAudioPolicyService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioPolicyService.h
\ No newline at end of file
diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h
deleted file mode 120000
index 0d4b3e7..0000000
--- a/include/media/IAudioPolicyServiceClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioPolicyServiceClient.h
\ No newline at end of file
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
deleted file mode 120000
index 7bab1fd..0000000
--- a/include/media/IAudioTrack.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioTrack.h
\ No newline at end of file
diff --git a/include/media/IDataSource.h b/include/media/IDataSource.h
deleted file mode 120000
index 41cdd8b..0000000
--- a/include/media/IDataSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IDataSource.h
\ No newline at end of file
diff --git a/include/media/IEffect.h b/include/media/IEffect.h
deleted file mode 120000
index 2fb8bfb..0000000
--- a/include/media/IEffect.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IEffect.h
\ No newline at end of file
diff --git a/include/media/IEffectClient.h b/include/media/IEffectClient.h
deleted file mode 120000
index b4e39cf..0000000
--- a/include/media/IEffectClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IEffectClient.h
\ No newline at end of file
diff --git a/include/media/IMediaCodecList.h b/include/media/IMediaCodecList.h
deleted file mode 120000
index 2186312..0000000
--- a/include/media/IMediaCodecList.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaCodecList.h
\ No newline at end of file
diff --git a/include/media/IMediaDeathNotifier.h b/include/media/IMediaDeathNotifier.h
deleted file mode 120000
index ce3b8f0..0000000
--- a/include/media/IMediaDeathNotifier.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaDeathNotifier.h
\ No newline at end of file
diff --git a/include/media/IMediaExtractor.h b/include/media/IMediaExtractor.h
deleted file mode 120000
index 8708c8c..0000000
--- a/include/media/IMediaExtractor.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaExtractor.h
\ No newline at end of file
diff --git a/include/media/IMediaExtractorService.h b/include/media/IMediaExtractorService.h
deleted file mode 120000
index 3ee9f1e..0000000
--- a/include/media/IMediaExtractorService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaExtractorService.h
\ No newline at end of file
diff --git a/include/media/IMediaHTTPConnection.h b/include/media/IMediaHTTPConnection.h
deleted file mode 120000
index 0970c15..0000000
--- a/include/media/IMediaHTTPConnection.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaHTTPConnection.h
\ No newline at end of file
diff --git a/include/media/IMediaHTTPService.h b/include/media/IMediaHTTPService.h
deleted file mode 120000
index b90c34f..0000000
--- a/include/media/IMediaHTTPService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaHTTPService.h
\ No newline at end of file
diff --git a/include/media/IMediaLogService.h b/include/media/IMediaLogService.h
deleted file mode 120000
index 245a29d..0000000
--- a/include/media/IMediaLogService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaLogService.h
\ No newline at end of file
diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h
deleted file mode 120000
index 959df1a..0000000
--- a/include/media/IMediaMetadataRetriever.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaMetadataRetriever.h
\ No newline at end of file
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
deleted file mode 120000
index 9414d37..0000000
--- a/include/media/IMediaPlayer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaPlayer.h
\ No newline at end of file
diff --git a/include/media/IMediaPlayerClient.h b/include/media/IMediaPlayerClient.h
deleted file mode 120000
index b6547ce..0000000
--- a/include/media/IMediaPlayerClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaPlayerClient.h
\ No newline at end of file
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
deleted file mode 120000
index 89c96cd..0000000
--- a/include/media/IMediaPlayerService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaPlayerService.h
\ No newline at end of file
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
deleted file mode 120000
index 57d192c..0000000
--- a/include/media/IMediaRecorder.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaRecorder.h
\ No newline at end of file
diff --git a/include/media/IMediaRecorderClient.h b/include/media/IMediaRecorderClient.h
deleted file mode 120000
index 89f4359..0000000
--- a/include/media/IMediaRecorderClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaRecorderClient.h
\ No newline at end of file
diff --git a/include/media/IMediaSource.h b/include/media/IMediaSource.h
deleted file mode 120000
index 1330ad3..0000000
--- a/include/media/IMediaSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaSource.h
\ No newline at end of file
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
deleted file mode 120000
index 6d5b375..0000000
--- a/include/media/IOMX.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IOMX.h
\ No newline at end of file
diff --git a/include/media/IRemoteDisplay.h b/include/media/IRemoteDisplay.h
deleted file mode 120000
index 4b0cf10..0000000
--- a/include/media/IRemoteDisplay.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IRemoteDisplay.h
\ No newline at end of file
diff --git a/include/media/IRemoteDisplayClient.h b/include/media/IRemoteDisplayClient.h
deleted file mode 120000
index f29a2ee..0000000
--- a/include/media/IRemoteDisplayClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IRemoteDisplayClient.h
\ No newline at end of file
diff --git a/include/media/IResourceManagerClient.h b/include/media/IResourceManagerClient.h
deleted file mode 120000
index 100af9b..0000000
--- a/include/media/IResourceManagerClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IResourceManagerClient.h
\ No newline at end of file
diff --git a/include/media/IResourceManagerService.h b/include/media/IResourceManagerService.h
deleted file mode 120000
index 9b389c6..0000000
--- a/include/media/IResourceManagerService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IResourceManagerService.h
\ No newline at end of file
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
deleted file mode 120000
index 4943af9..0000000
--- a/include/media/IStreamSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IStreamSource.h
\ No newline at end of file
diff --git a/include/media/JetPlayer.h b/include/media/JetPlayer.h
deleted file mode 120000
index 5483fda..0000000
--- a/include/media/JetPlayer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/JetPlayer.h
\ No newline at end of file
diff --git a/include/media/LinearMap.h b/include/media/LinearMap.h
deleted file mode 120000
index 30d4ca8..0000000
--- a/include/media/LinearMap.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/LinearMap.h
\ No newline at end of file
diff --git a/include/media/MediaCodecBuffer.h b/include/media/MediaCodecBuffer.h
deleted file mode 120000
index 8c9aa76..0000000
--- a/include/media/MediaCodecBuffer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaCodecBuffer.h
\ No newline at end of file
diff --git a/include/media/MediaCodecInfo.h b/include/media/MediaCodecInfo.h
deleted file mode 120000
index ff44ce4..0000000
--- a/include/media/MediaCodecInfo.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaCodecInfo.h
\ No newline at end of file
diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h
deleted file mode 120000
index 1c53511..0000000
--- a/include/media/MediaMetadataRetrieverInterface.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaMetadataRetrieverInterface.h
\ No newline at end of file
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
deleted file mode 120000
index 651c6e6..0000000
--- a/include/media/MediaProfiles.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaProfiles.h
\ No newline at end of file
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
deleted file mode 120000
index e40f992..0000000
--- a/include/media/MediaRecorderBase.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaRecorderBase.h
\ No newline at end of file
diff --git a/include/media/MediaResource.h b/include/media/MediaResource.h
deleted file mode 120000
index 91346aa..0000000
--- a/include/media/MediaResource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaResource.h
\ No newline at end of file
diff --git a/include/media/MediaResourcePolicy.h b/include/media/MediaResourcePolicy.h
deleted file mode 120000
index 5d165ee..0000000
--- a/include/media/MediaResourcePolicy.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaResourcePolicy.h
\ No newline at end of file
diff --git a/include/media/MemoryLeakTrackUtil.h b/include/media/MemoryLeakTrackUtil.h
deleted file mode 120000
index 504173e..0000000
--- a/include/media/MemoryLeakTrackUtil.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MemoryLeakTrackUtil.h
\ No newline at end of file
diff --git a/include/media/Metadata.h b/include/media/Metadata.h
deleted file mode 120000
index e421168..0000000
--- a/include/media/Metadata.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/Metadata.h
\ No newline at end of file
diff --git a/include/media/MidiDeviceInfo.h b/include/media/MidiDeviceInfo.h
deleted file mode 120000
index 95da7cf..0000000
--- a/include/media/MidiDeviceInfo.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MidiDeviceInfo.h
\ No newline at end of file
diff --git a/include/media/MidiIoWrapper.h b/include/media/MidiIoWrapper.h
deleted file mode 120000
index 786ec3d..0000000
--- a/include/media/MidiIoWrapper.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MidiIoWrapper.h
\ No newline at end of file
diff --git a/include/media/Modulo.h b/include/media/Modulo.h
deleted file mode 120000
index 989c4cb..0000000
--- a/include/media/Modulo.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/Modulo.h
\ No newline at end of file
diff --git a/include/media/OMXBuffer.h b/include/media/OMXBuffer.h
deleted file mode 120000
index 00db207..0000000
--- a/include/media/OMXBuffer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/OMXBuffer.h
\ No newline at end of file
diff --git a/include/media/OMXFenceParcelable.h b/include/media/OMXFenceParcelable.h
deleted file mode 120000
index c4c1b0a..0000000
--- a/include/media/OMXFenceParcelable.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/OMXFenceParcelable.h
\ No newline at end of file
diff --git a/include/media/PluginLoader.h b/include/media/PluginLoader.h
deleted file mode 120000
index 9101735..0000000
--- a/include/media/PluginLoader.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/PluginLoader.h
\ No newline at end of file
diff --git a/include/media/PluginMetricsReporting.h b/include/media/PluginMetricsReporting.h
deleted file mode 120000
index 7d9a7a0..0000000
--- a/include/media/PluginMetricsReporting.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/PluginMetricsReporting.h
\ No newline at end of file
diff --git a/include/media/RecordBufferConverter.h b/include/media/RecordBufferConverter.h
deleted file mode 120000
index 2d7bc0c..0000000
--- a/include/media/RecordBufferConverter.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/RecordBufferConverter.h
\ No newline at end of file
diff --git a/include/media/RingBuffer.h b/include/media/RingBuffer.h
deleted file mode 120000
index 9af28d5..0000000
--- a/include/media/RingBuffer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/RingBuffer.h
\ No newline at end of file
diff --git a/include/media/StringArray.h b/include/media/StringArray.h
deleted file mode 120000
index 616ce6c..0000000
--- a/include/media/StringArray.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/StringArray.h
\ No newline at end of file
diff --git a/include/media/TimeCheck.h b/include/media/TimeCheck.h
deleted file mode 120000
index 85e17f9..0000000
--- a/include/media/TimeCheck.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/utils/include/mediautils/TimeCheck.h
\ No newline at end of file
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
deleted file mode 120000
index 33df0e3..0000000
--- a/include/media/ToneGenerator.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/ToneGenerator.h
\ No newline at end of file
diff --git a/include/media/TypeConverter.h b/include/media/TypeConverter.h
deleted file mode 120000
index 837af44..0000000
--- a/include/media/TypeConverter.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/TypeConverter.h
\ No newline at end of file
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
deleted file mode 120000
index ed2ec15..0000000
--- a/include/media/Visualizer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/Visualizer.h
\ No newline at end of file
diff --git a/include/media/convert.h b/include/media/convert.h
deleted file mode 120000
index cb0d00d..0000000
--- a/include/media/convert.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/convert.h
\ No newline at end of file
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
deleted file mode 120000
index b401bab..0000000
--- a/include/media/mediametadataretriever.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/mediametadataretriever.h
\ No newline at end of file
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
deleted file mode 120000
index 06d537b..0000000
--- a/include/media/mediaplayer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/mediaplayer.h
\ No newline at end of file
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
deleted file mode 120000
index a24deb3..0000000
--- a/include/media/mediarecorder.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/mediarecorder.h
\ No newline at end of file
diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h
deleted file mode 120000
index 91479e0..0000000
--- a/include/media/mediascanner.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/mediascanner.h
\ No newline at end of file
diff --git a/include/media/nbaio/AudioBufferProviderSource.h b/include/media/nbaio/AudioBufferProviderSource.h
deleted file mode 120000
index 55841e7..0000000
--- a/include/media/nbaio/AudioBufferProviderSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../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
deleted file mode 120000
index f5bcc76..0000000
--- a/include/media/nbaio/AudioStreamInSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/AudioStreamInSource.h
\ No newline at end of file
diff --git a/include/media/nbaio/LibsndfileSink.h b/include/media/nbaio/LibsndfileSink.h
deleted file mode 120000
index 8a13b6c..0000000
--- a/include/media/nbaio/LibsndfileSink.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../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
deleted file mode 120000
index 2750fde..0000000
--- a/include/media/nbaio/LibsndfileSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../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
deleted file mode 120000
index 4ea43be..0000000
--- a/include/media/nbaio/MonoPipe.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../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
deleted file mode 120000
index 30f426c..0000000
--- a/include/media/nbaio/MonoPipeReader.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include_mono/media/nbaio/MonoPipeReader.h
\ No newline at end of file
diff --git a/include/media/nbaio/Pipe.h b/include/media/nbaio/Pipe.h
deleted file mode 120000
index a4bbbc9..0000000
--- a/include/media/nbaio/Pipe.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../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
deleted file mode 120000
index 64b21cf..0000000
--- a/include/media/nbaio/PipeReader.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../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
deleted file mode 120000
index 74a3b06..0000000
--- a/include/media/nbaio/SourceAudioBufferProvider.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/SourceAudioBufferProvider.h
\ No newline at end of file
diff --git a/include/media/nblog/NBLog.h b/include/media/nblog/NBLog.h
deleted file mode 120000
index 3cc366c..0000000
--- a/include/media/nblog/NBLog.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnblog/include/media/nblog/NBLog.h
\ No newline at end of file
diff --git a/include/media/nblog/PerformanceAnalysis.h b/include/media/nblog/PerformanceAnalysis.h
deleted file mode 120000
index 6ead3bc..0000000
--- a/include/media/nblog/PerformanceAnalysis.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnblog/include/media/nblog/PerformanceAnalysis.h
\ No newline at end of file
diff --git a/include/media/nblog/ReportPerformance.h b/include/media/nblog/ReportPerformance.h
deleted file mode 120000
index e9b8e80..0000000
--- a/include/media/nblog/ReportPerformance.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnblog/include/media/nblog/ReportPerformance.h
\ No newline at end of file
diff --git a/include/mediadrm/CryptoHal.h b/include/mediadrm/CryptoHal.h
deleted file mode 120000
index 92f3137..0000000
--- a/include/mediadrm/CryptoHal.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/CryptoHal.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmHal.h b/include/mediadrm/DrmHal.h
deleted file mode 120000
index 17bb667..0000000
--- a/include/mediadrm/DrmHal.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmHal.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmMetrics.h b/include/mediadrm/DrmMetrics.h
deleted file mode 120000
index abc966b..0000000
--- a/include/mediadrm/DrmMetrics.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmMetrics.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmPluginPath.h b/include/mediadrm/DrmPluginPath.h
deleted file mode 120000
index 9e05194..0000000
--- a/include/mediadrm/DrmPluginPath.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmPluginPath.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmSessionClientInterface.h b/include/mediadrm/DrmSessionClientInterface.h
deleted file mode 120000
index f4e3211..0000000
--- a/include/mediadrm/DrmSessionClientInterface.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmSessionClientInterface.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmSessionManager.h b/include/mediadrm/DrmSessionManager.h
deleted file mode 120000
index f0a47bf..0000000
--- a/include/mediadrm/DrmSessionManager.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmSessionManager.h
\ No newline at end of file
diff --git a/include/mediadrm/ICrypto.h b/include/mediadrm/ICrypto.h
deleted file mode 120000
index b250e07..0000000
--- a/include/mediadrm/ICrypto.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/ICrypto.h
\ No newline at end of file
diff --git a/include/mediadrm/IDrm.h b/include/mediadrm/IDrm.h
deleted file mode 120000
index 841bb1b..0000000
--- a/include/mediadrm/IDrm.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IDrm.h
\ No newline at end of file
diff --git a/include/mediadrm/IDrmClient.h b/include/mediadrm/IDrmClient.h
deleted file mode 120000
index 10aa5c0..0000000
--- a/include/mediadrm/IDrmClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IDrmClient.h
\ No newline at end of file
diff --git a/include/mediadrm/IMediaDrmService.h b/include/mediadrm/IMediaDrmService.h
deleted file mode 120000
index f3c260f..0000000
--- a/include/mediadrm/IMediaDrmService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaDrmService.h
\ No newline at end of file
diff --git a/include/mediadrm/SharedLibrary.h b/include/mediadrm/SharedLibrary.h
deleted file mode 120000
index 9f8f5a4..0000000
--- a/include/mediadrm/SharedLibrary.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/SharedLibrary.h
\ No newline at end of file
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index f5f021b..6697cb5 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -9,6 +9,7 @@
 	libaaudioservice \
 	libaudioflinger \
 	libaudiopolicyservice \
+	libaudioprocessing \
 	libbinder \
 	libcutils \
 	liblog \
diff --git a/media/bufferpool/1.0/AccessorImpl.cpp b/media/bufferpool/1.0/AccessorImpl.cpp
index fa17f15..a5366f6 100644
--- a/media/bufferpool/1.0/AccessorImpl.cpp
+++ b/media/bufferpool/1.0/AccessorImpl.cpp
@@ -151,6 +151,7 @@
                 newConnection->initialize(accessor, id);
                 *connection = newConnection;
                 *pConnectionId = id;
+                mBufferPool.mConnectionIds.insert(id);
                 ++sSeqId;
             }
         }
@@ -305,7 +306,12 @@
         found->second->mSenderValidated = true;
         return true;
     }
-    // TODO: verify there is target connection Id
+    if (mConnectionIds.find(message.targetConnectionId) == mConnectionIds.end()) {
+        // N.B: it could be fake or receive connection already closed.
+        ALOGD("bufferpool %p receiver connection %lld is no longer valid",
+              this, (long long)message.targetConnectionId);
+        return false;
+    }
     mStats.onBufferSent();
     mTransactions.insert(std::make_pair(
             message.transactionId,
@@ -450,6 +456,7 @@
             }
         }
     }
+    mConnectionIds.erase(connectionId);
     return true;
 }
 
diff --git a/media/bufferpool/1.0/AccessorImpl.h b/media/bufferpool/1.0/AccessorImpl.h
index c04dbf3..84cb685 100644
--- a/media/bufferpool/1.0/AccessorImpl.h
+++ b/media/bufferpool/1.0/AccessorImpl.h
@@ -94,6 +94,7 @@
 
         std::map<BufferId, std::unique_ptr<InternalBuffer>> mBuffers;
         std::set<BufferId> mFreeBuffers;
+        std::set<ConnectionId> mConnectionIds;
 
         /// Buffer pool statistics which tracks allocation and transfer statistics.
         struct Stats {
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 94cf006..cacd465 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -163,6 +163,7 @@
                 *connection = newConnection;
                 *pConnectionId = id;
                 *pMsgId = mBufferPool.mInvalidation.mInvalidationId;
+                mBufferPool.mConnectionIds.insert(id);
                 mBufferPool.mInvalidationChannel.getDesc(invDescPtr);
                 mBufferPool.mInvalidation.onConnect(id, observer);
                 ++sSeqId;
@@ -474,7 +475,12 @@
         found->second->mSenderValidated = true;
         return true;
     }
-    // TODO: verify there is target connection Id
+    if (mConnectionIds.find(message.targetConnectionId) == mConnectionIds.end()) {
+        // N.B: it could be fake or receive connection already closed.
+        ALOGD("bufferpool2 %p receiver connection %lld is no longer valid",
+              this, (long long)message.targetConnectionId);
+        return false;
+    }
     mStats.onBufferSent();
     mTransactions.insert(std::make_pair(
             message.transactionId,
@@ -644,6 +650,7 @@
             }
         }
     }
+    mConnectionIds.erase(connectionId);
     return true;
 }
 
@@ -774,11 +781,19 @@
             std::mutex &mutex,
             std::condition_variable &cv,
             bool &ready) {
+    constexpr uint32_t NUM_SPIN_TO_INCREASE_SLEEP = 1024;
+    constexpr uint32_t NUM_SPIN_TO_LOG = 1024*8;
+    constexpr useconds_t MAX_SLEEP_US = 10000;
+    uint32_t numSpin = 0;
+    useconds_t sleepUs = 1;
+
     while(true) {
         std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> copied;
         {
             std::unique_lock<std::mutex> lock(mutex);
             if (!ready) {
+                numSpin = 0;
+                sleepUs = 1;
                 cv.wait(lock);
             }
             copied.insert(accessors.begin(), accessors.end());
@@ -800,9 +815,20 @@
             if (accessors.size() == 0) {
                 ready = false;
             } else {
-                // prevent draining cpu.
+                // TODO Use an efficient way to wait over FMQ.
+                // N.B. Since there is not a efficient way to wait over FMQ,
+                // polling over the FMQ is the current way to prevent draining
+                // CPU.
                 lock.unlock();
-                std::this_thread::yield();
+                ++numSpin;
+                if (numSpin % NUM_SPIN_TO_INCREASE_SLEEP == 0 &&
+                    sleepUs < MAX_SLEEP_US) {
+                    sleepUs *= 10;
+                }
+                if (numSpin % NUM_SPIN_TO_LOG == 0) {
+                    ALOGW("invalidator thread spinning");
+                }
+                ::usleep(sleepUs);
             }
         }
     }
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/bufferpool/2.0/AccessorImpl.h
index eea72b9..807e0f1 100644
--- a/media/bufferpool/2.0/AccessorImpl.h
+++ b/media/bufferpool/2.0/AccessorImpl.h
@@ -111,6 +111,7 @@
 
         std::map<BufferId, std::unique_ptr<InternalBuffer>> mBuffers;
         std::set<BufferId> mFreeBuffers;
+        std::set<ConnectionId> mConnectionIds;
 
         struct Invalidation {
             static std::atomic<std::uint32_t> sInvSeqId;
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index 8e3852c..1dc676b 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -157,7 +157,7 @@
       mSentCodecSpecificData(false),
       mInputTimeSet(false),
       mInputSize(0),
-      mInputTimeUs(0),
+      mNextFrameTimestampUs(0),
       mSignalledError(false),
       mOutIndex(0u) {
 }
@@ -183,7 +183,7 @@
     mSentCodecSpecificData = false;
     mInputTimeSet = false;
     mInputSize = 0u;
-    mInputTimeUs = 0;
+    mNextFrameTimestampUs = 0;
     mSignalledError = false;
     return C2_OK;
 }
@@ -201,7 +201,7 @@
     mSentCodecSpecificData = false;
     mInputTimeSet = false;
     mInputSize = 0u;
-    mInputTimeUs = 0;
+    mNextFrameTimestampUs = 0;
     return C2_OK;
 }
 
@@ -365,17 +365,18 @@
         capacity = view.capacity();
     }
     if (!mInputTimeSet && capacity > 0) {
-        mInputTimeUs = work->input.ordinal.timestamp;
+        mNextFrameTimestampUs = work->input.ordinal.timestamp;
         mInputTimeSet = true;
     }
 
     size_t numFrames = (capacity + mInputSize + (eos ? mNumBytesPerInputFrame - 1 : 0))
             / mNumBytesPerInputFrame;
-    ALOGV("capacity = %zu; mInputSize = %zu; numFrames = %zu mNumBytesPerInputFrame = %u",
-          capacity, mInputSize, numFrames, mNumBytesPerInputFrame);
+    ALOGV("capacity = %zu; mInputSize = %zu; numFrames = %zu "
+          "mNumBytesPerInputFrame = %u inputTS = %lld",
+          capacity, mInputSize, numFrames,
+          mNumBytesPerInputFrame, work->input.ordinal.timestamp.peekll());
 
     std::shared_ptr<C2LinearBlock> block;
-    std::shared_ptr<C2Buffer> buffer;
     std::unique_ptr<C2WriteView> wView;
     uint8_t *outPtr = temp;
     size_t outAvailable = 0u;
@@ -442,7 +443,11 @@
         const std::shared_ptr<C2Buffer> mBuffer;
     };
 
-    C2WorkOrdinalStruct outOrdinal = work->input.ordinal;
+    struct OutputBuffer {
+        std::shared_ptr<C2Buffer> buffer;
+        c2_cntr64_t timestampUs;
+    };
+    std::list<OutputBuffer> outputBuffers;
 
     while (encoderErr == AACENC_OK && inargs.numInSamples > 0) {
         if (numFrames && !block) {
@@ -473,29 +478,22 @@
                                   &outargs);
 
         if (encoderErr == AACENC_OK) {
-            if (buffer) {
-                outOrdinal.frameIndex = mOutIndex++;
-                outOrdinal.timestamp = mInputTimeUs;
-                cloneAndSend(
-                        inputIndex,
-                        work,
-                        FillWork(C2FrameData::FLAG_INCOMPLETE, outOrdinal, buffer));
-                buffer.reset();
-            }
-
             if (outargs.numOutBytes > 0) {
                 mInputSize = 0;
                 int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples
                         + outargs.numInSamples;
-                mInputTimeUs = work->input.ordinal.timestamp
+                c2_cntr64_t currentFrameTimestampUs = mNextFrameTimestampUs;
+                mNextFrameTimestampUs = work->input.ordinal.timestamp
                         + (consumed * 1000000ll / channelCount / sampleRate);
-                buffer = createLinearBuffer(block, 0, outargs.numOutBytes);
+                std::shared_ptr<C2Buffer> buffer = createLinearBuffer(block, 0, outargs.numOutBytes);
 #if defined(LOG_NDEBUG) && !LOG_NDEBUG
                 hexdump(outPtr, std::min(outargs.numOutBytes, 256));
 #endif
                 outPtr = temp;
                 outAvailable = 0;
                 block.reset();
+
+                outputBuffers.push_back({buffer, currentFrameTimestampUs});
             } else {
                 mInputSize += outargs.numInSamples * sizeof(int16_t);
             }
@@ -506,8 +504,9 @@
                 inargs.numInSamples -= outargs.numInSamples;
             }
         }
-        ALOGV("encoderErr = %d mInputSize = %zu inargs.numInSamples = %d, mInputTimeUs = %lld",
-              encoderErr, mInputSize, inargs.numInSamples, mInputTimeUs.peekll());
+        ALOGV("encoderErr = %d mInputSize = %zu "
+              "inargs.numInSamples = %d, mNextFrameTimestampUs = %lld",
+              encoderErr, mInputSize, inargs.numInSamples, mNextFrameTimestampUs.peekll());
     }
 
     if (eos && inBufferSize[0] > 0) {
@@ -542,10 +541,27 @@
                            &outargs);
     }
 
-    outOrdinal.frameIndex = mOutIndex++;
-    outOrdinal.timestamp = mInputTimeUs;
+    while (outputBuffers.size() > 1) {
+        const OutputBuffer& front = outputBuffers.front();
+        C2WorkOrdinalStruct ordinal = work->input.ordinal;
+        ordinal.frameIndex = mOutIndex++;
+        ordinal.timestamp = front.timestampUs;
+        cloneAndSend(
+                inputIndex,
+                work,
+                FillWork(C2FrameData::FLAG_INCOMPLETE, ordinal, front.buffer));
+        outputBuffers.pop_front();
+    }
+    std::shared_ptr<C2Buffer> buffer;
+    C2WorkOrdinalStruct ordinal = work->input.ordinal;
+    ordinal.frameIndex = mOutIndex++;
+    if (!outputBuffers.empty()) {
+        ordinal.timestamp = outputBuffers.front().timestampUs;
+        buffer = outputBuffers.front().buffer;
+    }
+    // Mark the end of frame
     FillWork((C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0),
-             outOrdinal, buffer)(work);
+             ordinal, buffer)(work);
 }
 
 c2_status_t C2SoftAacEnc::drain(
@@ -569,7 +585,7 @@
     mSentCodecSpecificData = false;
     mInputTimeSet = false;
     mInputSize = 0u;
-    mInputTimeUs = 0;
+    mNextFrameTimestampUs = 0;
 
     // TODO: we don't have any pending work at this time to drain.
     return C2_OK;
diff --git a/media/codec2/components/aac/C2SoftAacEnc.h b/media/codec2/components/aac/C2SoftAacEnc.h
index a38be19..2655039 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.h
+++ b/media/codec2/components/aac/C2SoftAacEnc.h
@@ -56,7 +56,7 @@
     bool mSentCodecSpecificData;
     bool mInputTimeSet;
     size_t mInputSize;
-    c2_cntr64_t mInputTimeUs;
+    c2_cntr64_t mNextFrameTimestampUs;
 
     bool mSignalledError;
     std::atomic_uint64_t mOutIndex;
diff --git a/media/codec2/components/cmds/Android.bp b/media/codec2/components/cmds/Android.bp
index 35f689e..a081e28 100644
--- a/media/codec2/components/cmds/Android.bp
+++ b/media/codec2/components/cmds/Android.bp
@@ -9,10 +9,15 @@
     include_dirs: [
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
     shared_libs: [
         "libbase",
         "libbinder",
         "libcutils",
+        "libdatasource",
         "libgui",
         "liblog",
         "libstagefright",
diff --git a/media/codec2/components/cmds/codec2.cpp b/media/codec2/components/cmds/codec2.cpp
index f2cf545..38eaf88 100644
--- a/media/codec2/components/cmds/codec2.cpp
+++ b/media/codec2/components/cmds/codec2.cpp
@@ -30,15 +30,15 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaHTTPService.h>
 #include <media/MediaSource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaExtractorFactory.h>
@@ -418,7 +418,7 @@
         const char *filename = argv[k];
 
         sp<DataSource> dataSource =
-            DataSourceFactory::CreateFromURI(nullptr /* httpService */, filename);
+            DataSourceFactory::getInstance()->CreateFromURI(nullptr /* httpService */, filename);
 
         if (strncasecmp(filename, "sine:", 5) && dataSource == nullptr) {
             fprintf(stderr, "Unable to create data source.\n");
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index b129b1b..19ccbf9 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -42,6 +42,36 @@
 
 constexpr char COMPONENT_NAME[] = "c2.android.hevc.encoder";
 
+void ParseGop(
+        const C2StreamGopTuning::output &gop,
+        uint32_t *syncInterval, uint32_t *iInterval, uint32_t *maxBframes) {
+    uint32_t syncInt = 1;
+    uint32_t iInt = 1;
+    for (size_t i = 0; i < gop.flexCount(); ++i) {
+        const C2GopLayerStruct &layer = gop.m.values[i];
+        if (layer.count == UINT32_MAX) {
+            syncInt = 0;
+        } else if (syncInt <= UINT32_MAX / (layer.count + 1)) {
+            syncInt *= (layer.count + 1);
+        }
+        if ((layer.type_ & I_FRAME) == 0) {
+            if (layer.count == UINT32_MAX) {
+                iInt = 0;
+            } else if (iInt <= UINT32_MAX / (layer.count + 1)) {
+                iInt *= (layer.count + 1);
+            }
+        }
+        if (layer.type_ == C2Config::picture_type_t(P_FRAME | B_FRAME) && maxBframes) {
+            *maxBframes = layer.count;
+        }
+    }
+    if (syncInterval) {
+        *syncInterval = syncInt;
+    }
+    if (iInterval) {
+        *iInterval = iInt;
+    }
+}
 } // namepsace
 
 class C2SoftHevcEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -60,13 +90,21 @@
         setDerivedInstance(this);
 
         addParameter(
+                DefineParam(mGop, C2_PARAMKEY_GOP)
+                .withDefault(C2StreamGopTuning::output::AllocShared(
+                        0 /* flexCount */, 0u /* stream */))
+                .withFields({C2F(mGop, m.values[0].type_).any(),
+                             C2F(mGop, m.values[0].count).any()})
+                .withSetter(GopSetter)
+                .build());
+
+        addParameter(
                 DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY)
                 .withDefault(new C2PortActualDelayTuning::input(
                     DEFAULT_B_FRAMES + DEFAULT_RC_LOOKAHEAD))
                 .withFields({C2F(mActualInputDelay, value).inRange(
                     0, MAX_B_FRAMES + MAX_RC_LOOKAHEAD)})
-                .withSetter(
-                    Setter<decltype(*mActualInputDelay)>::StrictValueWithNoDeps)
+                .calculatedAs(InputDelaySetter, mGop)
                 .build());
 
         addParameter(
@@ -172,6 +210,17 @@
                 .build());
     }
 
+    static C2R InputDelaySetter(
+            bool mayBlock,
+            C2P<C2PortActualDelayTuning::input> &me,
+            const C2P<C2StreamGopTuning::output> &gop) {
+        (void)mayBlock;
+        uint32_t maxBframes = 0;
+        ParseGop(gop.v, nullptr, nullptr, &maxBframes);
+        me.set().value = maxBframes + DEFAULT_RC_LOOKAHEAD;
+        return C2R::Ok();
+    }
+
     static C2R BitrateSetter(bool mayBlock,
                              C2P<C2StreamBitrateInfo::output>& me) {
         (void)mayBlock;
@@ -270,6 +319,18 @@
         return C2R::Ok();
     }
 
+    static C2R GopSetter(bool mayBlock, C2P<C2StreamGopTuning::output> &me) {
+        (void)mayBlock;
+        for (size_t i = 0; i < me.v.flexCount(); ++i) {
+            const C2GopLayerStruct &layer = me.v.m.values[0];
+            if (layer.type_ == C2Config::picture_type_t(P_FRAME | B_FRAME)
+                    && layer.count > MAX_B_FRAMES) {
+                me.set().m.values[i].count = MAX_B_FRAMES;
+            }
+        }
+        return C2R::Ok();
+    }
+
     UWORD32 getProfile_l() const {
         switch (mProfileLevel->profile) {
         case PROFILE_HEVC_MAIN:  [[fallthrough]];
@@ -338,6 +399,9 @@
     std::shared_ptr<C2StreamQualityTuning::output> getQuality_l() const {
         return mQuality;
     }
+    std::shared_ptr<C2StreamGopTuning::output> getGop_l() const {
+        return mGop;
+    }
 
    private:
     std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -350,6 +414,7 @@
     std::shared_ptr<C2StreamQualityTuning::output> mQuality;
     std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
     std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
+    std::shared_ptr<C2StreamGopTuning::output> mGop;
 };
 
 static size_t GetCPUCoreCount() {
@@ -449,7 +514,25 @@
         ALOGE("HEVC default init failed : 0x%x", err);
         return C2_CORRUPTED;
     }
-
+    mBframes = 0;
+    if (mGop && mGop->flexCount() > 0) {
+        uint32_t syncInterval = 1;
+        uint32_t iInterval = 1;
+        uint32_t maxBframes = 0;
+        ParseGop(*mGop, &syncInterval, &iInterval, &maxBframes);
+        if (syncInterval > 0) {
+            ALOGD("Updating IDR interval from GOP: old %u new %u", mIDRInterval, syncInterval);
+            mIDRInterval = syncInterval;
+        }
+        if (iInterval > 0) {
+            ALOGD("Updating I interval from GOP: old %u new %u", mIInterval, iInterval);
+            mIInterval = iInterval;
+        }
+        if (mBframes != maxBframes) {
+            ALOGD("Updating max B frames from GOP: old %u new %u", mBframes, maxBframes);
+            mBframes = maxBframes;
+        }
+    }
     // update configuration
     mEncParams.s_src_prms.i4_width = mSize->width;
     mEncParams.s_src_prms.i4_height = mSize->height;
@@ -463,12 +546,20 @@
         mBitrate->value << 1;
     mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_codec_level = mHevcEncLevel;
     mEncParams.s_coding_tools_prms.i4_max_i_open_gop_period = mIDRInterval;
-    mEncParams.s_coding_tools_prms.i4_max_cra_open_gop_period = mIDRInterval;
+    mEncParams.s_coding_tools_prms.i4_max_cra_open_gop_period = mIInterval;
     mIvVideoColorFormat = IV_YUV_420P;
     mEncParams.s_multi_thrd_prms.i4_max_num_cores = mNumCores;
     mEncParams.s_out_strm_prms.i4_codec_profile = mHevcEncProfile;
     mEncParams.s_lap_prms.i4_rc_look_ahead_pics = DEFAULT_RC_LOOKAHEAD;
-    mEncParams.s_coding_tools_prms.i4_max_temporal_layers = DEFAULT_B_FRAMES;
+    if (mBframes == 0) {
+        mEncParams.s_coding_tools_prms.i4_max_temporal_layers = 0;
+    } else if (mBframes <= 2) {
+        mEncParams.s_coding_tools_prms.i4_max_temporal_layers = 1;
+    } else if (mBframes <= 6) {
+        mEncParams.s_coding_tools_prms.i4_max_temporal_layers = 2;
+    } else {
+        mEncParams.s_coding_tools_prms.i4_max_temporal_layers = 3;
+    }
 
     switch (mBitrateMode->value) {
         case C2Config::BITRATE_IGNORE:
@@ -523,6 +614,7 @@
 
 c2_status_t C2SoftHevcEnc::initEncoder() {
     CHECK(!mCodecCtx);
+
     {
         IntfImpl::Lock lock = mIntf->lock();
         mSize = mIntf->getSize_l();
@@ -532,8 +624,10 @@
         mHevcEncProfile = mIntf->getProfile_l();
         mHevcEncLevel = mIntf->getLevel_l();
         mIDRInterval = mIntf->getSyncFramePeriod_l();
+        mIInterval = mIntf->getSyncFramePeriod_l();
         mComplexity = mIntf->getComplexity_l();
         mQuality = mIntf->getQuality_l();
+        mGop = mIntf->getGop_l();
     }
 
     c2_status_t status = initEncParams();
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.h b/media/codec2/components/hevc/C2SoftHevcEnc.h
index f2c7642..140b4a9 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.h
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.h
@@ -67,6 +67,8 @@
     ihevce_static_cfg_params_t mEncParams;
     size_t mNumCores;
     UWORD32 mIDRInterval;
+    UWORD32 mIInterval;
+    UWORD32 mBframes;
     IV_COLOR_FORMAT_T mIvVideoColorFormat;
     UWORD32 mHevcEncProfile;
     UWORD32 mHevcEncLevel;
@@ -85,7 +87,7 @@
     std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
     std::shared_ptr<C2StreamComplexityTuning::output> mComplexity;
     std::shared_ptr<C2StreamQualityTuning::output> mQuality;
-
+    std::shared_ptr<C2StreamGopTuning::output> mGop;
 #ifdef FILE_DUMP_ENABLE
     char mInFile[200];
     char mOutFile[200];
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 9c84c71..ec576c9 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -22,6 +22,8 @@
 
     header_libs: [
         "libcodec2_internal",
+        "libmediadrm_headers",
+        "media_ndk_headers",
     ],
 
     shared_libs: [
@@ -39,7 +41,7 @@
         "libhidlallocatorutils",
         "libhidlbase",
         "liblog",
-        "libmedia",
+        "libmedia_codeclist",
         "libmedia_omx",
         "libsfplugin_ccodec_utils",
         "libstagefright_bufferqueue_helper",
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 9d1cc60..8223273 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -375,7 +375,11 @@
 
         // consumer usage is queried earlier.
 
-        ALOGD("ISConfig%s", status.str().c_str());
+        if (status.str().empty()) {
+            ALOGD("ISConfig not changed");
+        } else {
+            ALOGD("ISConfig%s", status.str().c_str());
+        }
         return err;
     }
 
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 8308292..0cbf62b 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -224,7 +224,7 @@
       mFirstValidFrameIndex(0u),
       mMetaMode(MODE_NONE),
       mInputMetEos(false) {
-    mOutputSurface.lock()->maxDequeueBuffers = kSmoothnessFactor + kRenderingDepth;
+    mOutputSurface.lock()->maxDequeueBuffers = 2 * kSmoothnessFactor + kRenderingDepth;
     {
         Mutexed<Input>::Locked input(mInput);
         input->buffers.reset(new DummyInputBuffers(""));
@@ -948,7 +948,8 @@
         uint32_t outputGeneration;
         {
             Mutexed<OutputSurface>::Locked output(mOutputSurface);
-            output->maxDequeueBuffers = numOutputSlots + reorderDepth.value + kRenderingDepth;
+            output->maxDequeueBuffers = numOutputSlots + numInputSlots +
+                    reorderDepth.value + kRenderingDepth;
             outputSurface = output->surface ?
                     output->surface->getIGraphicBufferProducer() : nullptr;
             if (outputSurface) {
@@ -1332,9 +1333,10 @@
                     ALOGV("[%s] onWorkDone: updated reorder depth to %u",
                           mName, reorderDepth.value);
                     size_t numOutputSlots = mOutput.lock()->numSlots;
+                    size_t numInputSlots = mInput.lock()->numSlots;
                     Mutexed<OutputSurface>::Locked output(mOutputSurface);
-                    output->maxDequeueBuffers =
-                        numOutputSlots + reorderDepth.value + kRenderingDepth;
+                    output->maxDequeueBuffers = numOutputSlots + numInputSlots +
+                            reorderDepth.value + kRenderingDepth;
                     if (output->surface) {
                         output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
                     }
@@ -1382,6 +1384,7 @@
 
                         bool outputBuffersChanged = false;
                         size_t numOutputSlots = 0;
+                        size_t numInputSlots = mInput.lock()->numSlots;
                         {
                             Mutexed<Output>::Locked output(mOutput);
                             output->outputDelay = outputDelay.value;
@@ -1406,7 +1409,8 @@
 
                         uint32_t depth = mReorderStash.lock()->depth();
                         Mutexed<OutputSurface>::Locked output(mOutputSurface);
-                        output->maxDequeueBuffers = numOutputSlots + depth + kRenderingDepth;
+                        output->maxDequeueBuffers = numOutputSlots + numInputSlots +
+                                depth + kRenderingDepth;
                         if (output->surface) {
                             output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
                         }
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index ee3455d..c0fa138 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -29,7 +29,6 @@
 #include <codec2/hidl/client.h>
 #include <media/stagefright/foundation/Mutexed.h>
 #include <media/stagefright/CodecBase.h>
-#include <media/ICrypto.h>
 
 #include "CCodecBuffers.h"
 #include "InputSurfaceWrapper.h"
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 26c702d..ed8b832 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -878,9 +878,10 @@
     switch (c2buffer->data().type()) {
         case C2BufferData::LINEAR: {
             uint32_t size = kLinearBufferSize;
-            const C2ConstLinearBlock &block = c2buffer->data().linearBlocks().front();
-            if (block.size() < kMaxLinearBufferSize / 2) {
-                size = block.size() * 2;
+            const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks();
+            const uint32_t block_size = linear_blocks.front().size();
+            if (block_size < kMaxLinearBufferSize / 2) {
+                size = block_size * 2;
             } else {
                 size = kMaxLinearBufferSize;
             }
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 1cfdc19..5adcd94 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -235,7 +235,10 @@
     const std::vector<ConfigMapper> &getConfigMappersForSdkKey(std::string key) const {
         auto it = mConfigMappers.find(key);
         if (it == mConfigMappers.end()) {
-            ALOGD("no c2 equivalents for %s", key.c_str());
+            if (mComplained.count(key) == 0) {
+                ALOGD("no c2 equivalents for %s", key.c_str());
+                mComplained.insert(key);
+            }
             return NO_MAPPERS;
         }
         ALOGV("found %zu eqs for %s", it->second.size(), key.c_str());
@@ -304,6 +307,7 @@
 
 private:
     std::map<SdkKey, std::vector<ConfigMapper>> mConfigMappers;
+    mutable std::set<std::string> mComplained;
 };
 
 const std::vector<ConfigMapper> StandardParams::NO_MAPPERS;
@@ -508,7 +512,8 @@
                .limitTo(D::ENCODER & D::VIDEO));
     // convert to timestamp base
     add(ConfigMapper(KEY_I_FRAME_INTERVAL, C2_PARAMKEY_SYNC_FRAME_INTERVAL, "value")
-        .withMappers([](C2Value v) -> C2Value {
+        .limitTo(D::VIDEO & D::ENCODER & D::CONFIG)
+        .withMapper([](C2Value v) -> C2Value {
             // convert from i32 to float
             int32_t i32Value;
             float fpValue;
@@ -518,12 +523,6 @@
                 return int64_t(c2_min(1000000 * fpValue + 0.5, (double)INT64_MAX));
             }
             return C2Value();
-        }, [](C2Value v) -> C2Value {
-            int64_t i64;
-            if (v.get(&i64)) {
-                return float(i64) / 1000000;
-            }
-            return C2Value();
         }));
     // remove when codecs switch to proper coding.gop (add support for calculating gop)
     deprecated(ConfigMapper("i-frame-period", "coding.gop", "intra-period")
@@ -1033,7 +1032,25 @@
     }
 
     ReflectedParamUpdater::Dict reflected = mParamUpdater->getParams(paramPointers);
-    ALOGD("c2 config is %s", reflected.debugString().c_str());
+    std::string config = reflected.debugString();
+    std::set<std::string> configLines;
+    std::string diff;
+    for (size_t start = 0; start != std::string::npos; ) {
+        size_t end = config.find('\n', start);
+        size_t count = (end == std::string::npos)
+                ? std::string::npos
+                : end - start + 1;
+        std::string line = config.substr(start, count);
+        configLines.insert(line);
+        if (mLastConfig.count(line) == 0) {
+            diff.append(line);
+        }
+        start = (end == std::string::npos) ? std::string::npos : end + 1;
+    }
+    if (!diff.empty()) {
+        ALOGD("c2 config diff is %s", diff.c_str());
+    }
+    mLastConfig.swap(configLines);
 
     bool changed = false;
     if (domain & mInputDomain) {
diff --git a/media/codec2/sfplugin/CCodecConfig.h b/media/codec2/sfplugin/CCodecConfig.h
index 3bafe3f..a61c8b7 100644
--- a/media/codec2/sfplugin/CCodecConfig.h
+++ b/media/codec2/sfplugin/CCodecConfig.h
@@ -134,6 +134,8 @@
     /// For now support a validation function.
     std::map<C2Param::Index, LocalParamValidator> mLocalParams;
 
+    std::set<std::string> mLastConfig;
+
     CCodecConfig();
 
     /// initializes the members required to manage the format: descriptors, reflector,
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index 36dcab9..6f87101 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -25,7 +25,7 @@
 #include <media/hardware/VideoAPI.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/MediaCodecBuffer.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 
 namespace android {
 
diff --git a/media/codec2/sfplugin/PipelineWatcher.cpp b/media/codec2/sfplugin/PipelineWatcher.cpp
index 74d14e8..0ee9056 100644
--- a/media/codec2/sfplugin/PipelineWatcher.cpp
+++ b/media/codec2/sfplugin/PipelineWatcher.cpp
@@ -146,7 +146,7 @@
               std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count());
         durations.push_back(elapsed);
     }
-    std::nth_element(durations.begin(), durations.end(), durations.begin() + n,
+    std::nth_element(durations.begin(), durations.begin() + n, durations.end(),
                      std::greater<Clock::duration>());
     return durations[n];
 }
diff --git a/media/codec2/sfplugin/tests/Android.bp b/media/codec2/sfplugin/tests/Android.bp
index be7f55c..b6eb2b4 100644
--- a/media/codec2/sfplugin/tests/Android.bp
+++ b/media/codec2/sfplugin/tests/Android.bp
@@ -33,6 +33,10 @@
         "frameworks/av/media/codec2/sfplugin",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
     shared_libs: [
         "libbinder",
         "libcodec2",
diff --git a/media/codec2/sfplugin/tests/MediaCodec_sanity_test.cpp b/media/codec2/sfplugin/tests/MediaCodec_sanity_test.cpp
index ba3687b..6deede0 100644
--- a/media/codec2/sfplugin/tests/MediaCodec_sanity_test.cpp
+++ b/media/codec2/sfplugin/tests/MediaCodec_sanity_test.cpp
@@ -21,7 +21,7 @@
 #include <binder/ProcessState.h>
 #include <gtest/gtest.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/hardware/VideoAPI.h>
 #include <media/stagefright/MediaCodec.h>
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index 5a73d20..223d359 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -17,7 +17,6 @@
 #ifndef FLAC_EXTRACTOR_H_
 #define FLAC_EXTRACTOR_H_
 
-#include <media/DataSourceBase.h>
 #include <media/MediaExtractorPluginApi.h>
 #include <media/MediaExtractorPluginHelper.h>
 #include <media/NdkMediaFormat.h>
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index 7d42e70..d36cb49 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -6,6 +6,10 @@
         "frameworks/av/media/libstagefright/include",
     ],
 
+    header_libs: [
+        "libmedia_headers",
+    ],
+
     shared_libs: [
         "liblog",
         "libmediandk",
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 2e78086..b486fc6 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -17,7 +17,6 @@
 #ifndef MIDI_EXTRACTOR_H_
 #define MIDI_EXTRACTOR_H_
 
-#include <media/DataSourceBase.h>
 #include <media/MediaExtractorPluginApi.h>
 #include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MediaBufferBase.h>
diff --git a/media/extractors/mp4/SampleIterator.cpp b/media/extractors/mp4/SampleIterator.cpp
index 2890b26..85fbf97 100644
--- a/media/extractors/mp4/SampleIterator.cpp
+++ b/media/extractors/mp4/SampleIterator.cpp
@@ -22,7 +22,6 @@
 
 #include <arpa/inet.h>
 
-#include <media/DataSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 
@@ -355,7 +354,7 @@
     if (offset > 0) {
         *time += offset;
     } else {
-        *time -= (offset == INT64_MIN ? INT64_MAX : (-offset));
+        *time -= (offset == INT32_MIN ? INT64_MAX : (-offset));
     }
 
     *duration = mTTSDuration;
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 0f0c72c..1d9e1e6 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -16,6 +16,7 @@
         "android.hardware.cas.native@1.0",
         "android.hidl.token@1.0-utils",
         "android.hidl.allocator@1.0",
+        "libcrypto",
         "libhidlmemory",
         "libhidlbase",
         "liblog",
@@ -23,13 +24,13 @@
     ],
 
     header_libs: [
+        "libaudioclient_headers",
         "libbase_headers",
         "libstagefright_headers",
         "libmedia_headers",
     ],
 
     static_libs: [
-        "libcrypto",
         "libstagefright_foundation_without_imemory",
         "libstagefright_mpeg2support",
         "libutils",
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index 731584d..002a855 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -23,7 +23,6 @@
 #include "mpeg2ts/AnotherPacketSource.h"
 #include "mpeg2ts/ESQueue.h"
 
-#include <media/DataSourceBase.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -111,8 +110,10 @@
     AMediaFormat *meta = AMediaFormat_new();
     for (size_t i = mTracks.size(); i > 0;) {
         i--;
-        if (mTracks.valueAt(i)->getFormat(meta) != AMEDIA_OK) {
+        Track *track = mTracks.valueAt(i);
+        if (track->getFormat(meta) != AMEDIA_OK) {
             mTracks.removeItemsAt(i);
+            delete track;
         }
     }
     AMediaFormat_delete(meta);
@@ -122,6 +123,10 @@
 
 MPEG2PSExtractor::~MPEG2PSExtractor() {
     delete mDataSource;
+    for (size_t i = mTracks.size(); i > 0;) {
+        i--;
+        delete mTracks.valueAt(i);
+    }
 }
 
 size_t MPEG2PSExtractor::countTracks() {
@@ -793,7 +798,9 @@
 }
 
 media_status_t MPEG2PSExtractor::WrappedTrack::start() {
+    delete mTrack->mBufferGroup;
     mTrack->mBufferGroup = mBufferGroup;
+    mBufferGroup = nullptr;
     return mTrack->start();
 }
 
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index 56c0170..850b1d0 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -10,7 +10,9 @@
         "legacy",
         "utility",
     ],
-    header_libs: ["libaaudio_headers"],
+    header_libs: [
+        "libaaudio_headers",
+    ],
     export_header_lib_headers: ["libaaudio_headers"],
     version_script: "libaaudio.map.txt",
 
@@ -53,7 +55,10 @@
     ],
 
     export_include_dirs: ["."],
-    header_libs: ["libaaudio_headers"],
+    header_libs: [
+        "libaaudio_headers",
+        "libmedia_headers"
+    ],
     export_header_lib_headers: ["libaaudio_headers"],
 
     shared_libs: [
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 52eadd4..fb276c2 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -36,6 +36,7 @@
 #include "binding/AAudioStreamConfiguration.h"
 #include "binding/IAAudioService.h"
 #include "binding/AAudioServiceMessage.h"
+#include "core/AudioGlobal.h"
 #include "core/AudioStreamBuilder.h"
 #include "fifo/FifoBuffer.h"
 #include "utility/AudioClock.h"
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index a6cc45b..366cc87 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -89,7 +89,11 @@
     if (mAudioEndpoint.isFreeRunning()) {
         //ALOGD("AudioStreamInternalCapture::processDataNow() - update remote counter");
         // Update data queue based on the timing model.
-        int64_t estimatedRemoteCounter = mClockModel.convertTimeToPosition(currentNanoTime);
+        // Jitter in the DSP can cause late writes to the FIFO.
+        // This might be caused by resampling.
+        // We want to read the FIFO after the latest possible time
+        // that the DSP could have written the data.
+        int64_t estimatedRemoteCounter = mClockModel.convertLatestTimeToPosition(currentNanoTime);
         // TODO refactor, maybe use setRemoteCounter()
         mAudioEndpoint.setDataWriteCounter(estimatedRemoteCounter);
     }
@@ -139,7 +143,7 @@
                 // the writeCounter might have just advanced in the background,
                 // causing us to sleep until a later burst.
                 int64_t nextPosition = mAudioEndpoint.getDataReadCounter() + mFramesPerBurst;
-                wakeTime = mClockModel.convertPositionToTime(nextPosition);
+                wakeTime = mClockModel.convertPositionToLatestTime(nextPosition);
             }
                 break;
             default:
diff --git a/media/libaaudio/src/client/IsochronousClockModel.cpp b/media/libaaudio/src/client/IsochronousClockModel.cpp
index 747d0e1..9abdf53 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.cpp
+++ b/media/libaaudio/src/client/IsochronousClockModel.cpp
@@ -19,12 +19,11 @@
 #include <log/log.h>
 
 #include <stdint.h>
+#include <algorithm>
 
 #include "utility/AudioClock.h"
 #include "IsochronousClockModel.h"
 
-#define MIN_LATENESS_NANOS (10 * AAUDIO_NANOS_PER_MICROSECOND)
-
 using namespace aaudio;
 
 IsochronousClockModel::IsochronousClockModel()
@@ -32,7 +31,7 @@
         , mMarkerNanoTime(0)
         , mSampleRate(48000)
         , mFramesPerBurst(64)
-        , mMaxLatenessInNanos(0)
+        , mMaxMeasuredLatenessNanos(0)
         , mState(STATE_STOPPED)
 {
 }
@@ -41,8 +40,7 @@
 }
 
 void IsochronousClockModel::setPositionAndTime(int64_t framePosition, int64_t nanoTime) {
-    ALOGV("setPositionAndTime(%lld, %lld)",
-          (long long) framePosition, (long long) nanoTime);
+    ALOGV("setPositionAndTime, %lld, %lld", (long long) framePosition, (long long) nanoTime);
     mMarkerFramePosition = framePosition;
     mMarkerNanoTime = nanoTime;
 }
@@ -54,7 +52,9 @@
 }
 
 void IsochronousClockModel::stop(int64_t nanoTime) {
-    ALOGV("stop(nanos = %lld)\n", (long long) nanoTime);
+    ALOGD("stop(nanos = %lld) max lateness = %d micros\n",
+        (long long) nanoTime,
+        (int) (mMaxMeasuredLatenessNanos / 1000));
     setPositionAndTime(convertTimeToPosition(nanoTime), nanoTime);
     // TODO should we set position?
     mState = STATE_STOPPED;
@@ -69,9 +69,10 @@
 }
 
 void IsochronousClockModel::processTimestamp(int64_t framePosition, int64_t nanoTime) {
-//    ALOGD("processTimestamp() - framePosition = %lld at nanoTime %llu",
-//         (long long)framePosition,
-//         (long long)nanoTime);
+    mTimestampCount++;
+// Log position and time in CSV format so we can import it easily into spreadsheets.
+    //ALOGD("%s() CSV, %d, %lld, %lld", __func__,
+          //mTimestampCount, (long long)framePosition, (long long)nanoTime);
     int64_t framesDelta = framePosition - mMarkerFramePosition;
     int64_t nanosDelta = nanoTime - mMarkerNanoTime;
     if (nanosDelta < 1000) {
@@ -108,17 +109,56 @@
     case STATE_RUNNING:
         if (nanosDelta < expectedNanosDelta) {
             // Earlier than expected timestamp.
-            // This data is probably more accurate so use it.
-            // or we may be drifting due to a slow HW clock.
-//            ALOGD("processTimestamp() - STATE_RUNNING - %d < %d micros - EARLY",
-//                 (int) (nanosDelta / 1000), (int)(expectedNanosDelta / 1000));
+            // This data is probably more accurate, so use it.
+            // Or we may be drifting due to a fast HW clock.
+            //int microsDelta = (int) (nanosDelta / 1000);
+            //int expectedMicrosDelta = (int) (expectedNanosDelta / 1000);
+            //ALOGD("%s() - STATE_RUNNING - #%d, %4d micros EARLY",
+                //__func__, mTimestampCount, expectedMicrosDelta - microsDelta);
+
             setPositionAndTime(framePosition, nanoTime);
-        } else if (nanosDelta > (expectedNanosDelta + mMaxLatenessInNanos)) {
-            // Later than expected timestamp.
-//            ALOGD("processTimestamp() - STATE_RUNNING - %d > %d + %d micros - LATE",
-//                 (int) (nanosDelta / 1000), (int)(expectedNanosDelta / 1000),
-//                 (int) (mMaxLatenessInNanos / 1000));
-            setPositionAndTime(framePosition - mFramesPerBurst,  nanoTime - mMaxLatenessInNanos);
+        } else if (nanosDelta > (expectedNanosDelta + (2 * mBurstPeriodNanos))) {
+            // In this case we do not update mMaxMeasuredLatenessNanos because it
+            // would force it too high.
+            // mMaxMeasuredLatenessNanos should range from 1 to 2 * mBurstPeriodNanos
+            //int32_t measuredLatenessNanos = (int32_t)(nanosDelta - expectedNanosDelta);
+            //ALOGD("%s() - STATE_RUNNING - #%d, lateness %d - max %d = %4d micros VERY LATE",
+                  //__func__,
+                  //mTimestampCount,
+                  //measuredLatenessNanos / 1000,
+                  //mMaxMeasuredLatenessNanos / 1000,
+                  //(measuredLatenessNanos - mMaxMeasuredLatenessNanos) / 1000
+                  //);
+
+            // This typically happens when we are modelling a service instead of a DSP.
+            setPositionAndTime(framePosition,  nanoTime - (2 * mBurstPeriodNanos));
+        } else if (nanosDelta > (expectedNanosDelta + mMaxMeasuredLatenessNanos)) {
+            //int32_t previousLatenessNanos = mMaxMeasuredLatenessNanos;
+            mMaxMeasuredLatenessNanos = (int32_t)(nanosDelta - expectedNanosDelta);
+
+            //ALOGD("%s() - STATE_RUNNING - #%d, newmax %d - oldmax %d = %4d micros LATE",
+                  //__func__,
+                  //mTimestampCount,
+                  //mMaxMeasuredLatenessNanos / 1000,
+                  //previousLatenessNanos / 1000,
+                  //(mMaxMeasuredLatenessNanos - previousLatenessNanos) / 1000
+                  //);
+
+            // When we are late, it may be because of preemption in the kernel,
+            // or timing jitter caused by resampling in the DSP,
+            // or we may be drifting due to a slow HW clock.
+            // We add slight drift value just in case there is actual long term drift
+            // forward caused by a slower clock.
+            // If the clock is faster than the model will get pushed earlier
+            // by the code in the preceding branch.
+            // The two opposing forces should allow the model to track the real clock
+            // over a long time.
+            int64_t driftingTime = mMarkerNanoTime + expectedNanosDelta + kDriftNanos;
+            setPositionAndTime(framePosition,  driftingTime);
+            //ALOGD("%s() - #%d, max lateness = %d micros",
+                  //__func__,
+                  //mTimestampCount,
+                  //(int) (mMaxMeasuredLatenessNanos / 1000));
         }
         break;
     default:
@@ -138,9 +178,12 @@
     update();
 }
 
+// Update expected lateness based on sampleRate and framesPerBurst
 void IsochronousClockModel::update() {
-    int64_t nanosLate = convertDeltaPositionToTime(mFramesPerBurst); // uses mSampleRate
-    mMaxLatenessInNanos = (nanosLate > MIN_LATENESS_NANOS) ? nanosLate : MIN_LATENESS_NANOS;
+    mBurstPeriodNanos = convertDeltaPositionToTime(mFramesPerBurst); // uses mSampleRate
+    // Timestamps may be late by up to a burst because we are randomly sampling the time period
+    // after the DSP position is actually updated.
+    mMaxMeasuredLatenessNanos = mBurstPeriodNanos;
 }
 
 int64_t IsochronousClockModel::convertDeltaPositionToTime(int64_t framesDelta) const {
@@ -183,11 +226,25 @@
     return position;
 }
 
+int32_t IsochronousClockModel::getLateTimeOffsetNanos() const {
+    // This will never be < 0 because mMaxLatenessNanos starts at
+    // mBurstPeriodNanos and only gets bigger.
+    return (mMaxMeasuredLatenessNanos - mBurstPeriodNanos) + kExtraLatenessNanos;
+}
+
+int64_t IsochronousClockModel::convertPositionToLatestTime(int64_t framePosition) const {
+    return convertPositionToTime(framePosition) + getLateTimeOffsetNanos();
+}
+
+int64_t IsochronousClockModel::convertLatestTimeToPosition(int64_t nanoTime) const {
+    return convertTimeToPosition(nanoTime - getLateTimeOffsetNanos());
+}
+
 void IsochronousClockModel::dump() const {
     ALOGD("mMarkerFramePosition = %lld", (long long) mMarkerFramePosition);
     ALOGD("mMarkerNanoTime      = %lld", (long long) mMarkerNanoTime);
     ALOGD("mSampleRate          = %6d", mSampleRate);
     ALOGD("mFramesPerBurst      = %6d", mFramesPerBurst);
-    ALOGD("mMaxLatenessInNanos  = %6d", mMaxLatenessInNanos);
+    ALOGD("mMaxMeasuredLatenessNanos = %6d", mMaxMeasuredLatenessNanos);
     ALOGD("mState               = %6d", mState);
 }
diff --git a/media/libaaudio/src/client/IsochronousClockModel.h b/media/libaaudio/src/client/IsochronousClockModel.h
index 46ca48e..582bf4e 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.h
+++ b/media/libaaudio/src/client/IsochronousClockModel.h
@@ -18,6 +18,7 @@
 #define ANDROID_AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
 
 #include <stdint.h>
+#include "utility/AudioClock.h"
 
 namespace aaudio {
 
@@ -79,6 +80,15 @@
     int64_t convertPositionToTime(int64_t framePosition) const;
 
     /**
+     * Calculate the latest estimated time that the stream will be at that position.
+     * The more jittery the clock is then the later this will be.
+     *
+     * @param framePosition
+     * @return time in nanoseconds
+     */
+    int64_t convertPositionToLatestTime(int64_t framePosition) const;
+
+    /**
      * Calculate an estimated position where the stream will be at the specified time.
      *
      * @param nanoTime time of interest
@@ -87,6 +97,18 @@
     int64_t convertTimeToPosition(int64_t nanoTime) const;
 
     /**
+     * Calculate the corresponding estimated position based on the specified time being
+     * the latest possible time.
+     *
+     * For the same nanoTime, this may return an earlier position than
+     * convertTimeToPosition().
+     *
+     * @param nanoTime
+     * @return position in frames
+     */
+    int64_t convertLatestTimeToPosition(int64_t nanoTime) const;
+
+    /**
      * @param framesDelta difference in frames
      * @return duration in nanoseconds
      */
@@ -101,6 +123,9 @@
     void dump() const;
 
 private:
+
+    int32_t getLateTimeOffsetNanos() const;
+
     enum clock_model_state_t {
         STATE_STOPPED,
         STATE_STARTING,
@@ -108,13 +133,23 @@
         STATE_RUNNING
     };
 
+    // Amount of time to drift forward when we get a late timestamp.
+    // This value was calculated to allow tracking of a clock with 50 ppm error.
+    static constexpr int32_t   kDriftNanos         =  10 * 1000;
+    // TODO review value of kExtraLatenessNanos
+    static constexpr int32_t   kExtraLatenessNanos = 100 * 1000;
+
     int64_t             mMarkerFramePosition;
     int64_t             mMarkerNanoTime;
     int32_t             mSampleRate;
     int32_t             mFramesPerBurst;
-    int32_t             mMaxLatenessInNanos;
+    int32_t             mBurstPeriodNanos;
+    // Includes mBurstPeriodNanos because we sample randomly over time.
+    int32_t             mMaxMeasuredLatenessNanos;
     clock_model_state_t mState;
 
+    int32_t             mTimestampCount = 0;
+
     void update();
 };
 
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index c516d20..32904bb 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -84,6 +84,7 @@
     header_libs: [
         "libaudioclient_headers",
         "libbase_headers",
+        "libmedia_headers",
     ],
     export_header_lib_headers: ["libaudioclient_headers"],
 
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index dd95e34..e3e64af 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -24,8 +24,8 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
-#include <media/TimeCheck.h>
 #include <mediautils/ServiceUtilities.h>
+#include <mediautils/TimeCheck.h>
 #include "IAudioFlinger.h"
 
 namespace android {
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 64f0aca..7cc95e5 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -26,8 +26,8 @@
 #include <binder/Parcel.h>
 #include <media/AudioEffect.h>
 #include <media/IAudioPolicyService.h>
-#include <media/TimeCheck.h>
 #include <mediautils/ServiceUtilities.h>
+#include <mediautils/TimeCheck.h>
 #include <system/audio.h>
 
 namespace android {
diff --git a/media/libaudioclient/include/media/AudioMixer.h b/media/libaudioclient/include/media/AudioMixer.h
index 783eef3..3f7cd48 100644
--- a/media/libaudioclient/include/media/AudioMixer.h
+++ b/media/libaudioclient/include/media/AudioMixer.h
@@ -18,87 +18,38 @@
 #ifndef ANDROID_AUDIO_MIXER_H
 #define ANDROID_AUDIO_MIXER_H
 
-#include <map>
 #include <pthread.h>
-#include <sstream>
 #include <stdint.h>
 #include <sys/types.h>
-#include <unordered_map>
-#include <vector>
 
 #include <android/os/IExternalVibratorService.h>
-#include <media/AudioBufferProvider.h>
-#include <media/AudioResampler.h>
-#include <media/AudioResamplerPublic.h>
+#include <media/AudioMixerBase.h>
 #include <media/BufferProviders.h>
-#include <system/audio.h>
-#include <utils/Compat.h>
 #include <utils/threads.h>
 
 // FIXME This is actually unity gain, which might not be max in future, expressed in U.12
-#define MAX_GAIN_INT AudioMixer::UNITY_GAIN_INT
-
-// This must match frameworks/av/services/audioflinger/Configuration.h
-#define FLOAT_AUX
+#define MAX_GAIN_INT AudioMixerBase::UNITY_GAIN_INT
 
 namespace android {
 
-namespace NBLog {
-class Writer;
-}   // namespace NBLog
-
 // ----------------------------------------------------------------------------
 
-class AudioMixer
+// AudioMixer extends AudioMixerBase by adding support for down- and up-mixing
+// and time stretch that are implemented via Effects HAL, and adding support
+// for haptic channels which depends on Vibrator service. This is the version
+// that is used by Audioflinger.
+
+class AudioMixer : public AudioMixerBase
 {
 public:
-    // Do not change these unless underlying code changes.
-    // This mixer has a hard-coded upper limit of 8 channels for output.
-    static constexpr uint32_t MAX_NUM_CHANNELS = FCC_8;
-    static constexpr uint32_t MAX_NUM_VOLUMES = FCC_2; // stereo volume only
     // maximum number of channels supported for the content
     static const uint32_t MAX_NUM_CHANNELS_TO_DOWNMIX = AUDIO_CHANNEL_COUNT_MAX;
 
-    static const uint16_t UNITY_GAIN_INT = 0x1000;
-    static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
-
-    enum { // names
-        // setParameter targets
-        TRACK           = 0x3000,
-        RESAMPLE        = 0x3001,
-        RAMP_VOLUME     = 0x3002, // ramp to new volume
-        VOLUME          = 0x3003, // don't ramp
-        TIMESTRETCH     = 0x3004,
-
-        // set Parameter names
-        // for target TRACK
-        CHANNEL_MASK    = 0x4000,
-        FORMAT          = 0x4001,
-        MAIN_BUFFER     = 0x4002,
-        AUX_BUFFER      = 0x4003,
-        DOWNMIX_TYPE    = 0X4004,
-        MIXER_FORMAT    = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
-        MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output
+    enum { // extension of AudioMixerBase parameters
+        DOWNMIX_TYPE    = 0x4004,
         // for haptic
         HAPTIC_ENABLED  = 0x4007, // Set haptic data from this track should be played or not.
         HAPTIC_INTENSITY = 0x4008, // Set the intensity to play haptic data.
-        // for target RESAMPLE
-        SAMPLE_RATE     = 0x4100, // Configure sample rate conversion on this track name;
-                                  // parameter 'value' is the new sample rate in Hz.
-                                  // Only creates a sample rate converter the first time that
-                                  // the track sample rate is different from the mix sample rate.
-                                  // If the new sample rate is the same as the mix sample rate,
-                                  // and a sample rate converter already exists,
-                                  // then the sample rate converter remains present but is a no-op.
-        RESET           = 0x4101, // Reset sample rate converter without changing sample rate.
-                                  // This clears out the resampler's input buffer.
-        REMOVE          = 0x4102, // Remove the sample rate converter on this track name;
-                                  // the track is restored to the mix sample rate.
-        // for target RAMP_VOLUME and VOLUME (8 channels max)
-        // FIXME use float for these 3 to improve the dynamic range
-        VOLUME0         = 0x4200,
-        VOLUME1         = 0x4201,
-        AUXLEVEL        = 0x4210,
         // for target TIMESTRETCH
         PLAYBACK_RATE   = 0x4300, // Configure timestretch on this track name;
                                   // parameter 'value' is a pointer to the new playback rate.
@@ -131,142 +82,23 @@
     }
 
     AudioMixer(size_t frameCount, uint32_t sampleRate)
-        : mSampleRate(sampleRate)
-        , mFrameCount(frameCount) {
+            : AudioMixerBase(frameCount, sampleRate) {
         pthread_once(&sOnceControl, &sInitRoutine);
     }
 
-    // Create a new track in the mixer.
-    //
-    // \param name        a unique user-provided integer associated with the track.
-    //                    If name already exists, the function will abort.
-    // \param channelMask output channel mask.
-    // \param format      PCM format
-    // \param sessionId   Session id for the track. Tracks with the same
-    //                    session id will be submixed together.
-    //
-    // \return OK        on success.
-    //         BAD_VALUE if the format does not satisfy isValidFormat()
-    //                   or the channelMask does not satisfy isValidChannelMask().
-    status_t    create(
-            int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId);
+    bool isValidChannelMask(audio_channel_mask_t channelMask) const override;
 
-    bool        exists(int name) const {
-        return mTracks.count(name) > 0;
-    }
-
-    // Free an allocated track by name.
-    void        destroy(int name);
-
-    // Enable or disable an allocated track by name
-    void        enable(int name);
-    void        disable(int name);
-
-    void        setParameter(int name, int target, int param, void *value);
-
-    void        setBufferProvider(int name, AudioBufferProvider* bufferProvider);
-
-    void        process() {
-        for (const auto &pair : mTracks) {
-            // Clear contracted buffer before processing if contracted channels are saved
-            const std::shared_ptr<Track> &t = pair.second;
-            if (t->mKeepContractedChannels) {
-                t->clearContractedBuffer();
-            }
-        }
-        (this->*mHook)();
-        processHapticData();
-    }
-
-    size_t      getUnreleasedFrames(int name) const;
-
-    std::string trackNames() const {
-        std::stringstream ss;
-        for (const auto &pair : mTracks) {
-            ss << pair.first << " ";
-        }
-        return ss.str();
-    }
-
-    void        setNBLogWriter(NBLog::Writer *logWriter) {
-        mNBLogWriter = logWriter;
-    }
-
-    static inline bool isValidFormat(audio_format_t format) {
-        switch (format) {
-        case AUDIO_FORMAT_PCM_8_BIT:
-        case AUDIO_FORMAT_PCM_16_BIT:
-        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
-        case AUDIO_FORMAT_PCM_32_BIT:
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return true;
-        default:
-            return false;
-        }
-    }
-
-    static inline bool isValidChannelMask(audio_channel_mask_t channelMask) {
-        return audio_channel_mask_is_valid(channelMask); // the RemixBufferProvider is flexible.
-    }
+    void setParameter(int name, int target, int param, void *value) override;
+    void setBufferProvider(int name, AudioBufferProvider* bufferProvider);
 
 private:
 
-    /* For multi-format functions (calls template functions
-     * in AudioMixerOps.h).  The template parameters are as follows:
-     *
-     *   MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
-     *   USEFLOATVOL (set to true if float volume is used)
-     *   ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
-     *   TO: int32_t (Q4.27) or float
-     *   TI: int32_t (Q4.27) or int16_t (Q0.15) or float
-     *   TA: int32_t (Q4.27)
-     */
-
-    enum {
-        // FIXME this representation permits up to 8 channels
-        NEEDS_CHANNEL_COUNT__MASK   = 0x00000007,
-    };
-
-    enum {
-        NEEDS_CHANNEL_1             = 0x00000000,   // mono
-        NEEDS_CHANNEL_2             = 0x00000001,   // stereo
-
-        // sample format is not explicitly specified, and is assumed to be AUDIO_FORMAT_PCM_16_BIT
-
-        NEEDS_MUTE                  = 0x00000100,
-        NEEDS_RESAMPLE              = 0x00001000,
-        NEEDS_AUX                   = 0x00010000,
-    };
-
-    // hook types
-    enum {
-        PROCESSTYPE_NORESAMPLEONETRACK, // others set elsewhere
-    };
-
-    enum {
-        TRACKTYPE_NOP,
-        TRACKTYPE_RESAMPLE,
-        TRACKTYPE_NORESAMPLE,
-        TRACKTYPE_NORESAMPLEMONO,
-    };
-
-    // process hook functionality
-    using process_hook_t = void(AudioMixer::*)();
-
-    struct Track;
-    using hook_t = void(Track::*)(int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
-
-    struct Track {
-        Track()
-            : bufferProvider(nullptr)
-        {
-            // TODO: move additional initialization here.
-        }
+    struct Track : public TrackBase {
+        Track() : TrackBase() {}
 
         ~Track()
         {
-            // bufferProvider, mInputBufferProvider need not be deleted.
-            mResampler.reset(nullptr);
+            // mInputBufferProvider need not be deleted.
             // Ensure the order of destruction of buffer providers as they
             // release the upstream provider in the destructor.
             mTimestretchBufferProvider.reset(nullptr);
@@ -277,13 +109,12 @@
             mAdjustChannelsBufferProvider.reset(nullptr);
         }
 
-        bool        needsRamp() { return (volumeInc[0] | volumeInc[1] | auxInc) != 0; }
-        bool        setResampler(uint32_t trackSampleRate, uint32_t devSampleRate);
-        bool        doesResample() const { return mResampler.get() != nullptr; }
-        void        resetResampler() { if (mResampler.get() != nullptr) mResampler->reset(); }
-        void        adjustVolumeRamp(bool aux, bool useFloat = false);
-        size_t      getUnreleasedFrames() const { return mResampler.get() != nullptr ?
-                                                    mResampler->getUnreleasedFrames() : 0; };
+        uint32_t getOutputChannelCount() override {
+            return mDownmixerBufferProvider.get() != nullptr ? mMixerChannelCount : channelCount;
+        }
+        uint32_t getMixerChannelCount() override {
+            return mMixerChannelCount + mMixerHapticChannelCount;
+        }
 
         status_t    prepareForDownmix();
         void        unprepareForDownmix();
@@ -297,51 +128,9 @@
         bool        setPlaybackRate(const AudioPlaybackRate &playbackRate);
         void        reconfigureBufferProviders();
 
-        static hook_t getTrackHook(int trackType, uint32_t channelCount,
-                audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
-
-        void track__nop(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
-
-        template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
-            typename TO, typename TI, typename TA>
-        void volumeMix(TO *out, size_t outFrames, const TI *in, TA *aux, bool ramp);
-
-        uint32_t    needs;
-
-        // TODO: Eventually remove legacy integer volume settings
-        union {
-        int16_t     volume[MAX_NUM_VOLUMES]; // U4.12 fixed point (top bit should be zero)
-        int32_t     volumeRL;
-        };
-
-        int32_t     prevVolume[MAX_NUM_VOLUMES];
-        int32_t     volumeInc[MAX_NUM_VOLUMES];
-        int32_t     auxInc;
-        int32_t     prevAuxLevel;
-        int16_t     auxLevel;       // 0 <= auxLevel <= MAX_GAIN_INT, but signed for mul performance
-
-        uint16_t    frameCount;
-
-        uint8_t     channelCount;   // 1 or 2, redundant with (needs & NEEDS_CHANNEL_COUNT__MASK)
-        uint8_t     unused_padding; // formerly format, was always 16
-        uint16_t    enabled;        // actually bool
-        audio_channel_mask_t channelMask;
-
-        // actual buffer provider used by the track hooks, see DownmixerBufferProvider below
-        //  for how the Track buffer provider is wrapped by another one when dowmixing is required
-        AudioBufferProvider*                bufferProvider;
-
-        mutable AudioBufferProvider::Buffer buffer; // 8 bytes
-
-        hook_t      hook;
-        const void  *mIn;             // current location in buffer
-
-        std::unique_ptr<AudioResampler> mResampler;
-        uint32_t            sampleRate;
-        int32_t*           mainBuffer;
-        int32_t*           auxBuffer;
-
         /* Buffer providers are constructed to translate the track input data as needed.
+         * See DownmixerBufferProvider below for how the Track buffer provider
+         * is wrapped by another one when dowmixing is required.
          *
          * TODO: perhaps make a single PlaybackConverterProvider class to move
          * all pre-mixer track buffer conversions outside the AudioMixer class.
@@ -363,7 +152,7 @@
          *    the downmixer requirements to the mixer engine input requirements.
          * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
          */
-        AudioBufferProvider*     mInputBufferProvider;    // externally provided buffer provider.
+        AudioBufferProvider* mInputBufferProvider;    // externally provided buffer provider.
         // TODO: combine mAdjustChannelsBufferProvider and
         // mContractChannelsNonDestructiveBufferProvider
         std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
@@ -373,27 +162,10 @@
         std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
         std::unique_ptr<PassthruBufferProvider> mTimestretchBufferProvider;
 
-        int32_t     sessionId;
-
-        audio_format_t mMixerFormat;     // output mix format: AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
-        audio_format_t mFormat;          // input track format
-        audio_format_t mMixerInFormat;   // mix internal format AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
-                                         // each track must be converted to this format.
         audio_format_t mDownmixRequiresFormat;  // required downmixer format
                                                 // AUDIO_FORMAT_PCM_16_BIT if 16 bit necessary
                                                 // AUDIO_FORMAT_INVALID if no required format
 
-        float          mVolume[MAX_NUM_VOLUMES];     // floating point set volume
-        float          mPrevVolume[MAX_NUM_VOLUMES]; // floating point previous volume
-        float          mVolumeInc[MAX_NUM_VOLUMES];  // floating point volume increment
-
-        float          mAuxLevel;                     // floating point set aux level
-        float          mPrevAuxLevel;                 // floating point prev aux level
-        float          mAuxInc;                       // floating point aux increment
-
-        audio_channel_mask_t mMixerChannelMask;
-        uint32_t             mMixerChannelCount;
-
         AudioPlaybackRate    mPlaybackRate;
 
         // Haptic
@@ -440,76 +212,23 @@
             return 0.0f;
         }
         }
-
-    private:
-        // hooks
-        void track__genericResample(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
-        void track__16BitsStereo(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
-        void track__16BitsMono(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
-
-        void volumeRampStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
-        void volumeStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
-
-        // multi-format track hooks
-        template <int MIXTYPE, typename TO, typename TI, typename TA>
-        void track__Resample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
-        template <int MIXTYPE, typename TO, typename TI, typename TA>
-        void track__NoResample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
     };
 
-    // TODO: remove BLOCKSIZE unit of processing - it isn't needed anymore.
-    static constexpr int BLOCKSIZE = 16;
-
-    bool setChannelMasks(int name,
-            audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask);
-
-    // Called when track info changes and a new process hook should be determined.
-    void invalidate() {
-        mHook = &AudioMixer::process__validate;
+    inline std::shared_ptr<Track> getTrack(int name) {
+        return std::static_pointer_cast<Track>(mTracks[name]);
     }
 
-    void process__validate();
-    void process__nop();
-    void process__genericNoResampling();
-    void process__genericResampling();
-    void process__oneTrack16BitsStereoNoResampling();
+    std::shared_ptr<TrackBase> preCreateTrack() override;
+    status_t postCreateTrack(TrackBase *track) override;
 
-    template <int MIXTYPE, typename TO, typename TI, typename TA>
-    void process__noResampleOneTrack();
+    void preProcess() override;
+    void postProcess() override;
 
-    void processHapticData();
-
-    static process_hook_t getProcessHook(int processType, uint32_t channelCount,
-            audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
-
-    static void convertMixerFormat(void *out, audio_format_t mixerOutFormat,
-            void *in, audio_format_t mixerInFormat, size_t sampleCount);
+    bool setChannelMasks(int name,
+            audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask) override;
 
     static void sInitRoutine();
 
-    // initialization constants
-    const uint32_t mSampleRate;
-    const size_t mFrameCount;
-
-    NBLog::Writer *mNBLogWriter = nullptr;   // associated NBLog::Writer
-
-    process_hook_t mHook = &AudioMixer::process__nop;   // one of process__*, never nullptr
-
-    // the size of the type (int32_t) should be the largest of all types supported
-    // by the mixer.
-    std::unique_ptr<int32_t[]> mOutputTemp;
-    std::unique_ptr<int32_t[]> mResampleTemp;
-
-    // track names grouped by main buffer, in no particular order of main buffer.
-    // however names for a particular main buffer are in order (by construction).
-    std::unordered_map<void * /* mainBuffer */, std::vector<int /* name */>> mGroups;
-
-    // track names that are enabled, in increasing order (by construction).
-    std::vector<int /* name */> mEnabled;
-
-    // track smart pointers, by name, in increasing order of name.
-    std::map<int /* name */, std::shared_ptr<Track>> mTracks;
-
     static pthread_once_t sOnceControl; // initialized in constructor by first new
 };
 
diff --git a/media/libaudioclient/include/media/AudioParameter.h b/media/libaudioclient/include/media/AudioParameter.h
index 24837e3..3c190f2 100644
--- a/media/libaudioclient/include/media/AudioParameter.h
+++ b/media/libaudioclient/include/media/AudioParameter.h
@@ -67,9 +67,12 @@
     //  keyAudioLanguagePreferred: Preferred audio language
     static const char * const keyAudioLanguagePreferred;
 
-    //  keyStreamConnect / Disconnect: value is an int in audio_devices_t
-    static const char * const keyStreamConnect;
-    static const char * const keyStreamDisconnect;
+    //  keyDeviceConnect / Disconnect: value is an int in audio_devices_t
+    static const char * const keyDeviceConnect;
+    static const char * const keyDeviceDisconnect;
+    //  Need to be here because vendors still use them.
+    static const char * const keyStreamConnect;  // Deprecated: DO NOT USE.
+    static const char * const keyStreamDisconnect;  // Deprecated: DO NOT USE.
 
     // For querying stream capabilities. All the returned values are lists.
     //   keyStreamSupportedFormats: audio_format_t
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 52bb2fb..d509be6 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -11,6 +11,9 @@
     defaults: ["libaudioclient_tests_defaults"],
     srcs: ["test_create_audiotrack.cpp",
            "test_create_utils.cpp"],
+    header_libs: [
+        "libmedia_headers",
+    ],
     shared_libs: [
         "libaudioclient",
         "libbinder",
@@ -25,6 +28,9 @@
     defaults: ["libaudioclient_tests_defaults"],
     srcs: ["test_create_audiorecord.cpp",
            "test_create_utils.cpp"],
+    header_libs: [
+        "libmedia_headers",
+    ],
     shared_libs: [
         "libaudioclient",
         "libbinder",
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index d4a4f41..a23d945 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -43,6 +43,7 @@
     ],
     header_libs: [
         "android.hardware.audio.common.util@all-versions",
+        "libaudioclient_headers",
         "libaudiohal_headers"
     ],
 
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
index cb78063..9b5d58c 100644
--- a/media/libaudioprocessing/Android.bp
+++ b/media/libaudioprocessing/Android.bp
@@ -3,20 +3,13 @@
 
     export_include_dirs: ["include"],
 
+    header_libs: ["libaudioclient_headers"],
+
     shared_libs: [
-        "libaudiohal",
         "libaudioutils",
         "libcutils",
         "liblog",
-        "libnbaio",
-        "libnblog",
-        "libsonic",
         "libutils",
-        "libvibrator",
-    ],
-
-    header_libs: [
-        "libbase_headers",
     ],
 
     cflags: [
@@ -33,18 +26,32 @@
     defaults: ["libaudioprocessing_defaults"],
 
     srcs: [
+        "AudioMixer.cpp",
         "BufferProviders.cpp",
         "RecordBufferConverter.cpp",
     ],
-    whole_static_libs: ["libaudioprocessing_arm"],
+
+    header_libs: [
+        "libbase_headers",
+        "libmedia_headers"
+    ],
+
+    shared_libs: [
+        "libaudiohal",
+        "libsonic",
+        "libvibrator",
+    ],
+
+    whole_static_libs: ["libaudioprocessing_base"],
 }
 
 cc_library_static {
-    name: "libaudioprocessing_arm",
+    name: "libaudioprocessing_base",
     defaults: ["libaudioprocessing_defaults"],
+    vendor_available: true,
 
     srcs: [
-        "AudioMixer.cpp",
+        "AudioMixerBase.cpp",
         "AudioResampler.cpp",
         "AudioResamplerCubic.cpp",
         "AudioResamplerSinc.cpp",
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index f7cc096..c0b11a4 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "AudioMixer"
 //#define LOG_NDEBUG 0
 
+#include <sstream>
 #include <stdint.h>
 #include <string.h>
 #include <stdlib.h>
@@ -27,9 +28,6 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
-#include <cutils/compiler.h>
-#include <utils/Debug.h>
-
 #include <system/audio.h>
 
 #include <audio_utils/primitives.h>
@@ -58,138 +56,15 @@
 #define ALOGVV(a...) do { } while (0)
 #endif
 
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
-#endif
-
-// Set kUseNewMixer to true to use the new mixer engine always. Otherwise the
-// original code will be used for stereo sinks, the new mixer for multichannel.
-static constexpr bool kUseNewMixer = true;
-
-// Set kUseFloat to true to allow floating input into the mixer engine.
-// If kUseNewMixer is false, this is ignored or may be overridden internally
-// because of downmix/upmix support.
-static constexpr bool kUseFloat = true;
-
-#ifdef FLOAT_AUX
-using TYPE_AUX = float;
-static_assert(kUseNewMixer && kUseFloat,
-        "kUseNewMixer and kUseFloat must be true for FLOAT_AUX option");
-#else
-using TYPE_AUX = int32_t; // q4.27
-#endif
-
 // Set to default copy buffer size in frames for input processing.
-static const size_t kCopyBufferFrameCount = 256;
+static constexpr size_t kCopyBufferFrameCount = 256;
 
 namespace android {
 
 // ----------------------------------------------------------------------------
 
-static inline audio_format_t selectMixerInFormat(audio_format_t inputFormat __unused) {
-    return kUseFloat && kUseNewMixer ? AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
-}
-
-status_t AudioMixer::create(
-        int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId)
-{
-    LOG_ALWAYS_FATAL_IF(exists(name), "name %d already exists", name);
-
-    if (!isValidChannelMask(channelMask)) {
-        ALOGE("%s invalid channelMask: %#x", __func__, channelMask);
-        return BAD_VALUE;
-    }
-    if (!isValidFormat(format)) {
-        ALOGE("%s invalid format: %#x", __func__, format);
-        return BAD_VALUE;
-    }
-
-    auto t = std::make_shared<Track>();
-    {
-        // TODO: move initialization to the Track constructor.
-        // assume default parameters for the track, except where noted below
-        t->needs = 0;
-
-        // Integer volume.
-        // Currently integer volume is kept for the legacy integer mixer.
-        // Will be removed when the legacy mixer path is removed.
-        t->volume[0] = 0;
-        t->volume[1] = 0;
-        t->prevVolume[0] = 0 << 16;
-        t->prevVolume[1] = 0 << 16;
-        t->volumeInc[0] = 0;
-        t->volumeInc[1] = 0;
-        t->auxLevel = 0;
-        t->auxInc = 0;
-        t->prevAuxLevel = 0;
-
-        // Floating point volume.
-        t->mVolume[0] = 0.f;
-        t->mVolume[1] = 0.f;
-        t->mPrevVolume[0] = 0.f;
-        t->mPrevVolume[1] = 0.f;
-        t->mVolumeInc[0] = 0.;
-        t->mVolumeInc[1] = 0.;
-        t->mAuxLevel = 0.;
-        t->mAuxInc = 0.;
-        t->mPrevAuxLevel = 0.;
-
-        // no initialization needed
-        // t->frameCount
-        t->mHapticChannelMask = channelMask & AUDIO_CHANNEL_HAPTIC_ALL;
-        t->mHapticChannelCount = audio_channel_count_from_out_mask(t->mHapticChannelMask);
-        channelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
-        t->channelCount = audio_channel_count_from_out_mask(channelMask);
-        t->enabled = false;
-        ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
-                "Non-stereo channel mask: %d\n", channelMask);
-        t->channelMask = channelMask;
-        t->sessionId = sessionId;
-        // setBufferProvider(name, AudioBufferProvider *) is required before enable(name)
-        t->bufferProvider = NULL;
-        t->buffer.raw = NULL;
-        // no initialization needed
-        // t->buffer.frameCount
-        t->hook = NULL;
-        t->mIn = NULL;
-        t->sampleRate = mSampleRate;
-        // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
-        t->mainBuffer = NULL;
-        t->auxBuffer = NULL;
-        t->mInputBufferProvider = NULL;
-        t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
-        t->mFormat = format;
-        t->mMixerInFormat = selectMixerInFormat(format);
-        t->mDownmixRequiresFormat = AUDIO_FORMAT_INVALID; // no format required
-        t->mMixerChannelMask = audio_channel_mask_from_representation_and_bits(
-                AUDIO_CHANNEL_REPRESENTATION_POSITION, AUDIO_CHANNEL_OUT_STEREO);
-        t->mMixerChannelCount = audio_channel_count_from_out_mask(t->mMixerChannelMask);
-        t->mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
-        // haptic
-        t->mHapticPlaybackEnabled = false;
-        t->mHapticIntensity = HAPTIC_SCALE_NONE;
-        t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
-        t->mMixerHapticChannelCount = 0;
-        t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
-        t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
-        t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
-        t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
-        t->mKeepContractedChannels = false;
-        // Check the downmixing (or upmixing) requirements.
-        status_t status = t->prepareForDownmix();
-        if (status != OK) {
-            ALOGE("AudioMixer::getTrackName invalid channelMask (%#x)", channelMask);
-            return BAD_VALUE;
-        }
-        // prepareForDownmix() may change mDownmixRequiresFormat
-        ALOGVV("mMixerFormat:%#x  mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat);
-        t->prepareForReformat();
-        t->prepareForAdjustChannelsNonDestructive(mFrameCount);
-        t->prepareForAdjustChannels();
-
-        mTracks[name] = t;
-        return OK;
-    }
+bool AudioMixer::isValidChannelMask(audio_channel_mask_t channelMask) const {
+    return audio_channel_mask_is_valid(channelMask); // the RemixBufferProvider is flexible.
 }
 
 // Called when channel masks have changed for a track name
@@ -198,7 +73,7 @@
 bool AudioMixer::setChannelMasks(int name,
         audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask) {
     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
+    const std::shared_ptr<Track> &track = getTrack(name);
 
     if (trackChannelMask == (track->channelMask | track->mHapticChannelMask)
             && mixerChannelMask == (track->mMixerChannelMask | track->mMixerHapticChannelMask)) {
@@ -255,14 +130,8 @@
     track->prepareForAdjustChannelsNonDestructive(mFrameCount);
     track->prepareForAdjustChannels();
 
-    if (track->mResampler.get() != nullptr) {
-        // resampler channels may have changed.
-        const uint32_t resetToSampleRate = track->sampleRate;
-        track->mResampler.reset(nullptr);
-        track->sampleRate = mSampleRate; // without resampler, track rate is device sample rate.
-        // recreate the resampler with updated format, channels, saved sampleRate.
-        track->setResampler(resetToSampleRate /*trackSampleRate*/, mSampleRate /*devSampleRate*/);
-    }
+    // Resampler channels may have changed.
+    track->recreateResampler(mSampleRate);
     return true;
 }
 
@@ -477,171 +346,10 @@
     }
 }
 
-void AudioMixer::destroy(int name)
-{
-    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    ALOGV("deleteTrackName(%d)", name);
-
-    if (mTracks[name]->enabled) {
-        invalidate();
-    }
-    mTracks.erase(name); // deallocate track
-}
-
-void AudioMixer::enable(int name)
-{
-    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
-
-    if (!track->enabled) {
-        track->enabled = true;
-        ALOGV("enable(%d)", name);
-        invalidate();
-    }
-}
-
-void AudioMixer::disable(int name)
-{
-    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
-
-    if (track->enabled) {
-        track->enabled = false;
-        ALOGV("disable(%d)", name);
-        invalidate();
-    }
-}
-
-/* Sets the volume ramp variables for the AudioMixer.
- *
- * The volume ramp variables are used to transition from the previous
- * volume to the set volume.  ramp controls the duration of the transition.
- * Its value is typically one state framecount period, but may also be 0,
- * meaning "immediate."
- *
- * FIXME: 1) Volume ramp is enabled only if there is a nonzero integer increment
- * even if there is a nonzero floating point increment (in that case, the volume
- * change is immediate).  This restriction should be changed when the legacy mixer
- * is removed (see #2).
- * FIXME: 2) Integer volume variables are used for Legacy mixing and should be removed
- * when no longer needed.
- *
- * @param newVolume set volume target in floating point [0.0, 1.0].
- * @param ramp number of frames to increment over. if ramp is 0, the volume
- * should be set immediately.  Currently ramp should not exceed 65535 (frames).
- * @param pIntSetVolume pointer to the U4.12 integer target volume, set on return.
- * @param pIntPrevVolume pointer to the U4.28 integer previous volume, set on return.
- * @param pIntVolumeInc pointer to the U4.28 increment per output audio frame, set on return.
- * @param pSetVolume pointer to the float target volume, set on return.
- * @param pPrevVolume pointer to the float previous volume, set on return.
- * @param pVolumeInc pointer to the float increment per output audio frame, set on return.
- * @return true if the volume has changed, false if volume is same.
- */
-static inline bool setVolumeRampVariables(float newVolume, int32_t ramp,
-        int16_t *pIntSetVolume, int32_t *pIntPrevVolume, int32_t *pIntVolumeInc,
-        float *pSetVolume, float *pPrevVolume, float *pVolumeInc) {
-    // check floating point volume to see if it is identical to the previously
-    // set volume.
-    // We do not use a tolerance here (and reject changes too small)
-    // as it may be confusing to use a different value than the one set.
-    // If the resulting volume is too small to ramp, it is a direct set of the volume.
-    if (newVolume == *pSetVolume) {
-        return false;
-    }
-    if (newVolume < 0) {
-        newVolume = 0; // should not have negative volumes
-    } else {
-        switch (fpclassify(newVolume)) {
-        case FP_SUBNORMAL:
-        case FP_NAN:
-            newVolume = 0;
-            break;
-        case FP_ZERO:
-            break; // zero volume is fine
-        case FP_INFINITE:
-            // Infinite volume could be handled consistently since
-            // floating point math saturates at infinities,
-            // but we limit volume to unity gain float.
-            // ramp = 0; break;
-            //
-            newVolume = AudioMixer::UNITY_GAIN_FLOAT;
-            break;
-        case FP_NORMAL:
-        default:
-            // Floating point does not have problems with overflow wrap
-            // that integer has.  However, we limit the volume to
-            // unity gain here.
-            // TODO: Revisit the volume limitation and perhaps parameterize.
-            if (newVolume > AudioMixer::UNITY_GAIN_FLOAT) {
-                newVolume = AudioMixer::UNITY_GAIN_FLOAT;
-            }
-            break;
-        }
-    }
-
-    // set floating point volume ramp
-    if (ramp != 0) {
-        // when the ramp completes, *pPrevVolume is set to *pSetVolume, so there
-        // is no computational mismatch; hence equality is checked here.
-        ALOGD_IF(*pPrevVolume != *pSetVolume, "previous float ramp hasn't finished,"
-                " prev:%f  set_to:%f", *pPrevVolume, *pSetVolume);
-        const float inc = (newVolume - *pPrevVolume) / ramp; // could be inf, nan, subnormal
-        // could be inf, cannot be nan, subnormal
-        const float maxv = std::max(newVolume, *pPrevVolume);
-
-        if (isnormal(inc) // inc must be a normal number (no subnormals, infinite, nan)
-                && maxv + inc != maxv) { // inc must make forward progress
-            *pVolumeInc = inc;
-            // ramp is set now.
-            // Note: if newVolume is 0, then near the end of the ramp,
-            // it may be possible that the ramped volume may be subnormal or
-            // temporarily negative by a small amount or subnormal due to floating
-            // point inaccuracies.
-        } else {
-            ramp = 0; // ramp not allowed
-        }
-    }
-
-    // compute and check integer volume, no need to check negative values
-    // The integer volume is limited to "unity_gain" to avoid wrapping and other
-    // audio artifacts, so it never reaches the range limit of U4.28.
-    // We safely use signed 16 and 32 bit integers here.
-    const float scaledVolume = newVolume * AudioMixer::UNITY_GAIN_INT; // not neg, subnormal, nan
-    const int32_t intVolume = (scaledVolume >= (float)AudioMixer::UNITY_GAIN_INT) ?
-            AudioMixer::UNITY_GAIN_INT : (int32_t)scaledVolume;
-
-    // set integer volume ramp
-    if (ramp != 0) {
-        // integer volume is U4.12 (to use 16 bit multiplies), but ramping uses U4.28.
-        // when the ramp completes, *pIntPrevVolume is set to *pIntSetVolume << 16, so there
-        // is no computational mismatch; hence equality is checked here.
-        ALOGD_IF(*pIntPrevVolume != *pIntSetVolume << 16, "previous int ramp hasn't finished,"
-                " prev:%d  set_to:%d", *pIntPrevVolume, *pIntSetVolume << 16);
-        const int32_t inc = ((intVolume << 16) - *pIntPrevVolume) / ramp;
-
-        if (inc != 0) { // inc must make forward progress
-            *pIntVolumeInc = inc;
-        } else {
-            ramp = 0; // ramp not allowed
-        }
-    }
-
-    // if no ramp, or ramp not allowed, then clear float and integer increments
-    if (ramp == 0) {
-        *pVolumeInc = 0;
-        *pPrevVolume = newVolume;
-        *pIntVolumeInc = 0;
-        *pIntPrevVolume = intVolume << 16;
-    }
-    *pSetVolume = newVolume;
-    *pIntSetVolume = intVolume;
-    return true;
-}
-
 void AudioMixer::setParameter(int name, int target, int param, void *value)
 {
     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
+    const std::shared_ptr<Track> &track = getTrack(name);
 
     int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value));
     int32_t *valueBuf = reinterpret_cast<int32_t*>(value);
@@ -670,11 +378,7 @@
             }
             break;
         case AUX_BUFFER:
-            if (track->auxBuffer != valueBuf) {
-                track->auxBuffer = valueBuf;
-                ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
-                invalidate();
-            }
+            AudioMixerBase::setParameter(name, target, param, value);
             break;
         case FORMAT: {
             audio_format_t format = static_cast<audio_format_t>(valueInt);
@@ -730,127 +434,38 @@
         break;
 
     case RESAMPLE:
-        switch (param) {
-        case SAMPLE_RATE:
-            ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
-            if (track->setResampler(uint32_t(valueInt), mSampleRate)) {
-                ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
-                        uint32_t(valueInt));
-                invalidate();
-            }
-            break;
-        case RESET:
-            track->resetResampler();
-            invalidate();
-            break;
-        case REMOVE:
-            track->mResampler.reset(nullptr);
-            track->sampleRate = mSampleRate;
-            invalidate();
-            break;
-        default:
-            LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param);
-        }
-        break;
-
     case RAMP_VOLUME:
     case VOLUME:
+        AudioMixerBase::setParameter(name, target, param, value);
+        break;
+    case TIMESTRETCH:
         switch (param) {
-        case AUXLEVEL:
-            if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
-                    target == RAMP_VOLUME ? mFrameCount : 0,
-                    &track->auxLevel, &track->prevAuxLevel, &track->auxInc,
-                    &track->mAuxLevel, &track->mPrevAuxLevel, &track->mAuxInc)) {
-                ALOGV("setParameter(%s, AUXLEVEL: %04x)",
-                        target == VOLUME ? "VOLUME" : "RAMP_VOLUME", track->auxLevel);
-                invalidate();
+        case PLAYBACK_RATE: {
+            const AudioPlaybackRate *playbackRate =
+                    reinterpret_cast<AudioPlaybackRate*>(value);
+            ALOGW_IF(!isAudioPlaybackRateValid(*playbackRate),
+                    "bad parameters speed %f, pitch %f",
+                    playbackRate->mSpeed, playbackRate->mPitch);
+            if (track->setPlaybackRate(*playbackRate)) {
+                ALOGV("setParameter(TIMESTRETCH, PLAYBACK_RATE, STRETCH_MODE, FALLBACK_MODE "
+                        "%f %f %d %d",
+                        playbackRate->mSpeed,
+                        playbackRate->mPitch,
+                        playbackRate->mStretchMode,
+                        playbackRate->mFallbackMode);
+                // invalidate();  (should not require reconfigure)
             }
-            break;
+        } break;
         default:
-            if ((unsigned)param >= VOLUME0 && (unsigned)param < VOLUME0 + MAX_NUM_VOLUMES) {
-                if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
-                        target == RAMP_VOLUME ? mFrameCount : 0,
-                        &track->volume[param - VOLUME0],
-                        &track->prevVolume[param - VOLUME0],
-                        &track->volumeInc[param - VOLUME0],
-                        &track->mVolume[param - VOLUME0],
-                        &track->mPrevVolume[param - VOLUME0],
-                        &track->mVolumeInc[param - VOLUME0])) {
-                    ALOGV("setParameter(%s, VOLUME%d: %04x)",
-                            target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
-                                    track->volume[param - VOLUME0]);
-                    invalidate();
-                }
-            } else {
-                LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
-            }
+            LOG_ALWAYS_FATAL("setParameter timestretch: bad param %d", param);
         }
         break;
-        case TIMESTRETCH:
-            switch (param) {
-            case PLAYBACK_RATE: {
-                const AudioPlaybackRate *playbackRate =
-                        reinterpret_cast<AudioPlaybackRate*>(value);
-                ALOGW_IF(!isAudioPlaybackRateValid(*playbackRate),
-                        "bad parameters speed %f, pitch %f",
-                        playbackRate->mSpeed, playbackRate->mPitch);
-                if (track->setPlaybackRate(*playbackRate)) {
-                    ALOGV("setParameter(TIMESTRETCH, PLAYBACK_RATE, STRETCH_MODE, FALLBACK_MODE "
-                            "%f %f %d %d",
-                            playbackRate->mSpeed,
-                            playbackRate->mPitch,
-                            playbackRate->mStretchMode,
-                            playbackRate->mFallbackMode);
-                    // invalidate();  (should not require reconfigure)
-                }
-            } break;
-            default:
-                LOG_ALWAYS_FATAL("setParameter timestretch: bad param %d", param);
-            }
-            break;
 
     default:
         LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
     }
 }
 
-bool AudioMixer::Track::setResampler(uint32_t trackSampleRate, uint32_t devSampleRate)
-{
-    if (trackSampleRate != devSampleRate || mResampler.get() != nullptr) {
-        if (sampleRate != trackSampleRate) {
-            sampleRate = trackSampleRate;
-            if (mResampler.get() == nullptr) {
-                ALOGV("Creating resampler from track %d Hz to device %d Hz",
-                        trackSampleRate, devSampleRate);
-                AudioResampler::src_quality quality;
-                // force lowest quality level resampler if use case isn't music or video
-                // FIXME this is flawed for dynamic sample rates, as we choose the resampler
-                // quality level based on the initial ratio, but that could change later.
-                // Should have a way to distinguish tracks with static ratios vs. dynamic ratios.
-                if (isMusicRate(trackSampleRate)) {
-                    quality = AudioResampler::DEFAULT_QUALITY;
-                } else {
-                    quality = AudioResampler::DYN_LOW_QUALITY;
-                }
-
-                // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer
-                // but if none exists, it is the channel count (1 for mono).
-                const int resamplerChannelCount = mDownmixerBufferProvider.get() != nullptr
-                        ? mMixerChannelCount : channelCount;
-                ALOGVV("Creating resampler:"
-                        " format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n",
-                        mMixerInFormat, resamplerChannelCount, devSampleRate, quality);
-                mResampler.reset(AudioResampler::create(
-                        mMixerInFormat,
-                        resamplerChannelCount,
-                        devSampleRate, quality));
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
 bool AudioMixer::Track::setPlaybackRate(const AudioPlaybackRate &playbackRate)
 {
     if ((mTimestretchBufferProvider.get() == nullptr &&
@@ -863,8 +478,7 @@
     if (mTimestretchBufferProvider.get() == nullptr) {
         // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer
         // but if none exists, it is the channel count (1 for mono).
-        const int timestretchChannelCount = mDownmixerBufferProvider.get() != nullptr
-                ? mMixerChannelCount : channelCount;
+        const int timestretchChannelCount = getOutputChannelCount();
         mTimestretchBufferProvider.reset(new TimestretchBufferProvider(timestretchChannelCount,
                 mMixerInFormat, sampleRate, playbackRate));
         reconfigureBufferProviders();
@@ -875,84 +489,10 @@
     return true;
 }
 
-/* Checks to see if the volume ramp has completed and clears the increment
- * variables appropriately.
- *
- * FIXME: There is code to handle int/float ramp variable switchover should it not
- * complete within a mixer buffer processing call, but it is preferred to avoid switchover
- * due to precision issues.  The switchover code is included for legacy code purposes
- * and can be removed once the integer volume is removed.
- *
- * It is not sufficient to clear only the volumeInc integer variable because
- * if one channel requires ramping, all channels are ramped.
- *
- * There is a bit of duplicated code here, but it keeps backward compatibility.
- */
-inline void AudioMixer::Track::adjustVolumeRamp(bool aux, bool useFloat)
-{
-    if (useFloat) {
-        for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
-            if ((mVolumeInc[i] > 0 && mPrevVolume[i] + mVolumeInc[i] >= mVolume[i]) ||
-                     (mVolumeInc[i] < 0 && mPrevVolume[i] + mVolumeInc[i] <= mVolume[i])) {
-                volumeInc[i] = 0;
-                prevVolume[i] = volume[i] << 16;
-                mVolumeInc[i] = 0.;
-                mPrevVolume[i] = mVolume[i];
-            } else {
-                //ALOGV("ramp: %f %f %f", mVolume[i], mPrevVolume[i], mVolumeInc[i]);
-                prevVolume[i] = u4_28_from_float(mPrevVolume[i]);
-            }
-        }
-    } else {
-        for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
-            if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
-                    ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
-                volumeInc[i] = 0;
-                prevVolume[i] = volume[i] << 16;
-                mVolumeInc[i] = 0.;
-                mPrevVolume[i] = mVolume[i];
-            } else {
-                //ALOGV("ramp: %d %d %d", volume[i] << 16, prevVolume[i], volumeInc[i]);
-                mPrevVolume[i]  = float_from_u4_28(prevVolume[i]);
-            }
-        }
-    }
-
-    if (aux) {
-#ifdef FLOAT_AUX
-        if (useFloat) {
-            if ((mAuxInc > 0.f && mPrevAuxLevel + mAuxInc >= mAuxLevel) ||
-                    (mAuxInc < 0.f && mPrevAuxLevel + mAuxInc <= mAuxLevel)) {
-                auxInc = 0;
-                prevAuxLevel = auxLevel << 16;
-                mAuxInc = 0.f;
-                mPrevAuxLevel = mAuxLevel;
-            }
-        } else
-#endif
-        if ((auxInc > 0 && ((prevAuxLevel + auxInc) >> 16) >= auxLevel) ||
-                (auxInc < 0 && ((prevAuxLevel + auxInc) >> 16) <= auxLevel)) {
-            auxInc = 0;
-            prevAuxLevel = auxLevel << 16;
-            mAuxInc = 0.f;
-            mPrevAuxLevel = mAuxLevel;
-        }
-    }
-}
-
-size_t AudioMixer::getUnreleasedFrames(int name) const
-{
-    const auto it = mTracks.find(name);
-    if (it != mTracks.end()) {
-        return it->second->getUnreleasedFrames();
-    }
-    return 0;
-}
-
 void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider)
 {
     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
+    const std::shared_ptr<Track> &track = getTrack(name);
 
     if (track->mInputBufferProvider == bufferProvider) {
         return; // don't reset any buffer providers if identical.
@@ -976,679 +516,6 @@
     track->reconfigureBufferProviders();
 }
 
-void AudioMixer::process__validate()
-{
-    // TODO: fix all16BitsStereNoResample logic to
-    // either properly handle muted tracks (it should ignore them)
-    // or remove altogether as an obsolete optimization.
-    bool all16BitsStereoNoResample = true;
-    bool resampling = false;
-    bool volumeRamp = false;
-
-    mEnabled.clear();
-    mGroups.clear();
-    for (const auto &pair : mTracks) {
-        const int name = pair.first;
-        const std::shared_ptr<Track> &t = pair.second;
-        if (!t->enabled) continue;
-
-        mEnabled.emplace_back(name);  // we add to mEnabled in order of name.
-        mGroups[t->mainBuffer].emplace_back(name); // mGroups also in order of name.
-
-        uint32_t n = 0;
-        // FIXME can overflow (mask is only 3 bits)
-        n |= NEEDS_CHANNEL_1 + t->channelCount - 1;
-        if (t->doesResample()) {
-            n |= NEEDS_RESAMPLE;
-        }
-        if (t->auxLevel != 0 && t->auxBuffer != NULL) {
-            n |= NEEDS_AUX;
-        }
-
-        if (t->volumeInc[0]|t->volumeInc[1]) {
-            volumeRamp = true;
-        } else if (!t->doesResample() && t->volumeRL == 0) {
-            n |= NEEDS_MUTE;
-        }
-        t->needs = n;
-
-        if (n & NEEDS_MUTE) {
-            t->hook = &Track::track__nop;
-        } else {
-            if (n & NEEDS_AUX) {
-                all16BitsStereoNoResample = false;
-            }
-            if (n & NEEDS_RESAMPLE) {
-                all16BitsStereoNoResample = false;
-                resampling = true;
-                t->hook = Track::getTrackHook(TRACKTYPE_RESAMPLE, t->mMixerChannelCount,
-                        t->mMixerInFormat, t->mMixerFormat);
-                ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
-                        "Track %d needs downmix + resample", name);
-            } else {
-                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
-                    t->hook = Track::getTrackHook(
-                            (t->mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO  // TODO: MONO_HACK
-                                    && t->channelMask == AUDIO_CHANNEL_OUT_MONO)
-                                ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE,
-                            t->mMixerChannelCount,
-                            t->mMixerInFormat, t->mMixerFormat);
-                    all16BitsStereoNoResample = false;
-                }
-                if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
-                    t->hook = Track::getTrackHook(TRACKTYPE_NORESAMPLE, t->mMixerChannelCount,
-                            t->mMixerInFormat, t->mMixerFormat);
-                    ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
-                            "Track %d needs downmix", name);
-                }
-            }
-        }
-    }
-
-    // select the processing hooks
-    mHook = &AudioMixer::process__nop;
-    if (mEnabled.size() > 0) {
-        if (resampling) {
-            if (mOutputTemp.get() == nullptr) {
-                mOutputTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
-            }
-            if (mResampleTemp.get() == nullptr) {
-                mResampleTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
-            }
-            mHook = &AudioMixer::process__genericResampling;
-        } else {
-            // we keep temp arrays around.
-            mHook = &AudioMixer::process__genericNoResampling;
-            if (all16BitsStereoNoResample && !volumeRamp) {
-                if (mEnabled.size() == 1) {
-                    const std::shared_ptr<Track> &t = mTracks[mEnabled[0]];
-                    if ((t->needs & NEEDS_MUTE) == 0) {
-                        // The check prevents a muted track from acquiring a process hook.
-                        //
-                        // This is dangerous if the track is MONO as that requires
-                        // special case handling due to implicit channel duplication.
-                        // Stereo or Multichannel should actually be fine here.
-                        mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
-                                t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat);
-                    }
-                }
-            }
-        }
-    }
-
-    ALOGV("mixer configuration change: %zu "
-        "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
-        mEnabled.size(), all16BitsStereoNoResample, resampling, volumeRamp);
-
-   process();
-
-    // Now that the volume ramp has been done, set optimal state and
-    // track hooks for subsequent mixer process
-    if (mEnabled.size() > 0) {
-        bool allMuted = true;
-
-        for (const int name : mEnabled) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            if (!t->doesResample() && t->volumeRL == 0) {
-                t->needs |= NEEDS_MUTE;
-                t->hook = &Track::track__nop;
-            } else {
-                allMuted = false;
-            }
-        }
-        if (allMuted) {
-            mHook = &AudioMixer::process__nop;
-        } else if (all16BitsStereoNoResample) {
-            if (mEnabled.size() == 1) {
-                //const int i = 31 - __builtin_clz(enabledTracks);
-                const std::shared_ptr<Track> &t = mTracks[mEnabled[0]];
-                // Muted single tracks handled by allMuted above.
-                mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
-                        t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat);
-            }
-        }
-    }
-}
-
-void AudioMixer::Track::track__genericResample(
-        int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
-{
-    ALOGVV("track__genericResample\n");
-    mResampler->setSampleRate(sampleRate);
-
-    // ramp gain - resample to temp buffer and scale/mix in 2nd step
-    if (aux != NULL) {
-        // always resample with unity gain when sending to auxiliary buffer to be able
-        // to apply send level after resampling
-        mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
-        memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(int32_t));
-        mResampler->resample(temp, outFrameCount, bufferProvider);
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
-            volumeRampStereo(out, outFrameCount, temp, aux);
-        } else {
-            volumeStereo(out, outFrameCount, temp, aux);
-        }
-    } else {
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
-            mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
-            memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
-            mResampler->resample(temp, outFrameCount, bufferProvider);
-            volumeRampStereo(out, outFrameCount, temp, aux);
-        }
-
-        // constant gain
-        else {
-            mResampler->setVolume(mVolume[0], mVolume[1]);
-            mResampler->resample(out, outFrameCount, bufferProvider);
-        }
-    }
-}
-
-void AudioMixer::Track::track__nop(int32_t* out __unused,
-        size_t outFrameCount __unused, int32_t* temp __unused, int32_t* aux __unused)
-{
-}
-
-void AudioMixer::Track::volumeRampStereo(
-        int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
-{
-    int32_t vl = prevVolume[0];
-    int32_t vr = prevVolume[1];
-    const int32_t vlInc = volumeInc[0];
-    const int32_t vrInc = volumeInc[1];
-
-    //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-    //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
-    //       (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-    // ramp volume
-    if (CC_UNLIKELY(aux != NULL)) {
-        int32_t va = prevAuxLevel;
-        const int32_t vaInc = auxInc;
-        int32_t l;
-        int32_t r;
-
-        do {
-            l = (*temp++ >> 12);
-            r = (*temp++ >> 12);
-            *out++ += (vl >> 16) * l;
-            *out++ += (vr >> 16) * r;
-            *aux++ += (va >> 17) * (l + r);
-            vl += vlInc;
-            vr += vrInc;
-            va += vaInc;
-        } while (--frameCount);
-        prevAuxLevel = va;
-    } else {
-        do {
-            *out++ += (vl >> 16) * (*temp++ >> 12);
-            *out++ += (vr >> 16) * (*temp++ >> 12);
-            vl += vlInc;
-            vr += vrInc;
-        } while (--frameCount);
-    }
-    prevVolume[0] = vl;
-    prevVolume[1] = vr;
-    adjustVolumeRamp(aux != NULL);
-}
-
-void AudioMixer::Track::volumeStereo(
-        int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
-{
-    const int16_t vl = volume[0];
-    const int16_t vr = volume[1];
-
-    if (CC_UNLIKELY(aux != NULL)) {
-        const int16_t va = auxLevel;
-        do {
-            int16_t l = (int16_t)(*temp++ >> 12);
-            int16_t r = (int16_t)(*temp++ >> 12);
-            out[0] = mulAdd(l, vl, out[0]);
-            int16_t a = (int16_t)(((int32_t)l + r) >> 1);
-            out[1] = mulAdd(r, vr, out[1]);
-            out += 2;
-            aux[0] = mulAdd(a, va, aux[0]);
-            aux++;
-        } while (--frameCount);
-    } else {
-        do {
-            int16_t l = (int16_t)(*temp++ >> 12);
-            int16_t r = (int16_t)(*temp++ >> 12);
-            out[0] = mulAdd(l, vl, out[0]);
-            out[1] = mulAdd(r, vr, out[1]);
-            out += 2;
-        } while (--frameCount);
-    }
-}
-
-void AudioMixer::Track::track__16BitsStereo(
-        int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
-{
-    ALOGVV("track__16BitsStereo\n");
-    const int16_t *in = static_cast<const int16_t *>(mIn);
-
-    if (CC_UNLIKELY(aux != NULL)) {
-        int32_t l;
-        int32_t r;
-        // ramp gain
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
-            int32_t vl = prevVolume[0];
-            int32_t vr = prevVolume[1];
-            int32_t va = prevAuxLevel;
-            const int32_t vlInc = volumeInc[0];
-            const int32_t vrInc = volumeInc[1];
-            const int32_t vaInc = auxInc;
-            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-            //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
-            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-            do {
-                l = (int32_t)*in++;
-                r = (int32_t)*in++;
-                *out++ += (vl >> 16) * l;
-                *out++ += (vr >> 16) * r;
-                *aux++ += (va >> 17) * (l + r);
-                vl += vlInc;
-                vr += vrInc;
-                va += vaInc;
-            } while (--frameCount);
-
-            prevVolume[0] = vl;
-            prevVolume[1] = vr;
-            prevAuxLevel = va;
-            adjustVolumeRamp(true);
-        }
-
-        // constant gain
-        else {
-            const uint32_t vrl = volumeRL;
-            const int16_t va = (int16_t)auxLevel;
-            do {
-                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
-                in += 2;
-                out[0] = mulAddRL(1, rl, vrl, out[0]);
-                out[1] = mulAddRL(0, rl, vrl, out[1]);
-                out += 2;
-                aux[0] = mulAdd(a, va, aux[0]);
-                aux++;
-            } while (--frameCount);
-        }
-    } else {
-        // ramp gain
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
-            int32_t vl = prevVolume[0];
-            int32_t vr = prevVolume[1];
-            const int32_t vlInc = volumeInc[0];
-            const int32_t vrInc = volumeInc[1];
-
-            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-            //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
-            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-            do {
-                *out++ += (vl >> 16) * (int32_t) *in++;
-                *out++ += (vr >> 16) * (int32_t) *in++;
-                vl += vlInc;
-                vr += vrInc;
-            } while (--frameCount);
-
-            prevVolume[0] = vl;
-            prevVolume[1] = vr;
-            adjustVolumeRamp(false);
-        }
-
-        // constant gain
-        else {
-            const uint32_t vrl = volumeRL;
-            do {
-                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                in += 2;
-                out[0] = mulAddRL(1, rl, vrl, out[0]);
-                out[1] = mulAddRL(0, rl, vrl, out[1]);
-                out += 2;
-            } while (--frameCount);
-        }
-    }
-    mIn = in;
-}
-
-void AudioMixer::Track::track__16BitsMono(
-        int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
-{
-    ALOGVV("track__16BitsMono\n");
-    const int16_t *in = static_cast<int16_t const *>(mIn);
-
-    if (CC_UNLIKELY(aux != NULL)) {
-        // ramp gain
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
-            int32_t vl = prevVolume[0];
-            int32_t vr = prevVolume[1];
-            int32_t va = prevAuxLevel;
-            const int32_t vlInc = volumeInc[0];
-            const int32_t vrInc = volumeInc[1];
-            const int32_t vaInc = auxInc;
-
-            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-            //         t, vlInc/65536.0f, vl/65536.0f, volume[0],
-            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-            do {
-                int32_t l = *in++;
-                *out++ += (vl >> 16) * l;
-                *out++ += (vr >> 16) * l;
-                *aux++ += (va >> 16) * l;
-                vl += vlInc;
-                vr += vrInc;
-                va += vaInc;
-            } while (--frameCount);
-
-            prevVolume[0] = vl;
-            prevVolume[1] = vr;
-            prevAuxLevel = va;
-            adjustVolumeRamp(true);
-        }
-        // constant gain
-        else {
-            const int16_t vl = volume[0];
-            const int16_t vr = volume[1];
-            const int16_t va = (int16_t)auxLevel;
-            do {
-                int16_t l = *in++;
-                out[0] = mulAdd(l, vl, out[0]);
-                out[1] = mulAdd(l, vr, out[1]);
-                out += 2;
-                aux[0] = mulAdd(l, va, aux[0]);
-                aux++;
-            } while (--frameCount);
-        }
-    } else {
-        // ramp gain
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
-            int32_t vl = prevVolume[0];
-            int32_t vr = prevVolume[1];
-            const int32_t vlInc = volumeInc[0];
-            const int32_t vrInc = volumeInc[1];
-
-            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-            //         t, vlInc/65536.0f, vl/65536.0f, volume[0],
-            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-            do {
-                int32_t l = *in++;
-                *out++ += (vl >> 16) * l;
-                *out++ += (vr >> 16) * l;
-                vl += vlInc;
-                vr += vrInc;
-            } while (--frameCount);
-
-            prevVolume[0] = vl;
-            prevVolume[1] = vr;
-            adjustVolumeRamp(false);
-        }
-        // constant gain
-        else {
-            const int16_t vl = volume[0];
-            const int16_t vr = volume[1];
-            do {
-                int16_t l = *in++;
-                out[0] = mulAdd(l, vl, out[0]);
-                out[1] = mulAdd(l, vr, out[1]);
-                out += 2;
-            } while (--frameCount);
-        }
-    }
-    mIn = in;
-}
-
-// no-op case
-void AudioMixer::process__nop()
-{
-    ALOGVV("process__nop\n");
-
-    for (const auto &pair : mGroups) {
-        // process by group of tracks with same output buffer to
-        // avoid multiple memset() on same buffer
-        const auto &group = pair.second;
-
-        const std::shared_ptr<Track> &t = mTracks[group[0]];
-        memset(t->mainBuffer, 0,
-                mFrameCount * audio_bytes_per_frame(
-                        t->mMixerChannelCount + t->mMixerHapticChannelCount, t->mMixerFormat));
-
-        // now consume data
-        for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            size_t outFrames = mFrameCount;
-            while (outFrames) {
-                t->buffer.frameCount = outFrames;
-                t->bufferProvider->getNextBuffer(&t->buffer);
-                if (t->buffer.raw == NULL) break;
-                outFrames -= t->buffer.frameCount;
-                t->bufferProvider->releaseBuffer(&t->buffer);
-            }
-        }
-    }
-}
-
-// generic code without resampling
-void AudioMixer::process__genericNoResampling()
-{
-    ALOGVV("process__genericNoResampling\n");
-    int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
-
-    for (const auto &pair : mGroups) {
-        // process by group of tracks with same output main buffer to
-        // avoid multiple memset() on same buffer
-        const auto &group = pair.second;
-
-        // acquire buffer
-        for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            t->buffer.frameCount = mFrameCount;
-            t->bufferProvider->getNextBuffer(&t->buffer);
-            t->frameCount = t->buffer.frameCount;
-            t->mIn = t->buffer.raw;
-        }
-
-        int32_t *out = (int *)pair.first;
-        size_t numFrames = 0;
-        do {
-            const size_t frameCount = std::min((size_t)BLOCKSIZE, mFrameCount - numFrames);
-            memset(outTemp, 0, sizeof(outTemp));
-            for (const int name : group) {
-                const std::shared_ptr<Track> &t = mTracks[name];
-                int32_t *aux = NULL;
-                if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
-                    aux = t->auxBuffer + numFrames;
-                }
-                for (int outFrames = frameCount; outFrames > 0; ) {
-                    // t->in == nullptr can happen if the track was flushed just after having
-                    // been enabled for mixing.
-                    if (t->mIn == nullptr) {
-                        break;
-                    }
-                    size_t inFrames = (t->frameCount > outFrames)?outFrames:t->frameCount;
-                    if (inFrames > 0) {
-                        (t.get()->*t->hook)(
-                                outTemp + (frameCount - outFrames) * t->mMixerChannelCount,
-                                inFrames, mResampleTemp.get() /* naked ptr */, aux);
-                        t->frameCount -= inFrames;
-                        outFrames -= inFrames;
-                        if (CC_UNLIKELY(aux != NULL)) {
-                            aux += inFrames;
-                        }
-                    }
-                    if (t->frameCount == 0 && outFrames) {
-                        t->bufferProvider->releaseBuffer(&t->buffer);
-                        t->buffer.frameCount = (mFrameCount - numFrames) -
-                                (frameCount - outFrames);
-                        t->bufferProvider->getNextBuffer(&t->buffer);
-                        t->mIn = t->buffer.raw;
-                        if (t->mIn == nullptr) {
-                            break;
-                        }
-                        t->frameCount = t->buffer.frameCount;
-                    }
-                }
-            }
-
-            const std::shared_ptr<Track> &t1 = mTracks[group[0]];
-            convertMixerFormat(out, t1->mMixerFormat, outTemp, t1->mMixerInFormat,
-                    frameCount * t1->mMixerChannelCount);
-            // TODO: fix ugly casting due to choice of out pointer type
-            out = reinterpret_cast<int32_t*>((uint8_t*)out
-                    + frameCount * t1->mMixerChannelCount
-                    * audio_bytes_per_sample(t1->mMixerFormat));
-            numFrames += frameCount;
-        } while (numFrames < mFrameCount);
-
-        // release each track's buffer
-        for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            t->bufferProvider->releaseBuffer(&t->buffer);
-        }
-    }
-}
-
-// generic code with resampling
-void AudioMixer::process__genericResampling()
-{
-    ALOGVV("process__genericResampling\n");
-    int32_t * const outTemp = mOutputTemp.get(); // naked ptr
-    size_t numFrames = mFrameCount;
-
-    for (const auto &pair : mGroups) {
-        const auto &group = pair.second;
-        const std::shared_ptr<Track> &t1 = mTracks[group[0]];
-
-        // clear temp buffer
-        memset(outTemp, 0, sizeof(*outTemp) * t1->mMixerChannelCount * mFrameCount);
-        for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            int32_t *aux = NULL;
-            if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
-                aux = t->auxBuffer;
-            }
-
-            // this is a little goofy, on the resampling case we don't
-            // acquire/release the buffers because it's done by
-            // the resampler.
-            if (t->needs & NEEDS_RESAMPLE) {
-                (t.get()->*t->hook)(outTemp, numFrames, mResampleTemp.get() /* naked ptr */, aux);
-            } else {
-
-                size_t outFrames = 0;
-
-                while (outFrames < numFrames) {
-                    t->buffer.frameCount = numFrames - outFrames;
-                    t->bufferProvider->getNextBuffer(&t->buffer);
-                    t->mIn = t->buffer.raw;
-                    // t->mIn == nullptr can happen if the track was flushed just after having
-                    // been enabled for mixing.
-                    if (t->mIn == nullptr) break;
-
-                    (t.get()->*t->hook)(
-                            outTemp + outFrames * t->mMixerChannelCount, t->buffer.frameCount,
-                            mResampleTemp.get() /* naked ptr */,
-                            aux != nullptr ? aux + outFrames : nullptr);
-                    outFrames += t->buffer.frameCount;
-
-                    t->bufferProvider->releaseBuffer(&t->buffer);
-                }
-            }
-        }
-        convertMixerFormat(t1->mainBuffer, t1->mMixerFormat,
-                outTemp, t1->mMixerInFormat, numFrames * t1->mMixerChannelCount);
-    }
-}
-
-// one track, 16 bits stereo without resampling is the most common case
-void AudioMixer::process__oneTrack16BitsStereoNoResampling()
-{
-    ALOGVV("process__oneTrack16BitsStereoNoResampling\n");
-    LOG_ALWAYS_FATAL_IF(mEnabled.size() != 0,
-            "%zu != 1 tracks enabled", mEnabled.size());
-    const int name = mEnabled[0];
-    const std::shared_ptr<Track> &t = mTracks[name];
-
-    AudioBufferProvider::Buffer& b(t->buffer);
-
-    int32_t* out = t->mainBuffer;
-    float *fout = reinterpret_cast<float*>(out);
-    size_t numFrames = mFrameCount;
-
-    const int16_t vl = t->volume[0];
-    const int16_t vr = t->volume[1];
-    const uint32_t vrl = t->volumeRL;
-    while (numFrames) {
-        b.frameCount = numFrames;
-        t->bufferProvider->getNextBuffer(&b);
-        const int16_t *in = b.i16;
-
-        // in == NULL can happen if the track was flushed just after having
-        // been enabled for mixing.
-        if (in == NULL || (((uintptr_t)in) & 3)) {
-            if ( AUDIO_FORMAT_PCM_FLOAT == t->mMixerFormat ) {
-                 memset((char*)fout, 0, numFrames
-                         * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
-            } else {
-                 memset((char*)out, 0, numFrames
-                         * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
-            }
-            ALOGE_IF((((uintptr_t)in) & 3),
-                    "process__oneTrack16BitsStereoNoResampling: misaligned buffer"
-                    " %p track %d, channels %d, needs %08x, volume %08x vfl %f vfr %f",
-                    in, name, t->channelCount, t->needs, vrl, t->mVolume[0], t->mVolume[1]);
-            return;
-        }
-        size_t outFrames = b.frameCount;
-
-        switch (t->mMixerFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            do {
-                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                in += 2;
-                int32_t l = mulRL(1, rl, vrl);
-                int32_t r = mulRL(0, rl, vrl);
-                *fout++ = float_from_q4_27(l);
-                *fout++ = float_from_q4_27(r);
-                // Note: In case of later int16_t sink output,
-                // conversion and clamping is done by memcpy_to_i16_from_float().
-            } while (--outFrames);
-            break;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) {
-                // volume is boosted, so we might need to clamp even though
-                // we process only one track.
-                do {
-                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                    in += 2;
-                    int32_t l = mulRL(1, rl, vrl) >> 12;
-                    int32_t r = mulRL(0, rl, vrl) >> 12;
-                    // clamping...
-                    l = clamp16(l);
-                    r = clamp16(r);
-                    *out++ = (r<<16) | (l & 0xFFFF);
-                } while (--outFrames);
-            } else {
-                do {
-                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                    in += 2;
-                    int32_t l = mulRL(1, rl, vrl) >> 12;
-                    int32_t r = mulRL(0, rl, vrl) >> 12;
-                    *out++ = (r<<16) | (l & 0xFFFF);
-                } while (--outFrames);
-            }
-            break;
-        default:
-            LOG_ALWAYS_FATAL("bad mixer format: %d", t->mMixerFormat);
-        }
-        numFrames -= b.frameCount;
-        t->bufferProvider->releaseBuffer(&b);
-    }
-}
-
 /*static*/ pthread_once_t AudioMixer::sOnceControl = PTHREAD_ONCE_INIT;
 
 /*static*/ void AudioMixer::sInitRoutine()
@@ -1656,211 +523,71 @@
     DownmixerBufferProvider::init(); // for the downmixer
 }
 
-/* TODO: consider whether this level of optimization is necessary.
- * Perhaps just stick with a single for loop.
- */
-
-// Needs to derive a compile time constant (constexpr).  Could be targeted to go
-// to a MONOVOL mixtype based on MAX_NUM_VOLUMES, but that's an unnecessary complication.
-#define MIXTYPE_MONOVOL(mixtype) ((mixtype) == MIXTYPE_MULTI ? MIXTYPE_MULTI_MONOVOL : \
-        (mixtype) == MIXTYPE_MULTI_SAVEONLY ? MIXTYPE_MULTI_SAVEONLY_MONOVOL : (mixtype))
-
-/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE,
-        typename TO, typename TI, typename TV, typename TA, typename TAV>
-static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount,
-        const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc)
+std::shared_ptr<AudioMixerBase::TrackBase> AudioMixer::preCreateTrack()
 {
-    switch (channels) {
-    case 1:
-        volumeRampMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 2:
-        volumeRampMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 3:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 4:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 5:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 6:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 7:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 8:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    }
+    return std::make_shared<Track>();
 }
 
-/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE,
-        typename TO, typename TI, typename TV, typename TA, typename TAV>
-static void volumeMulti(uint32_t channels, TO* out, size_t frameCount,
-        const TI* in, TA* aux, const TV *vol, TAV vola)
+status_t AudioMixer::postCreateTrack(TrackBase *track)
 {
-    switch (channels) {
-    case 1:
-        volumeMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 2:
-        volumeMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 3:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 4:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 5:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 6:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 7:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 8:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out, frameCount, in, aux, vol, vola);
-        break;
+    Track* t = static_cast<Track*>(track);
+
+    audio_channel_mask_t channelMask = t->channelMask;
+    t->mHapticChannelMask = channelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+    t->mHapticChannelCount = audio_channel_count_from_out_mask(t->mHapticChannelMask);
+    channelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
+    t->channelCount = audio_channel_count_from_out_mask(channelMask);
+    ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
+            "Non-stereo channel mask: %d\n", channelMask);
+    t->channelMask = channelMask;
+    t->mInputBufferProvider = NULL;
+    t->mDownmixRequiresFormat = AUDIO_FORMAT_INVALID; // no format required
+    t->mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
+    // haptic
+    t->mHapticPlaybackEnabled = false;
+    t->mHapticIntensity = HAPTIC_SCALE_NONE;
+    t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
+    t->mMixerHapticChannelCount = 0;
+    t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
+    t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
+    t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
+    t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
+    t->mKeepContractedChannels = false;
+    // Check the downmixing (or upmixing) requirements.
+    status_t status = t->prepareForDownmix();
+    if (status != OK) {
+        ALOGE("AudioMixer::getTrackName invalid channelMask (%#x)", channelMask);
+        return BAD_VALUE;
     }
+    // prepareForDownmix() may change mDownmixRequiresFormat
+    ALOGVV("mMixerFormat:%#x  mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat);
+    t->prepareForReformat();
+    t->prepareForAdjustChannelsNonDestructive(mFrameCount);
+    t->prepareForAdjustChannels();
+    return OK;
 }
 
-/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * USEFLOATVOL (set to true if float volume is used)
- * ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
-    typename TO, typename TI, typename TA>
-void AudioMixer::Track::volumeMix(TO *out, size_t outFrames,
-        const TI *in, TA *aux, bool ramp)
+void AudioMixer::preProcess()
 {
-    if (USEFLOATVOL) {
-        if (ramp) {
-            volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
-                    mPrevVolume, mVolumeInc,
-#ifdef FLOAT_AUX
-                    &mPrevAuxLevel, mAuxInc
-#else
-                    &prevAuxLevel, auxInc
-#endif
-                );
-            if (ADJUSTVOL) {
-                adjustVolumeRamp(aux != NULL, true);
-            }
-        } else {
-            volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
-                    mVolume,
-#ifdef FLOAT_AUX
-                    mAuxLevel
-#else
-                    auxLevel
-#endif
-            );
-        }
-    } else {
-        if (ramp) {
-            volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
-                    prevVolume, volumeInc, &prevAuxLevel, auxInc);
-            if (ADJUSTVOL) {
-                adjustVolumeRamp(aux != NULL);
-            }
-        } else {
-            volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
-                    volume, auxLevel);
+    for (const auto &pair : mTracks) {
+        // Clear contracted buffer before processing if contracted channels are saved
+        const std::shared_ptr<TrackBase> &tb = pair.second;
+        Track *t = static_cast<Track*>(tb.get());
+        if (t->mKeepContractedChannels) {
+            t->clearContractedBuffer();
         }
     }
 }
 
-/* This process hook is called when there is a single track without
- * aux buffer, volume ramp, or resampling.
- * TODO: Update the hook selection: this can properly handle aux and ramp.
- *
- * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27)
- */
-template <int MIXTYPE, typename TO, typename TI, typename TA>
-void AudioMixer::process__noResampleOneTrack()
+void AudioMixer::postProcess()
 {
-    ALOGVV("process__noResampleOneTrack\n");
-    LOG_ALWAYS_FATAL_IF(mEnabled.size() != 1,
-            "%zu != 1 tracks enabled", mEnabled.size());
-    const std::shared_ptr<Track> &t = mTracks[mEnabled[0]];
-    const uint32_t channels = t->mMixerChannelCount;
-    TO* out = reinterpret_cast<TO*>(t->mainBuffer);
-    TA* aux = reinterpret_cast<TA*>(t->auxBuffer);
-    const bool ramp = t->needsRamp();
-
-    for (size_t numFrames = mFrameCount; numFrames > 0; ) {
-        AudioBufferProvider::Buffer& b(t->buffer);
-        // get input buffer
-        b.frameCount = numFrames;
-        t->bufferProvider->getNextBuffer(&b);
-        const TI *in = reinterpret_cast<TI*>(b.raw);
-
-        // in == NULL can happen if the track was flushed just after having
-        // been enabled for mixing.
-        if (in == NULL || (((uintptr_t)in) & 3)) {
-            memset(out, 0, numFrames
-                    * channels * audio_bytes_per_sample(t->mMixerFormat));
-            ALOGE_IF((((uintptr_t)in) & 3), "process__noResampleOneTrack: bus error: "
-                    "buffer %p track %p, channels %d, needs %#x",
-                    in, &t, t->channelCount, t->needs);
-            return;
-        }
-
-        const size_t outFrames = b.frameCount;
-        t->volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, false /* ADJUSTVOL */> (
-                out, outFrames, in, aux, ramp);
-
-        out += outFrames * channels;
-        if (aux != NULL) {
-            aux += outFrames;
-        }
-        numFrames -= b.frameCount;
-
-        // release buffer
-        t->bufferProvider->releaseBuffer(&b);
-    }
-    if (ramp) {
-        t->adjustVolumeRamp(aux != NULL, is_same<TI, float>::value);
-    }
-}
-
-void AudioMixer::processHapticData()
-{
+    // Process haptic data.
     // Need to keep consistent with VibrationEffect.scale(int, float, int)
     for (const auto &pair : mGroups) {
         // process by group of tracks with same output main buffer.
         const auto &group = pair.second;
         for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
+            const std::shared_ptr<Track> &t = getTrack(name);
             if (t->mHapticPlaybackEnabled) {
                 size_t sampleCount = mFrameCount * t->mMixerHapticChannelCount;
                 float gamma = t->getHapticScaleGamma();
@@ -1887,225 +614,5 @@
     }
 }
 
-/* This track hook is called to do resampling then mixing,
- * pulling from the track's upstream AudioBufferProvider.
- *
- * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE, typename TO, typename TI, typename TA>
-void AudioMixer::Track::track__Resample(TO* out, size_t outFrameCount, TO* temp, TA* aux)
-{
-    ALOGVV("track__Resample\n");
-    mResampler->setSampleRate(sampleRate);
-    const bool ramp = needsRamp();
-    if (ramp || aux != NULL) {
-        // if ramp:        resample with unity gain to temp buffer and scale/mix in 2nd step.
-        // if aux != NULL: resample with unity gain to temp buffer then apply send level.
-
-        mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
-        memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(TO));
-        mResampler->resample((int32_t*)temp, outFrameCount, bufferProvider);
-
-        volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
-                out, outFrameCount, temp, aux, ramp);
-
-    } else { // constant volume gain
-        mResampler->setVolume(mVolume[0], mVolume[1]);
-        mResampler->resample((int32_t*)out, outFrameCount, bufferProvider);
-    }
-}
-
-/* This track hook is called to mix a track, when no resampling is required.
- * The input buffer should be present in in.
- *
- * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE, typename TO, typename TI, typename TA>
-void AudioMixer::Track::track__NoResample(TO* out, size_t frameCount, TO* temp __unused, TA* aux)
-{
-    ALOGVV("track__NoResample\n");
-    const TI *in = static_cast<const TI *>(mIn);
-
-    volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
-            out, frameCount, in, aux, needsRamp());
-
-    // MIXTYPE_MONOEXPAND reads a single input channel and expands to NCHAN output channels.
-    // MIXTYPE_MULTI reads NCHAN input channels and places to NCHAN output channels.
-    in += (MIXTYPE == MIXTYPE_MONOEXPAND) ? frameCount : frameCount * mMixerChannelCount;
-    mIn = in;
-}
-
-/* The Mixer engine generates either int32_t (Q4_27) or float data.
- * We use this function to convert the engine buffers
- * to the desired mixer output format, either int16_t (Q.15) or float.
- */
-/* static */
-void AudioMixer::convertMixerFormat(void *out, audio_format_t mixerOutFormat,
-        void *in, audio_format_t mixerInFormat, size_t sampleCount)
-{
-    switch (mixerInFormat) {
-    case AUDIO_FORMAT_PCM_FLOAT:
-        switch (mixerOutFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            memcpy(out, in, sampleCount * sizeof(float)); // MEMCPY. TODO optimize out
-            break;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            memcpy_to_i16_from_float((int16_t*)out, (float*)in, sampleCount);
-            break;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
-            break;
-        }
-        break;
-    case AUDIO_FORMAT_PCM_16_BIT:
-        switch (mixerOutFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            memcpy_to_float_from_q4_27((float*)out, (const int32_t*)in, sampleCount);
-            break;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            memcpy_to_i16_from_q4_27((int16_t*)out, (const int32_t*)in, sampleCount);
-            break;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
-            break;
-        }
-        break;
-    default:
-        LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-        break;
-    }
-}
-
-/* Returns the proper track hook to use for mixing the track into the output buffer.
- */
-/* static */
-AudioMixer::hook_t AudioMixer::Track::getTrackHook(int trackType, uint32_t channelCount,
-        audio_format_t mixerInFormat, audio_format_t mixerOutFormat __unused)
-{
-    if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
-        switch (trackType) {
-        case TRACKTYPE_NOP:
-            return &Track::track__nop;
-        case TRACKTYPE_RESAMPLE:
-            return &Track::track__genericResample;
-        case TRACKTYPE_NORESAMPLEMONO:
-            return &Track::track__16BitsMono;
-        case TRACKTYPE_NORESAMPLE:
-            return &Track::track__16BitsStereo;
-        default:
-            LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
-            break;
-        }
-    }
-    LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
-    switch (trackType) {
-    case TRACKTYPE_NOP:
-        return &Track::track__nop;
-    case TRACKTYPE_RESAMPLE:
-        switch (mixerInFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return (AudioMixer::hook_t) &Track::track__Resample<
-                    MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return (AudioMixer::hook_t) &Track::track__Resample<
-                    MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-            break;
-        }
-        break;
-    case TRACKTYPE_NORESAMPLEMONO:
-        switch (mixerInFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return (AudioMixer::hook_t) &Track::track__NoResample<
-                            MIXTYPE_MONOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return (AudioMixer::hook_t) &Track::track__NoResample<
-                            MIXTYPE_MONOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-            break;
-        }
-        break;
-    case TRACKTYPE_NORESAMPLE:
-        switch (mixerInFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return (AudioMixer::hook_t) &Track::track__NoResample<
-                    MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return (AudioMixer::hook_t) &Track::track__NoResample<
-                    MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-            break;
-        }
-        break;
-    default:
-        LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
-        break;
-    }
-    return NULL;
-}
-
-/* Returns the proper process hook for mixing tracks. Currently works only for
- * PROCESSTYPE_NORESAMPLEONETRACK, a mix involving one track, no resampling.
- *
- * TODO: Due to the special mixing considerations of duplicating to
- * a stereo output track, the input track cannot be MONO.  This should be
- * prevented by the caller.
- */
-/* static */
-AudioMixer::process_hook_t AudioMixer::getProcessHook(
-        int processType, uint32_t channelCount,
-        audio_format_t mixerInFormat, audio_format_t mixerOutFormat)
-{
-    if (processType != PROCESSTYPE_NORESAMPLEONETRACK) { // Only NORESAMPLEONETRACK
-        LOG_ALWAYS_FATAL("bad processType: %d", processType);
-        return NULL;
-    }
-    if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
-        return &AudioMixer::process__oneTrack16BitsStereoNoResampling;
-    }
-    LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
-    switch (mixerInFormat) {
-    case AUDIO_FORMAT_PCM_FLOAT:
-        switch (mixerOutFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return &AudioMixer::process__noResampleOneTrack<
-                    MIXTYPE_MULTI_SAVEONLY, float /*TO*/, float /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return &AudioMixer::process__noResampleOneTrack<
-                    MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, float /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
-            break;
-        }
-        break;
-    case AUDIO_FORMAT_PCM_16_BIT:
-        switch (mixerOutFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return &AudioMixer::process__noResampleOneTrack<
-                    MIXTYPE_MULTI_SAVEONLY, float /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return &AudioMixer::process__noResampleOneTrack<
-                    MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
-            break;
-        }
-        break;
-    default:
-        LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-        break;
-    }
-    return NULL;
-}
-
 // ----------------------------------------------------------------------------
 } // namespace android
diff --git a/media/libaudioprocessing/AudioMixerBase.cpp b/media/libaudioprocessing/AudioMixerBase.cpp
new file mode 100644
index 0000000..75c077d
--- /dev/null
+++ b/media/libaudioprocessing/AudioMixerBase.cpp
@@ -0,0 +1,1692 @@
+/*
+**
+** Copyright 2019, 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 "AudioMixer"
+//#define LOG_NDEBUG 0
+
+#include <sstream>
+#include <string.h>
+
+#include <audio_utils/primitives.h>
+#include <cutils/compiler.h>
+#include <media/AudioMixerBase.h>
+#include <utils/Log.h>
+
+#include "AudioMixerOps.h"
+
+// The FCC_2 macro refers to the Fixed Channel Count of 2 for the legacy integer mixer.
+#ifndef FCC_2
+#define FCC_2 2
+#endif
+
+// Look for MONO_HACK for any Mono hack involving legacy mono channel to
+// stereo channel conversion.
+
+/* VERY_VERY_VERBOSE_LOGGING will show exactly which process hook and track hook is
+ * being used. This is a considerable amount of log spam, so don't enable unless you
+ * are verifying the hook based code.
+ */
+//#define VERY_VERY_VERBOSE_LOGGING
+#ifdef VERY_VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+//define ALOGVV printf  // for test-mixer.cpp
+#else
+#define ALOGVV(a...) do { } while (0)
+#endif
+
+// TODO: remove BLOCKSIZE unit of processing - it isn't needed anymore.
+static constexpr int BLOCKSIZE = 16;
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+bool AudioMixerBase::isValidFormat(audio_format_t format) const
+{
+    switch (format) {
+    case AUDIO_FORMAT_PCM_8_BIT:
+    case AUDIO_FORMAT_PCM_16_BIT:
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+    case AUDIO_FORMAT_PCM_32_BIT:
+    case AUDIO_FORMAT_PCM_FLOAT:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool AudioMixerBase::isValidChannelMask(audio_channel_mask_t channelMask) const
+{
+    return audio_channel_count_from_out_mask(channelMask) <= MAX_NUM_CHANNELS;
+}
+
+std::shared_ptr<AudioMixerBase::TrackBase> AudioMixerBase::preCreateTrack()
+{
+    return std::make_shared<TrackBase>();
+}
+
+status_t AudioMixerBase::create(
+        int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId)
+{
+    LOG_ALWAYS_FATAL_IF(exists(name), "name %d already exists", name);
+
+    if (!isValidChannelMask(channelMask)) {
+        ALOGE("%s invalid channelMask: %#x", __func__, channelMask);
+        return BAD_VALUE;
+    }
+    if (!isValidFormat(format)) {
+        ALOGE("%s invalid format: %#x", __func__, format);
+        return BAD_VALUE;
+    }
+
+    auto t = preCreateTrack();
+    {
+        // TODO: move initialization to the Track constructor.
+        // assume default parameters for the track, except where noted below
+        t->needs = 0;
+
+        // Integer volume.
+        // Currently integer volume is kept for the legacy integer mixer.
+        // Will be removed when the legacy mixer path is removed.
+        t->volume[0] = 0;
+        t->volume[1] = 0;
+        t->prevVolume[0] = 0 << 16;
+        t->prevVolume[1] = 0 << 16;
+        t->volumeInc[0] = 0;
+        t->volumeInc[1] = 0;
+        t->auxLevel = 0;
+        t->auxInc = 0;
+        t->prevAuxLevel = 0;
+
+        // Floating point volume.
+        t->mVolume[0] = 0.f;
+        t->mVolume[1] = 0.f;
+        t->mPrevVolume[0] = 0.f;
+        t->mPrevVolume[1] = 0.f;
+        t->mVolumeInc[0] = 0.;
+        t->mVolumeInc[1] = 0.;
+        t->mAuxLevel = 0.;
+        t->mAuxInc = 0.;
+        t->mPrevAuxLevel = 0.;
+
+        // no initialization needed
+        // t->frameCount
+        t->channelCount = audio_channel_count_from_out_mask(channelMask);
+        t->enabled = false;
+        ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
+                "Non-stereo channel mask: %d\n", channelMask);
+        t->channelMask = channelMask;
+        t->sessionId = sessionId;
+        // setBufferProvider(name, AudioBufferProvider *) is required before enable(name)
+        t->bufferProvider = NULL;
+        t->buffer.raw = NULL;
+        // no initialization needed
+        // t->buffer.frameCount
+        t->hook = NULL;
+        t->mIn = NULL;
+        t->sampleRate = mSampleRate;
+        // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
+        t->mainBuffer = NULL;
+        t->auxBuffer = NULL;
+        t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
+        t->mFormat = format;
+        t->mMixerInFormat = kUseFloat && kUseNewMixer ?
+                AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
+        t->mMixerChannelMask = audio_channel_mask_from_representation_and_bits(
+                AUDIO_CHANNEL_REPRESENTATION_POSITION, AUDIO_CHANNEL_OUT_STEREO);
+        t->mMixerChannelCount = audio_channel_count_from_out_mask(t->mMixerChannelMask);
+        status_t status = postCreateTrack(t.get());
+        if (status != OK) return status;
+        mTracks[name] = t;
+        return OK;
+    }
+}
+
+// Called when channel masks have changed for a track name
+bool AudioMixerBase::setChannelMasks(int name,
+        audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    const std::shared_ptr<TrackBase> &track = mTracks[name];
+
+    if (trackChannelMask == track->channelMask && mixerChannelMask == track->mMixerChannelMask) {
+        return false;  // no need to change
+    }
+    // always recompute for both channel masks even if only one has changed.
+    const uint32_t trackChannelCount = audio_channel_count_from_out_mask(trackChannelMask);
+    const uint32_t mixerChannelCount = audio_channel_count_from_out_mask(mixerChannelMask);
+
+    ALOG_ASSERT(trackChannelCount && mixerChannelCount);
+    track->channelMask = trackChannelMask;
+    track->channelCount = trackChannelCount;
+    track->mMixerChannelMask = mixerChannelMask;
+    track->mMixerChannelCount = mixerChannelCount;
+
+    // Resampler channels may have changed.
+    track->recreateResampler(mSampleRate);
+    return true;
+}
+
+void AudioMixerBase::destroy(int name)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    ALOGV("deleteTrackName(%d)", name);
+
+    if (mTracks[name]->enabled) {
+        invalidate();
+    }
+    mTracks.erase(name); // deallocate track
+}
+
+void AudioMixerBase::enable(int name)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    const std::shared_ptr<TrackBase> &track = mTracks[name];
+
+    if (!track->enabled) {
+        track->enabled = true;
+        ALOGV("enable(%d)", name);
+        invalidate();
+    }
+}
+
+void AudioMixerBase::disable(int name)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    const std::shared_ptr<TrackBase> &track = mTracks[name];
+
+    if (track->enabled) {
+        track->enabled = false;
+        ALOGV("disable(%d)", name);
+        invalidate();
+    }
+}
+
+/* Sets the volume ramp variables for the AudioMixer.
+ *
+ * The volume ramp variables are used to transition from the previous
+ * volume to the set volume.  ramp controls the duration of the transition.
+ * Its value is typically one state framecount period, but may also be 0,
+ * meaning "immediate."
+ *
+ * FIXME: 1) Volume ramp is enabled only if there is a nonzero integer increment
+ * even if there is a nonzero floating point increment (in that case, the volume
+ * change is immediate).  This restriction should be changed when the legacy mixer
+ * is removed (see #2).
+ * FIXME: 2) Integer volume variables are used for Legacy mixing and should be removed
+ * when no longer needed.
+ *
+ * @param newVolume set volume target in floating point [0.0, 1.0].
+ * @param ramp number of frames to increment over. if ramp is 0, the volume
+ * should be set immediately.  Currently ramp should not exceed 65535 (frames).
+ * @param pIntSetVolume pointer to the U4.12 integer target volume, set on return.
+ * @param pIntPrevVolume pointer to the U4.28 integer previous volume, set on return.
+ * @param pIntVolumeInc pointer to the U4.28 increment per output audio frame, set on return.
+ * @param pSetVolume pointer to the float target volume, set on return.
+ * @param pPrevVolume pointer to the float previous volume, set on return.
+ * @param pVolumeInc pointer to the float increment per output audio frame, set on return.
+ * @return true if the volume has changed, false if volume is same.
+ */
+static inline bool setVolumeRampVariables(float newVolume, int32_t ramp,
+        int16_t *pIntSetVolume, int32_t *pIntPrevVolume, int32_t *pIntVolumeInc,
+        float *pSetVolume, float *pPrevVolume, float *pVolumeInc) {
+    // check floating point volume to see if it is identical to the previously
+    // set volume.
+    // We do not use a tolerance here (and reject changes too small)
+    // as it may be confusing to use a different value than the one set.
+    // If the resulting volume is too small to ramp, it is a direct set of the volume.
+    if (newVolume == *pSetVolume) {
+        return false;
+    }
+    if (newVolume < 0) {
+        newVolume = 0; // should not have negative volumes
+    } else {
+        switch (fpclassify(newVolume)) {
+        case FP_SUBNORMAL:
+        case FP_NAN:
+            newVolume = 0;
+            break;
+        case FP_ZERO:
+            break; // zero volume is fine
+        case FP_INFINITE:
+            // Infinite volume could be handled consistently since
+            // floating point math saturates at infinities,
+            // but we limit volume to unity gain float.
+            // ramp = 0; break;
+            //
+            newVolume = AudioMixerBase::UNITY_GAIN_FLOAT;
+            break;
+        case FP_NORMAL:
+        default:
+            // Floating point does not have problems with overflow wrap
+            // that integer has.  However, we limit the volume to
+            // unity gain here.
+            // TODO: Revisit the volume limitation and perhaps parameterize.
+            if (newVolume > AudioMixerBase::UNITY_GAIN_FLOAT) {
+                newVolume = AudioMixerBase::UNITY_GAIN_FLOAT;
+            }
+            break;
+        }
+    }
+
+    // set floating point volume ramp
+    if (ramp != 0) {
+        // when the ramp completes, *pPrevVolume is set to *pSetVolume, so there
+        // is no computational mismatch; hence equality is checked here.
+        ALOGD_IF(*pPrevVolume != *pSetVolume, "previous float ramp hasn't finished,"
+                " prev:%f  set_to:%f", *pPrevVolume, *pSetVolume);
+        const float inc = (newVolume - *pPrevVolume) / ramp; // could be inf, nan, subnormal
+        // could be inf, cannot be nan, subnormal
+        const float maxv = std::max(newVolume, *pPrevVolume);
+
+        if (isnormal(inc) // inc must be a normal number (no subnormals, infinite, nan)
+                && maxv + inc != maxv) { // inc must make forward progress
+            *pVolumeInc = inc;
+            // ramp is set now.
+            // Note: if newVolume is 0, then near the end of the ramp,
+            // it may be possible that the ramped volume may be subnormal or
+            // temporarily negative by a small amount or subnormal due to floating
+            // point inaccuracies.
+        } else {
+            ramp = 0; // ramp not allowed
+        }
+    }
+
+    // compute and check integer volume, no need to check negative values
+    // The integer volume is limited to "unity_gain" to avoid wrapping and other
+    // audio artifacts, so it never reaches the range limit of U4.28.
+    // We safely use signed 16 and 32 bit integers here.
+    const float scaledVolume = newVolume * AudioMixerBase::UNITY_GAIN_INT; // not neg, subnormal, nan
+    const int32_t intVolume = (scaledVolume >= (float)AudioMixerBase::UNITY_GAIN_INT) ?
+            AudioMixerBase::UNITY_GAIN_INT : (int32_t)scaledVolume;
+
+    // set integer volume ramp
+    if (ramp != 0) {
+        // integer volume is U4.12 (to use 16 bit multiplies), but ramping uses U4.28.
+        // when the ramp completes, *pIntPrevVolume is set to *pIntSetVolume << 16, so there
+        // is no computational mismatch; hence equality is checked here.
+        ALOGD_IF(*pIntPrevVolume != *pIntSetVolume << 16, "previous int ramp hasn't finished,"
+                " prev:%d  set_to:%d", *pIntPrevVolume, *pIntSetVolume << 16);
+        const int32_t inc = ((intVolume << 16) - *pIntPrevVolume) / ramp;
+
+        if (inc != 0) { // inc must make forward progress
+            *pIntVolumeInc = inc;
+        } else {
+            ramp = 0; // ramp not allowed
+        }
+    }
+
+    // if no ramp, or ramp not allowed, then clear float and integer increments
+    if (ramp == 0) {
+        *pVolumeInc = 0;
+        *pPrevVolume = newVolume;
+        *pIntVolumeInc = 0;
+        *pIntPrevVolume = intVolume << 16;
+    }
+    *pSetVolume = newVolume;
+    *pIntSetVolume = intVolume;
+    return true;
+}
+
+void AudioMixerBase::setParameter(int name, int target, int param, void *value)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    const std::shared_ptr<TrackBase> &track = mTracks[name];
+
+    int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value));
+    int32_t *valueBuf = reinterpret_cast<int32_t*>(value);
+
+    switch (target) {
+
+    case TRACK:
+        switch (param) {
+        case CHANNEL_MASK: {
+            const audio_channel_mask_t trackChannelMask =
+                static_cast<audio_channel_mask_t>(valueInt);
+            if (setChannelMasks(name, trackChannelMask, track->mMixerChannelMask)) {
+                ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", trackChannelMask);
+                invalidate();
+            }
+            } break;
+        case MAIN_BUFFER:
+            if (track->mainBuffer != valueBuf) {
+                track->mainBuffer = valueBuf;
+                ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
+                invalidate();
+            }
+            break;
+        case AUX_BUFFER:
+            if (track->auxBuffer != valueBuf) {
+                track->auxBuffer = valueBuf;
+                ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
+                invalidate();
+            }
+            break;
+        case FORMAT: {
+            audio_format_t format = static_cast<audio_format_t>(valueInt);
+            if (track->mFormat != format) {
+                ALOG_ASSERT(audio_is_linear_pcm(format), "Invalid format %#x", format);
+                track->mFormat = format;
+                ALOGV("setParameter(TRACK, FORMAT, %#x)", format);
+                invalidate();
+            }
+            } break;
+        case MIXER_FORMAT: {
+            audio_format_t format = static_cast<audio_format_t>(valueInt);
+            if (track->mMixerFormat != format) {
+                track->mMixerFormat = format;
+                ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
+            }
+            } break;
+        case MIXER_CHANNEL_MASK: {
+            const audio_channel_mask_t mixerChannelMask =
+                    static_cast<audio_channel_mask_t>(valueInt);
+            if (setChannelMasks(name, track->channelMask, mixerChannelMask)) {
+                ALOGV("setParameter(TRACK, MIXER_CHANNEL_MASK, %#x)", mixerChannelMask);
+                invalidate();
+            }
+            } break;
+        default:
+            LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
+        }
+        break;
+
+    case RESAMPLE:
+        switch (param) {
+        case SAMPLE_RATE:
+            ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
+            if (track->setResampler(uint32_t(valueInt), mSampleRate)) {
+                ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
+                        uint32_t(valueInt));
+                invalidate();
+            }
+            break;
+        case RESET:
+            track->resetResampler();
+            invalidate();
+            break;
+        case REMOVE:
+            track->mResampler.reset(nullptr);
+            track->sampleRate = mSampleRate;
+            invalidate();
+            break;
+        default:
+            LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param);
+        }
+        break;
+
+    case RAMP_VOLUME:
+    case VOLUME:
+        switch (param) {
+        case AUXLEVEL:
+            if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
+                    target == RAMP_VOLUME ? mFrameCount : 0,
+                    &track->auxLevel, &track->prevAuxLevel, &track->auxInc,
+                    &track->mAuxLevel, &track->mPrevAuxLevel, &track->mAuxInc)) {
+                ALOGV("setParameter(%s, AUXLEVEL: %04x)",
+                        target == VOLUME ? "VOLUME" : "RAMP_VOLUME", track->auxLevel);
+                invalidate();
+            }
+            break;
+        default:
+            if ((unsigned)param >= VOLUME0 && (unsigned)param < VOLUME0 + MAX_NUM_VOLUMES) {
+                if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
+                        target == RAMP_VOLUME ? mFrameCount : 0,
+                        &track->volume[param - VOLUME0],
+                        &track->prevVolume[param - VOLUME0],
+                        &track->volumeInc[param - VOLUME0],
+                        &track->mVolume[param - VOLUME0],
+                        &track->mPrevVolume[param - VOLUME0],
+                        &track->mVolumeInc[param - VOLUME0])) {
+                    ALOGV("setParameter(%s, VOLUME%d: %04x)",
+                            target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
+                                    track->volume[param - VOLUME0]);
+                    invalidate();
+                }
+            } else {
+                LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
+            }
+        }
+        break;
+
+    default:
+        LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
+    }
+}
+
+bool AudioMixerBase::TrackBase::setResampler(uint32_t trackSampleRate, uint32_t devSampleRate)
+{
+    if (trackSampleRate != devSampleRate || mResampler.get() != nullptr) {
+        if (sampleRate != trackSampleRate) {
+            sampleRate = trackSampleRate;
+            if (mResampler.get() == nullptr) {
+                ALOGV("Creating resampler from track %d Hz to device %d Hz",
+                        trackSampleRate, devSampleRate);
+                AudioResampler::src_quality quality;
+                // force lowest quality level resampler if use case isn't music or video
+                // FIXME this is flawed for dynamic sample rates, as we choose the resampler
+                // quality level based on the initial ratio, but that could change later.
+                // Should have a way to distinguish tracks with static ratios vs. dynamic ratios.
+                if (isMusicRate(trackSampleRate)) {
+                    quality = AudioResampler::DEFAULT_QUALITY;
+                } else {
+                    quality = AudioResampler::DYN_LOW_QUALITY;
+                }
+
+                // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer
+                // but if none exists, it is the channel count (1 for mono).
+                const int resamplerChannelCount = getOutputChannelCount();
+                ALOGVV("Creating resampler:"
+                        " format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n",
+                        mMixerInFormat, resamplerChannelCount, devSampleRate, quality);
+                mResampler.reset(AudioResampler::create(
+                        mMixerInFormat,
+                        resamplerChannelCount,
+                        devSampleRate, quality));
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+/* Checks to see if the volume ramp has completed and clears the increment
+ * variables appropriately.
+ *
+ * FIXME: There is code to handle int/float ramp variable switchover should it not
+ * complete within a mixer buffer processing call, but it is preferred to avoid switchover
+ * due to precision issues.  The switchover code is included for legacy code purposes
+ * and can be removed once the integer volume is removed.
+ *
+ * It is not sufficient to clear only the volumeInc integer variable because
+ * if one channel requires ramping, all channels are ramped.
+ *
+ * There is a bit of duplicated code here, but it keeps backward compatibility.
+ */
+void AudioMixerBase::TrackBase::adjustVolumeRamp(bool aux, bool useFloat)
+{
+    if (useFloat) {
+        for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
+            if ((mVolumeInc[i] > 0 && mPrevVolume[i] + mVolumeInc[i] >= mVolume[i]) ||
+                     (mVolumeInc[i] < 0 && mPrevVolume[i] + mVolumeInc[i] <= mVolume[i])) {
+                volumeInc[i] = 0;
+                prevVolume[i] = volume[i] << 16;
+                mVolumeInc[i] = 0.;
+                mPrevVolume[i] = mVolume[i];
+            } else {
+                //ALOGV("ramp: %f %f %f", mVolume[i], mPrevVolume[i], mVolumeInc[i]);
+                prevVolume[i] = u4_28_from_float(mPrevVolume[i]);
+            }
+        }
+    } else {
+        for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
+            if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
+                    ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
+                volumeInc[i] = 0;
+                prevVolume[i] = volume[i] << 16;
+                mVolumeInc[i] = 0.;
+                mPrevVolume[i] = mVolume[i];
+            } else {
+                //ALOGV("ramp: %d %d %d", volume[i] << 16, prevVolume[i], volumeInc[i]);
+                mPrevVolume[i]  = float_from_u4_28(prevVolume[i]);
+            }
+        }
+    }
+
+    if (aux) {
+#ifdef FLOAT_AUX
+        if (useFloat) {
+            if ((mAuxInc > 0.f && mPrevAuxLevel + mAuxInc >= mAuxLevel) ||
+                    (mAuxInc < 0.f && mPrevAuxLevel + mAuxInc <= mAuxLevel)) {
+                auxInc = 0;
+                prevAuxLevel = auxLevel << 16;
+                mAuxInc = 0.f;
+                mPrevAuxLevel = mAuxLevel;
+            }
+        } else
+#endif
+        if ((auxInc > 0 && ((prevAuxLevel + auxInc) >> 16) >= auxLevel) ||
+                (auxInc < 0 && ((prevAuxLevel + auxInc) >> 16) <= auxLevel)) {
+            auxInc = 0;
+            prevAuxLevel = auxLevel << 16;
+            mAuxInc = 0.f;
+            mPrevAuxLevel = mAuxLevel;
+        }
+    }
+}
+
+void AudioMixerBase::TrackBase::recreateResampler(uint32_t devSampleRate)
+{
+    if (mResampler.get() != nullptr) {
+        const uint32_t resetToSampleRate = sampleRate;
+        mResampler.reset(nullptr);
+        sampleRate = devSampleRate; // without resampler, track rate is device sample rate.
+        // recreate the resampler with updated format, channels, saved sampleRate.
+        setResampler(resetToSampleRate /*trackSampleRate*/, devSampleRate);
+    }
+}
+
+size_t AudioMixerBase::getUnreleasedFrames(int name) const
+{
+    const auto it = mTracks.find(name);
+    if (it != mTracks.end()) {
+        return it->second->getUnreleasedFrames();
+    }
+    return 0;
+}
+
+std::string AudioMixerBase::trackNames() const
+{
+    std::stringstream ss;
+    for (const auto &pair : mTracks) {
+        ss << pair.first << " ";
+    }
+    return ss.str();
+}
+
+void AudioMixerBase::process__validate()
+{
+    // TODO: fix all16BitsStereNoResample logic to
+    // either properly handle muted tracks (it should ignore them)
+    // or remove altogether as an obsolete optimization.
+    bool all16BitsStereoNoResample = true;
+    bool resampling = false;
+    bool volumeRamp = false;
+
+    mEnabled.clear();
+    mGroups.clear();
+    for (const auto &pair : mTracks) {
+        const int name = pair.first;
+        const std::shared_ptr<TrackBase> &t = pair.second;
+        if (!t->enabled) continue;
+
+        mEnabled.emplace_back(name);  // we add to mEnabled in order of name.
+        mGroups[t->mainBuffer].emplace_back(name); // mGroups also in order of name.
+
+        uint32_t n = 0;
+        // FIXME can overflow (mask is only 3 bits)
+        n |= NEEDS_CHANNEL_1 + t->channelCount - 1;
+        if (t->doesResample()) {
+            n |= NEEDS_RESAMPLE;
+        }
+        if (t->auxLevel != 0 && t->auxBuffer != NULL) {
+            n |= NEEDS_AUX;
+        }
+
+        if (t->volumeInc[0]|t->volumeInc[1]) {
+            volumeRamp = true;
+        } else if (!t->doesResample() && t->volumeRL == 0) {
+            n |= NEEDS_MUTE;
+        }
+        t->needs = n;
+
+        if (n & NEEDS_MUTE) {
+            t->hook = &TrackBase::track__nop;
+        } else {
+            if (n & NEEDS_AUX) {
+                all16BitsStereoNoResample = false;
+            }
+            if (n & NEEDS_RESAMPLE) {
+                all16BitsStereoNoResample = false;
+                resampling = true;
+                t->hook = TrackBase::getTrackHook(TRACKTYPE_RESAMPLE, t->mMixerChannelCount,
+                        t->mMixerInFormat, t->mMixerFormat);
+                ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
+                        "Track %d needs downmix + resample", name);
+            } else {
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
+                    t->hook = TrackBase::getTrackHook(
+                            (t->mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO  // TODO: MONO_HACK
+                                    && t->channelMask == AUDIO_CHANNEL_OUT_MONO)
+                                ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE,
+                            t->mMixerChannelCount,
+                            t->mMixerInFormat, t->mMixerFormat);
+                    all16BitsStereoNoResample = false;
+                }
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
+                    t->hook = TrackBase::getTrackHook(TRACKTYPE_NORESAMPLE, t->mMixerChannelCount,
+                            t->mMixerInFormat, t->mMixerFormat);
+                    ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
+                            "Track %d needs downmix", name);
+                }
+            }
+        }
+    }
+
+    // select the processing hooks
+    mHook = &AudioMixerBase::process__nop;
+    if (mEnabled.size() > 0) {
+        if (resampling) {
+            if (mOutputTemp.get() == nullptr) {
+                mOutputTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
+            }
+            if (mResampleTemp.get() == nullptr) {
+                mResampleTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
+            }
+            mHook = &AudioMixerBase::process__genericResampling;
+        } else {
+            // we keep temp arrays around.
+            mHook = &AudioMixerBase::process__genericNoResampling;
+            if (all16BitsStereoNoResample && !volumeRamp) {
+                if (mEnabled.size() == 1) {
+                    const std::shared_ptr<TrackBase> &t = mTracks[mEnabled[0]];
+                    if ((t->needs & NEEDS_MUTE) == 0) {
+                        // The check prevents a muted track from acquiring a process hook.
+                        //
+                        // This is dangerous if the track is MONO as that requires
+                        // special case handling due to implicit channel duplication.
+                        // Stereo or Multichannel should actually be fine here.
+                        mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
+                                t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat);
+                    }
+                }
+            }
+        }
+    }
+
+    ALOGV("mixer configuration change: %zu "
+        "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
+        mEnabled.size(), all16BitsStereoNoResample, resampling, volumeRamp);
+
+    process();
+
+    // Now that the volume ramp has been done, set optimal state and
+    // track hooks for subsequent mixer process
+    if (mEnabled.size() > 0) {
+        bool allMuted = true;
+
+        for (const int name : mEnabled) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            if (!t->doesResample() && t->volumeRL == 0) {
+                t->needs |= NEEDS_MUTE;
+                t->hook = &TrackBase::track__nop;
+            } else {
+                allMuted = false;
+            }
+        }
+        if (allMuted) {
+            mHook = &AudioMixerBase::process__nop;
+        } else if (all16BitsStereoNoResample) {
+            if (mEnabled.size() == 1) {
+                //const int i = 31 - __builtin_clz(enabledTracks);
+                const std::shared_ptr<TrackBase> &t = mTracks[mEnabled[0]];
+                // Muted single tracks handled by allMuted above.
+                mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
+                        t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat);
+            }
+        }
+    }
+}
+
+void AudioMixerBase::TrackBase::track__genericResample(
+        int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
+{
+    ALOGVV("track__genericResample\n");
+    mResampler->setSampleRate(sampleRate);
+
+    // ramp gain - resample to temp buffer and scale/mix in 2nd step
+    if (aux != NULL) {
+        // always resample with unity gain when sending to auxiliary buffer to be able
+        // to apply send level after resampling
+        mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
+        memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(int32_t));
+        mResampler->resample(temp, outFrameCount, bufferProvider);
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
+            volumeRampStereo(out, outFrameCount, temp, aux);
+        } else {
+            volumeStereo(out, outFrameCount, temp, aux);
+        }
+    } else {
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
+            mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
+            memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
+            mResampler->resample(temp, outFrameCount, bufferProvider);
+            volumeRampStereo(out, outFrameCount, temp, aux);
+        }
+
+        // constant gain
+        else {
+            mResampler->setVolume(mVolume[0], mVolume[1]);
+            mResampler->resample(out, outFrameCount, bufferProvider);
+        }
+    }
+}
+
+void AudioMixerBase::TrackBase::track__nop(int32_t* out __unused,
+        size_t outFrameCount __unused, int32_t* temp __unused, int32_t* aux __unused)
+{
+}
+
+void AudioMixerBase::TrackBase::volumeRampStereo(
+        int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+    int32_t vl = prevVolume[0];
+    int32_t vr = prevVolume[1];
+    const int32_t vlInc = volumeInc[0];
+    const int32_t vrInc = volumeInc[1];
+
+    //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+    //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
+    //       (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+    // ramp volume
+    if (CC_UNLIKELY(aux != NULL)) {
+        int32_t va = prevAuxLevel;
+        const int32_t vaInc = auxInc;
+        int32_t l;
+        int32_t r;
+
+        do {
+            l = (*temp++ >> 12);
+            r = (*temp++ >> 12);
+            *out++ += (vl >> 16) * l;
+            *out++ += (vr >> 16) * r;
+            *aux++ += (va >> 17) * (l + r);
+            vl += vlInc;
+            vr += vrInc;
+            va += vaInc;
+        } while (--frameCount);
+        prevAuxLevel = va;
+    } else {
+        do {
+            *out++ += (vl >> 16) * (*temp++ >> 12);
+            *out++ += (vr >> 16) * (*temp++ >> 12);
+            vl += vlInc;
+            vr += vrInc;
+        } while (--frameCount);
+    }
+    prevVolume[0] = vl;
+    prevVolume[1] = vr;
+    adjustVolumeRamp(aux != NULL);
+}
+
+void AudioMixerBase::TrackBase::volumeStereo(
+        int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+    const int16_t vl = volume[0];
+    const int16_t vr = volume[1];
+
+    if (CC_UNLIKELY(aux != NULL)) {
+        const int16_t va = auxLevel;
+        do {
+            int16_t l = (int16_t)(*temp++ >> 12);
+            int16_t r = (int16_t)(*temp++ >> 12);
+            out[0] = mulAdd(l, vl, out[0]);
+            int16_t a = (int16_t)(((int32_t)l + r) >> 1);
+            out[1] = mulAdd(r, vr, out[1]);
+            out += 2;
+            aux[0] = mulAdd(a, va, aux[0]);
+            aux++;
+        } while (--frameCount);
+    } else {
+        do {
+            int16_t l = (int16_t)(*temp++ >> 12);
+            int16_t r = (int16_t)(*temp++ >> 12);
+            out[0] = mulAdd(l, vl, out[0]);
+            out[1] = mulAdd(r, vr, out[1]);
+            out += 2;
+        } while (--frameCount);
+    }
+}
+
+void AudioMixerBase::TrackBase::track__16BitsStereo(
+        int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
+{
+    ALOGVV("track__16BitsStereo\n");
+    const int16_t *in = static_cast<const int16_t *>(mIn);
+
+    if (CC_UNLIKELY(aux != NULL)) {
+        int32_t l;
+        int32_t r;
+        // ramp gain
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
+            int32_t vl = prevVolume[0];
+            int32_t vr = prevVolume[1];
+            int32_t va = prevAuxLevel;
+            const int32_t vlInc = volumeInc[0];
+            const int32_t vrInc = volumeInc[1];
+            const int32_t vaInc = auxInc;
+            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
+            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                l = (int32_t)*in++;
+                r = (int32_t)*in++;
+                *out++ += (vl >> 16) * l;
+                *out++ += (vr >> 16) * r;
+                *aux++ += (va >> 17) * (l + r);
+                vl += vlInc;
+                vr += vrInc;
+                va += vaInc;
+            } while (--frameCount);
+
+            prevVolume[0] = vl;
+            prevVolume[1] = vr;
+            prevAuxLevel = va;
+            adjustVolumeRamp(true);
+        }
+
+        // constant gain
+        else {
+            const uint32_t vrl = volumeRL;
+            const int16_t va = (int16_t)auxLevel;
+            do {
+                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
+                in += 2;
+                out[0] = mulAddRL(1, rl, vrl, out[0]);
+                out[1] = mulAddRL(0, rl, vrl, out[1]);
+                out += 2;
+                aux[0] = mulAdd(a, va, aux[0]);
+                aux++;
+            } while (--frameCount);
+        }
+    } else {
+        // ramp gain
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
+            int32_t vl = prevVolume[0];
+            int32_t vr = prevVolume[1];
+            const int32_t vlInc = volumeInc[0];
+            const int32_t vrInc = volumeInc[1];
+
+            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
+            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                *out++ += (vl >> 16) * (int32_t) *in++;
+                *out++ += (vr >> 16) * (int32_t) *in++;
+                vl += vlInc;
+                vr += vrInc;
+            } while (--frameCount);
+
+            prevVolume[0] = vl;
+            prevVolume[1] = vr;
+            adjustVolumeRamp(false);
+        }
+
+        // constant gain
+        else {
+            const uint32_t vrl = volumeRL;
+            do {
+                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                in += 2;
+                out[0] = mulAddRL(1, rl, vrl, out[0]);
+                out[1] = mulAddRL(0, rl, vrl, out[1]);
+                out += 2;
+            } while (--frameCount);
+        }
+    }
+    mIn = in;
+}
+
+void AudioMixerBase::TrackBase::track__16BitsMono(
+        int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
+{
+    ALOGVV("track__16BitsMono\n");
+    const int16_t *in = static_cast<int16_t const *>(mIn);
+
+    if (CC_UNLIKELY(aux != NULL)) {
+        // ramp gain
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
+            int32_t vl = prevVolume[0];
+            int32_t vr = prevVolume[1];
+            int32_t va = prevAuxLevel;
+            const int32_t vlInc = volumeInc[0];
+            const int32_t vrInc = volumeInc[1];
+            const int32_t vaInc = auxInc;
+
+            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //         t, vlInc/65536.0f, vl/65536.0f, volume[0],
+            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                int32_t l = *in++;
+                *out++ += (vl >> 16) * l;
+                *out++ += (vr >> 16) * l;
+                *aux++ += (va >> 16) * l;
+                vl += vlInc;
+                vr += vrInc;
+                va += vaInc;
+            } while (--frameCount);
+
+            prevVolume[0] = vl;
+            prevVolume[1] = vr;
+            prevAuxLevel = va;
+            adjustVolumeRamp(true);
+        }
+        // constant gain
+        else {
+            const int16_t vl = volume[0];
+            const int16_t vr = volume[1];
+            const int16_t va = (int16_t)auxLevel;
+            do {
+                int16_t l = *in++;
+                out[0] = mulAdd(l, vl, out[0]);
+                out[1] = mulAdd(l, vr, out[1]);
+                out += 2;
+                aux[0] = mulAdd(l, va, aux[0]);
+                aux++;
+            } while (--frameCount);
+        }
+    } else {
+        // ramp gain
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
+            int32_t vl = prevVolume[0];
+            int32_t vr = prevVolume[1];
+            const int32_t vlInc = volumeInc[0];
+            const int32_t vrInc = volumeInc[1];
+
+            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //         t, vlInc/65536.0f, vl/65536.0f, volume[0],
+            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                int32_t l = *in++;
+                *out++ += (vl >> 16) * l;
+                *out++ += (vr >> 16) * l;
+                vl += vlInc;
+                vr += vrInc;
+            } while (--frameCount);
+
+            prevVolume[0] = vl;
+            prevVolume[1] = vr;
+            adjustVolumeRamp(false);
+        }
+        // constant gain
+        else {
+            const int16_t vl = volume[0];
+            const int16_t vr = volume[1];
+            do {
+                int16_t l = *in++;
+                out[0] = mulAdd(l, vl, out[0]);
+                out[1] = mulAdd(l, vr, out[1]);
+                out += 2;
+            } while (--frameCount);
+        }
+    }
+    mIn = in;
+}
+
+// no-op case
+void AudioMixerBase::process__nop()
+{
+    ALOGVV("process__nop\n");
+
+    for (const auto &pair : mGroups) {
+        // process by group of tracks with same output buffer to
+        // avoid multiple memset() on same buffer
+        const auto &group = pair.second;
+
+        const std::shared_ptr<TrackBase> &t = mTracks[group[0]];
+        memset(t->mainBuffer, 0,
+                mFrameCount * audio_bytes_per_frame(t->getMixerChannelCount(), t->mMixerFormat));
+
+        // now consume data
+        for (const int name : group) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            size_t outFrames = mFrameCount;
+            while (outFrames) {
+                t->buffer.frameCount = outFrames;
+                t->bufferProvider->getNextBuffer(&t->buffer);
+                if (t->buffer.raw == NULL) break;
+                outFrames -= t->buffer.frameCount;
+                t->bufferProvider->releaseBuffer(&t->buffer);
+            }
+        }
+    }
+}
+
+// generic code without resampling
+void AudioMixerBase::process__genericNoResampling()
+{
+    ALOGVV("process__genericNoResampling\n");
+    int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
+
+    for (const auto &pair : mGroups) {
+        // process by group of tracks with same output main buffer to
+        // avoid multiple memset() on same buffer
+        const auto &group = pair.second;
+
+        // acquire buffer
+        for (const int name : group) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            t->buffer.frameCount = mFrameCount;
+            t->bufferProvider->getNextBuffer(&t->buffer);
+            t->frameCount = t->buffer.frameCount;
+            t->mIn = t->buffer.raw;
+        }
+
+        int32_t *out = (int *)pair.first;
+        size_t numFrames = 0;
+        do {
+            const size_t frameCount = std::min((size_t)BLOCKSIZE, mFrameCount - numFrames);
+            memset(outTemp, 0, sizeof(outTemp));
+            for (const int name : group) {
+                const std::shared_ptr<TrackBase> &t = mTracks[name];
+                int32_t *aux = NULL;
+                if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
+                    aux = t->auxBuffer + numFrames;
+                }
+                for (int outFrames = frameCount; outFrames > 0; ) {
+                    // t->in == nullptr can happen if the track was flushed just after having
+                    // been enabled for mixing.
+                    if (t->mIn == nullptr) {
+                        break;
+                    }
+                    size_t inFrames = (t->frameCount > outFrames)?outFrames:t->frameCount;
+                    if (inFrames > 0) {
+                        (t.get()->*t->hook)(
+                                outTemp + (frameCount - outFrames) * t->mMixerChannelCount,
+                                inFrames, mResampleTemp.get() /* naked ptr */, aux);
+                        t->frameCount -= inFrames;
+                        outFrames -= inFrames;
+                        if (CC_UNLIKELY(aux != NULL)) {
+                            aux += inFrames;
+                        }
+                    }
+                    if (t->frameCount == 0 && outFrames) {
+                        t->bufferProvider->releaseBuffer(&t->buffer);
+                        t->buffer.frameCount = (mFrameCount - numFrames) -
+                                (frameCount - outFrames);
+                        t->bufferProvider->getNextBuffer(&t->buffer);
+                        t->mIn = t->buffer.raw;
+                        if (t->mIn == nullptr) {
+                            break;
+                        }
+                        t->frameCount = t->buffer.frameCount;
+                    }
+                }
+            }
+
+            const std::shared_ptr<TrackBase> &t1 = mTracks[group[0]];
+            convertMixerFormat(out, t1->mMixerFormat, outTemp, t1->mMixerInFormat,
+                    frameCount * t1->mMixerChannelCount);
+            // TODO: fix ugly casting due to choice of out pointer type
+            out = reinterpret_cast<int32_t*>((uint8_t*)out
+                    + frameCount * t1->mMixerChannelCount
+                    * audio_bytes_per_sample(t1->mMixerFormat));
+            numFrames += frameCount;
+        } while (numFrames < mFrameCount);
+
+        // release each track's buffer
+        for (const int name : group) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            t->bufferProvider->releaseBuffer(&t->buffer);
+        }
+    }
+}
+
+// generic code with resampling
+void AudioMixerBase::process__genericResampling()
+{
+    ALOGVV("process__genericResampling\n");
+    int32_t * const outTemp = mOutputTemp.get(); // naked ptr
+    size_t numFrames = mFrameCount;
+
+    for (const auto &pair : mGroups) {
+        const auto &group = pair.second;
+        const std::shared_ptr<TrackBase> &t1 = mTracks[group[0]];
+
+        // clear temp buffer
+        memset(outTemp, 0, sizeof(*outTemp) * t1->mMixerChannelCount * mFrameCount);
+        for (const int name : group) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            int32_t *aux = NULL;
+            if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
+                aux = t->auxBuffer;
+            }
+
+            // this is a little goofy, on the resampling case we don't
+            // acquire/release the buffers because it's done by
+            // the resampler.
+            if (t->needs & NEEDS_RESAMPLE) {
+                (t.get()->*t->hook)(outTemp, numFrames, mResampleTemp.get() /* naked ptr */, aux);
+            } else {
+
+                size_t outFrames = 0;
+
+                while (outFrames < numFrames) {
+                    t->buffer.frameCount = numFrames - outFrames;
+                    t->bufferProvider->getNextBuffer(&t->buffer);
+                    t->mIn = t->buffer.raw;
+                    // t->mIn == nullptr can happen if the track was flushed just after having
+                    // been enabled for mixing.
+                    if (t->mIn == nullptr) break;
+
+                    (t.get()->*t->hook)(
+                            outTemp + outFrames * t->mMixerChannelCount, t->buffer.frameCount,
+                            mResampleTemp.get() /* naked ptr */,
+                            aux != nullptr ? aux + outFrames : nullptr);
+                    outFrames += t->buffer.frameCount;
+
+                    t->bufferProvider->releaseBuffer(&t->buffer);
+                }
+            }
+        }
+        convertMixerFormat(t1->mainBuffer, t1->mMixerFormat,
+                outTemp, t1->mMixerInFormat, numFrames * t1->mMixerChannelCount);
+    }
+}
+
+// one track, 16 bits stereo without resampling is the most common case
+void AudioMixerBase::process__oneTrack16BitsStereoNoResampling()
+{
+    ALOGVV("process__oneTrack16BitsStereoNoResampling\n");
+    LOG_ALWAYS_FATAL_IF(mEnabled.size() != 0,
+            "%zu != 1 tracks enabled", mEnabled.size());
+    const int name = mEnabled[0];
+    const std::shared_ptr<TrackBase> &t = mTracks[name];
+
+    AudioBufferProvider::Buffer& b(t->buffer);
+
+    int32_t* out = t->mainBuffer;
+    float *fout = reinterpret_cast<float*>(out);
+    size_t numFrames = mFrameCount;
+
+    const int16_t vl = t->volume[0];
+    const int16_t vr = t->volume[1];
+    const uint32_t vrl = t->volumeRL;
+    while (numFrames) {
+        b.frameCount = numFrames;
+        t->bufferProvider->getNextBuffer(&b);
+        const int16_t *in = b.i16;
+
+        // in == NULL can happen if the track was flushed just after having
+        // been enabled for mixing.
+        if (in == NULL || (((uintptr_t)in) & 3)) {
+            if ( AUDIO_FORMAT_PCM_FLOAT == t->mMixerFormat ) {
+                 memset((char*)fout, 0, numFrames
+                         * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
+            } else {
+                 memset((char*)out, 0, numFrames
+                         * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
+            }
+            ALOGE_IF((((uintptr_t)in) & 3),
+                    "process__oneTrack16BitsStereoNoResampling: misaligned buffer"
+                    " %p track %d, channels %d, needs %08x, volume %08x vfl %f vfr %f",
+                    in, name, t->channelCount, t->needs, vrl, t->mVolume[0], t->mVolume[1]);
+            return;
+        }
+        size_t outFrames = b.frameCount;
+
+        switch (t->mMixerFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            do {
+                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                in += 2;
+                int32_t l = mulRL(1, rl, vrl);
+                int32_t r = mulRL(0, rl, vrl);
+                *fout++ = float_from_q4_27(l);
+                *fout++ = float_from_q4_27(r);
+                // Note: In case of later int16_t sink output,
+                // conversion and clamping is done by memcpy_to_i16_from_float().
+            } while (--outFrames);
+            break;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) {
+                // volume is boosted, so we might need to clamp even though
+                // we process only one track.
+                do {
+                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                    in += 2;
+                    int32_t l = mulRL(1, rl, vrl) >> 12;
+                    int32_t r = mulRL(0, rl, vrl) >> 12;
+                    // clamping...
+                    l = clamp16(l);
+                    r = clamp16(r);
+                    *out++ = (r<<16) | (l & 0xFFFF);
+                } while (--outFrames);
+            } else {
+                do {
+                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                    in += 2;
+                    int32_t l = mulRL(1, rl, vrl) >> 12;
+                    int32_t r = mulRL(0, rl, vrl) >> 12;
+                    *out++ = (r<<16) | (l & 0xFFFF);
+                } while (--outFrames);
+            }
+            break;
+        default:
+            LOG_ALWAYS_FATAL("bad mixer format: %d", t->mMixerFormat);
+        }
+        numFrames -= b.frameCount;
+        t->bufferProvider->releaseBuffer(&b);
+    }
+}
+
+/* TODO: consider whether this level of optimization is necessary.
+ * Perhaps just stick with a single for loop.
+ */
+
+// Needs to derive a compile time constant (constexpr).  Could be targeted to go
+// to a MONOVOL mixtype based on MAX_NUM_VOLUMES, but that's an unnecessary complication.
+#define MIXTYPE_MONOVOL(mixtype) ((mixtype) == MIXTYPE_MULTI ? MIXTYPE_MULTI_MONOVOL : \
+        (mixtype) == MIXTYPE_MULTI_SAVEONLY ? MIXTYPE_MULTI_SAVEONLY_MONOVOL : (mixtype))
+
+/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE,
+        typename TO, typename TI, typename TV, typename TA, typename TAV>
+static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount,
+        const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc)
+{
+    switch (channels) {
+    case 1:
+        volumeRampMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 2:
+        volumeRampMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 3:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 4:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 5:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 6:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 7:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 8:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    }
+}
+
+/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE,
+        typename TO, typename TI, typename TV, typename TA, typename TAV>
+static void volumeMulti(uint32_t channels, TO* out, size_t frameCount,
+        const TI* in, TA* aux, const TV *vol, TAV vola)
+{
+    switch (channels) {
+    case 1:
+        volumeMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 2:
+        volumeMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 3:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 4:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 5:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 6:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 7:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 8:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out, frameCount, in, aux, vol, vola);
+        break;
+    }
+}
+
+/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * USEFLOATVOL (set to true if float volume is used)
+ * ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
+    typename TO, typename TI, typename TA>
+void AudioMixerBase::TrackBase::volumeMix(TO *out, size_t outFrames,
+        const TI *in, TA *aux, bool ramp)
+{
+    if (USEFLOATVOL) {
+        if (ramp) {
+            volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
+                    mPrevVolume, mVolumeInc,
+#ifdef FLOAT_AUX
+                    &mPrevAuxLevel, mAuxInc
+#else
+                    &prevAuxLevel, auxInc
+#endif
+                );
+            if (ADJUSTVOL) {
+                adjustVolumeRamp(aux != NULL, true);
+            }
+        } else {
+            volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
+                    mVolume,
+#ifdef FLOAT_AUX
+                    mAuxLevel
+#else
+                    auxLevel
+#endif
+            );
+        }
+    } else {
+        if (ramp) {
+            volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
+                    prevVolume, volumeInc, &prevAuxLevel, auxInc);
+            if (ADJUSTVOL) {
+                adjustVolumeRamp(aux != NULL);
+            }
+        } else {
+            volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
+                    volume, auxLevel);
+        }
+    }
+}
+
+/* This process hook is called when there is a single track without
+ * aux buffer, volume ramp, or resampling.
+ * TODO: Update the hook selection: this can properly handle aux and ramp.
+ *
+ * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27)
+ */
+template <int MIXTYPE, typename TO, typename TI, typename TA>
+void AudioMixerBase::process__noResampleOneTrack()
+{
+    ALOGVV("process__noResampleOneTrack\n");
+    LOG_ALWAYS_FATAL_IF(mEnabled.size() != 1,
+            "%zu != 1 tracks enabled", mEnabled.size());
+    const std::shared_ptr<TrackBase> &t = mTracks[mEnabled[0]];
+    const uint32_t channels = t->mMixerChannelCount;
+    TO* out = reinterpret_cast<TO*>(t->mainBuffer);
+    TA* aux = reinterpret_cast<TA*>(t->auxBuffer);
+    const bool ramp = t->needsRamp();
+
+    for (size_t numFrames = mFrameCount; numFrames > 0; ) {
+        AudioBufferProvider::Buffer& b(t->buffer);
+        // get input buffer
+        b.frameCount = numFrames;
+        t->bufferProvider->getNextBuffer(&b);
+        const TI *in = reinterpret_cast<TI*>(b.raw);
+
+        // in == NULL can happen if the track was flushed just after having
+        // been enabled for mixing.
+        if (in == NULL || (((uintptr_t)in) & 3)) {
+            memset(out, 0, numFrames
+                    * channels * audio_bytes_per_sample(t->mMixerFormat));
+            ALOGE_IF((((uintptr_t)in) & 3), "process__noResampleOneTrack: bus error: "
+                    "buffer %p track %p, channels %d, needs %#x",
+                    in, &t, t->channelCount, t->needs);
+            return;
+        }
+
+        const size_t outFrames = b.frameCount;
+        t->volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, false /* ADJUSTVOL */> (
+                out, outFrames, in, aux, ramp);
+
+        out += outFrames * channels;
+        if (aux != NULL) {
+            aux += outFrames;
+        }
+        numFrames -= b.frameCount;
+
+        // release buffer
+        t->bufferProvider->releaseBuffer(&b);
+    }
+    if (ramp) {
+        t->adjustVolumeRamp(aux != NULL, is_same<TI, float>::value);
+    }
+}
+
+/* This track hook is called to do resampling then mixing,
+ * pulling from the track's upstream AudioBufferProvider.
+ *
+ * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE, typename TO, typename TI, typename TA>
+void AudioMixerBase::TrackBase::track__Resample(TO* out, size_t outFrameCount, TO* temp, TA* aux)
+{
+    ALOGVV("track__Resample\n");
+    mResampler->setSampleRate(sampleRate);
+    const bool ramp = needsRamp();
+    if (ramp || aux != NULL) {
+        // if ramp:        resample with unity gain to temp buffer and scale/mix in 2nd step.
+        // if aux != NULL: resample with unity gain to temp buffer then apply send level.
+
+        mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
+        memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(TO));
+        mResampler->resample((int32_t*)temp, outFrameCount, bufferProvider);
+
+        volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
+                out, outFrameCount, temp, aux, ramp);
+
+    } else { // constant volume gain
+        mResampler->setVolume(mVolume[0], mVolume[1]);
+        mResampler->resample((int32_t*)out, outFrameCount, bufferProvider);
+    }
+}
+
+/* This track hook is called to mix a track, when no resampling is required.
+ * The input buffer should be present in in.
+ *
+ * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE, typename TO, typename TI, typename TA>
+void AudioMixerBase::TrackBase::track__NoResample(
+        TO* out, size_t frameCount, TO* temp __unused, TA* aux)
+{
+    ALOGVV("track__NoResample\n");
+    const TI *in = static_cast<const TI *>(mIn);
+
+    volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
+            out, frameCount, in, aux, needsRamp());
+
+    // MIXTYPE_MONOEXPAND reads a single input channel and expands to NCHAN output channels.
+    // MIXTYPE_MULTI reads NCHAN input channels and places to NCHAN output channels.
+    in += (MIXTYPE == MIXTYPE_MONOEXPAND) ? frameCount : frameCount * mMixerChannelCount;
+    mIn = in;
+}
+
+/* The Mixer engine generates either int32_t (Q4_27) or float data.
+ * We use this function to convert the engine buffers
+ * to the desired mixer output format, either int16_t (Q.15) or float.
+ */
+/* static */
+void AudioMixerBase::convertMixerFormat(void *out, audio_format_t mixerOutFormat,
+        void *in, audio_format_t mixerInFormat, size_t sampleCount)
+{
+    switch (mixerInFormat) {
+    case AUDIO_FORMAT_PCM_FLOAT:
+        switch (mixerOutFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            memcpy(out, in, sampleCount * sizeof(float)); // MEMCPY. TODO optimize out
+            break;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            memcpy_to_i16_from_float((int16_t*)out, (float*)in, sampleCount);
+            break;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+            break;
+        }
+        break;
+    case AUDIO_FORMAT_PCM_16_BIT:
+        switch (mixerOutFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            memcpy_to_float_from_q4_27((float*)out, (const int32_t*)in, sampleCount);
+            break;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            memcpy_to_i16_from_q4_27((int16_t*)out, (const int32_t*)in, sampleCount);
+            break;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+            break;
+        }
+        break;
+    default:
+        LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+        break;
+    }
+}
+
+/* Returns the proper track hook to use for mixing the track into the output buffer.
+ */
+/* static */
+AudioMixerBase::hook_t AudioMixerBase::TrackBase::getTrackHook(int trackType, uint32_t channelCount,
+        audio_format_t mixerInFormat, audio_format_t mixerOutFormat __unused)
+{
+    if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
+        switch (trackType) {
+        case TRACKTYPE_NOP:
+            return &TrackBase::track__nop;
+        case TRACKTYPE_RESAMPLE:
+            return &TrackBase::track__genericResample;
+        case TRACKTYPE_NORESAMPLEMONO:
+            return &TrackBase::track__16BitsMono;
+        case TRACKTYPE_NORESAMPLE:
+            return &TrackBase::track__16BitsStereo;
+        default:
+            LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
+            break;
+        }
+    }
+    LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
+    switch (trackType) {
+    case TRACKTYPE_NOP:
+        return &TrackBase::track__nop;
+    case TRACKTYPE_RESAMPLE:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
+    case TRACKTYPE_NORESAMPLEMONO:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                            MIXTYPE_MONOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                            MIXTYPE_MONOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
+    case TRACKTYPE_NORESAMPLE:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                    MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                    MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
+    default:
+        LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
+        break;
+    }
+    return NULL;
+}
+
+/* Returns the proper process hook for mixing tracks. Currently works only for
+ * PROCESSTYPE_NORESAMPLEONETRACK, a mix involving one track, no resampling.
+ *
+ * TODO: Due to the special mixing considerations of duplicating to
+ * a stereo output track, the input track cannot be MONO.  This should be
+ * prevented by the caller.
+ */
+/* static */
+AudioMixerBase::process_hook_t AudioMixerBase::getProcessHook(
+        int processType, uint32_t channelCount,
+        audio_format_t mixerInFormat, audio_format_t mixerOutFormat)
+{
+    if (processType != PROCESSTYPE_NORESAMPLEONETRACK) { // Only NORESAMPLEONETRACK
+        LOG_ALWAYS_FATAL("bad processType: %d", processType);
+        return NULL;
+    }
+    if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
+        return &AudioMixerBase::process__oneTrack16BitsStereoNoResampling;
+    }
+    LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
+    switch (mixerInFormat) {
+    case AUDIO_FORMAT_PCM_FLOAT:
+        switch (mixerOutFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return &AudioMixerBase::process__noResampleOneTrack<
+                    MIXTYPE_MULTI_SAVEONLY, float /*TO*/, float /*TI*/, TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return &AudioMixerBase::process__noResampleOneTrack<
+                    MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, float /*TI*/, TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+            break;
+        }
+        break;
+    case AUDIO_FORMAT_PCM_16_BIT:
+        switch (mixerOutFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return &AudioMixerBase::process__noResampleOneTrack<
+                    MIXTYPE_MULTI_SAVEONLY, float /*TO*/, int16_t /*TI*/, TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return &AudioMixerBase::process__noResampleOneTrack<
+                    MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+            break;
+        }
+        break;
+    default:
+        LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+        break;
+    }
+    return NULL;
+}
+
+// ----------------------------------------------------------------------------
+} // namespace android
diff --git a/media/libaudioprocessing/include/media/AudioMixerBase.h b/media/libaudioprocessing/include/media/AudioMixerBase.h
new file mode 100644
index 0000000..805b6d0
--- /dev/null
+++ b/media/libaudioprocessing/include/media/AudioMixerBase.h
@@ -0,0 +1,359 @@
+/*
+**
+** Copyright 2019, 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_AUDIO_MIXER_BASE_H
+#define ANDROID_AUDIO_MIXER_BASE_H
+
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <media/AudioBufferProvider.h>
+#include <media/AudioResampler.h>
+#include <media/AudioResamplerPublic.h>
+#include <system/audio.h>
+#include <utils/Compat.h>
+
+// This must match frameworks/av/services/audioflinger/Configuration.h
+// when used with the Audio Framework.
+#define FLOAT_AUX
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// AudioMixerBase is functional on its own if only mixing and resampling
+// is needed.
+
+class AudioMixerBase
+{
+public:
+    // Do not change these unless underlying code changes.
+    // This mixer has a hard-coded upper limit of 8 channels for output.
+    static constexpr uint32_t MAX_NUM_CHANNELS = FCC_8;
+    static constexpr uint32_t MAX_NUM_VOLUMES = FCC_2; // stereo volume only
+
+    static const uint16_t UNITY_GAIN_INT = 0x1000;
+    static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
+
+    enum { // names
+        // setParameter targets
+        TRACK           = 0x3000,
+        RESAMPLE        = 0x3001,
+        RAMP_VOLUME     = 0x3002, // ramp to new volume
+        VOLUME          = 0x3003, // don't ramp
+        TIMESTRETCH     = 0x3004,
+
+        // set Parameter names
+        // for target TRACK
+        CHANNEL_MASK    = 0x4000,
+        FORMAT          = 0x4001,
+        MAIN_BUFFER     = 0x4002,
+        AUX_BUFFER      = 0x4003,
+        // 0x4004 reserved
+        MIXER_FORMAT    = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
+        MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output
+        // for target RESAMPLE
+        SAMPLE_RATE     = 0x4100, // Configure sample rate conversion on this track name;
+                                  // parameter 'value' is the new sample rate in Hz.
+                                  // Only creates a sample rate converter the first time that
+                                  // the track sample rate is different from the mix sample rate.
+                                  // If the new sample rate is the same as the mix sample rate,
+                                  // and a sample rate converter already exists,
+                                  // then the sample rate converter remains present but is a no-op.
+        RESET           = 0x4101, // Reset sample rate converter without changing sample rate.
+                                  // This clears out the resampler's input buffer.
+        REMOVE          = 0x4102, // Remove the sample rate converter on this track name;
+                                  // the track is restored to the mix sample rate.
+        // for target RAMP_VOLUME and VOLUME (8 channels max)
+        // FIXME use float for these 3 to improve the dynamic range
+        VOLUME0         = 0x4200,
+        VOLUME1         = 0x4201,
+        AUXLEVEL        = 0x4210,
+    };
+
+    AudioMixerBase(size_t frameCount, uint32_t sampleRate)
+        : mSampleRate(sampleRate)
+        , mFrameCount(frameCount) {
+    }
+
+    virtual ~AudioMixerBase() {}
+
+    virtual bool isValidFormat(audio_format_t format) const;
+    virtual bool isValidChannelMask(audio_channel_mask_t channelMask) const;
+
+    // Create a new track in the mixer.
+    //
+    // \param name        a unique user-provided integer associated with the track.
+    //                    If name already exists, the function will abort.
+    // \param channelMask output channel mask.
+    // \param format      PCM format
+    // \param sessionId   Session id for the track. Tracks with the same
+    //                    session id will be submixed together.
+    //
+    // \return OK        on success.
+    //         BAD_VALUE if the format does not satisfy isValidFormat()
+    //                   or the channelMask does not satisfy isValidChannelMask().
+    status_t    create(
+            int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId);
+
+    bool        exists(int name) const {
+        return mTracks.count(name) > 0;
+    }
+
+    // Free an allocated track by name.
+    void        destroy(int name);
+
+    // Enable or disable an allocated track by name
+    void        enable(int name);
+    void        disable(int name);
+
+    virtual void setParameter(int name, int target, int param, void *value);
+
+    void        process() {
+        preProcess();
+        (this->*mHook)();
+        postProcess();
+    }
+
+    size_t      getUnreleasedFrames(int name) const;
+
+    std::string trackNames() const;
+
+  protected:
+    // Set kUseNewMixer to true to use the new mixer engine always. Otherwise the
+    // original code will be used for stereo sinks, the new mixer for everything else.
+    static constexpr bool kUseNewMixer = true;
+
+    // Set kUseFloat to true to allow floating input into the mixer engine.
+    // If kUseNewMixer is false, this is ignored or may be overridden internally
+    static constexpr bool kUseFloat = true;
+
+#ifdef FLOAT_AUX
+    using TYPE_AUX = float;
+    static_assert(kUseNewMixer && kUseFloat,
+            "kUseNewMixer and kUseFloat must be true for FLOAT_AUX option");
+#else
+    using TYPE_AUX = int32_t; // q4.27
+#endif
+
+    /* For multi-format functions (calls template functions
+     * in AudioMixerOps.h).  The template parameters are as follows:
+     *
+     *   MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+     *   USEFLOATVOL (set to true if float volume is used)
+     *   ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
+     *   TO: int32_t (Q4.27) or float
+     *   TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+     *   TA: int32_t (Q4.27)
+     */
+
+    enum {
+        // FIXME this representation permits up to 8 channels
+        NEEDS_CHANNEL_COUNT__MASK   = 0x00000007,
+    };
+
+    enum {
+        NEEDS_CHANNEL_1             = 0x00000000,   // mono
+        NEEDS_CHANNEL_2             = 0x00000001,   // stereo
+
+        // sample format is not explicitly specified, and is assumed to be AUDIO_FORMAT_PCM_16_BIT
+
+        NEEDS_MUTE                  = 0x00000100,
+        NEEDS_RESAMPLE              = 0x00001000,
+        NEEDS_AUX                   = 0x00010000,
+    };
+
+    // hook types
+    enum {
+        PROCESSTYPE_NORESAMPLEONETRACK, // others set elsewhere
+    };
+
+    enum {
+        TRACKTYPE_NOP,
+        TRACKTYPE_RESAMPLE,
+        TRACKTYPE_NORESAMPLE,
+        TRACKTYPE_NORESAMPLEMONO,
+    };
+
+    // process hook functionality
+    using process_hook_t = void(AudioMixerBase::*)();
+
+    struct TrackBase;
+    using hook_t = void(TrackBase::*)(
+            int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
+
+    struct TrackBase {
+        TrackBase()
+            : bufferProvider(nullptr)
+        {
+            // TODO: move additional initialization here.
+        }
+        virtual ~TrackBase() {}
+
+        virtual uint32_t getOutputChannelCount() { return channelCount; }
+        virtual uint32_t getMixerChannelCount() { return mMixerChannelCount; }
+
+        bool        needsRamp() { return (volumeInc[0] | volumeInc[1] | auxInc) != 0; }
+        bool        setResampler(uint32_t trackSampleRate, uint32_t devSampleRate);
+        bool        doesResample() const { return mResampler.get() != nullptr; }
+        void        recreateResampler(uint32_t devSampleRate);
+        void        resetResampler() { if (mResampler.get() != nullptr) mResampler->reset(); }
+        void        adjustVolumeRamp(bool aux, bool useFloat = false);
+        size_t      getUnreleasedFrames() const { return mResampler.get() != nullptr ?
+                                                    mResampler->getUnreleasedFrames() : 0; };
+
+        static hook_t getTrackHook(int trackType, uint32_t channelCount,
+                audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
+
+        void track__nop(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+
+        template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
+            typename TO, typename TI, typename TA>
+        void volumeMix(TO *out, size_t outFrames, const TI *in, TA *aux, bool ramp);
+
+        uint32_t    needs;
+
+        // TODO: Eventually remove legacy integer volume settings
+        union {
+        int16_t     volume[MAX_NUM_VOLUMES]; // U4.12 fixed point (top bit should be zero)
+        int32_t     volumeRL;
+        };
+
+        int32_t     prevVolume[MAX_NUM_VOLUMES];
+        int32_t     volumeInc[MAX_NUM_VOLUMES];
+        int32_t     auxInc;
+        int32_t     prevAuxLevel;
+        int16_t     auxLevel;       // 0 <= auxLevel <= MAX_GAIN_INT, but signed for mul performance
+
+        uint16_t    frameCount;
+
+        uint8_t     channelCount;   // 1 or 2, redundant with (needs & NEEDS_CHANNEL_COUNT__MASK)
+        uint8_t     unused_padding; // formerly format, was always 16
+        uint16_t    enabled;        // actually bool
+        audio_channel_mask_t channelMask;
+
+        // actual buffer provider used by the track hooks
+        AudioBufferProvider*                bufferProvider;
+
+        mutable AudioBufferProvider::Buffer buffer; // 8 bytes
+
+        hook_t      hook;
+        const void  *mIn;             // current location in buffer
+
+        std::unique_ptr<AudioResampler> mResampler;
+        uint32_t    sampleRate;
+        int32_t*    mainBuffer;
+        int32_t*    auxBuffer;
+
+        int32_t     sessionId;
+
+        audio_format_t mMixerFormat;     // output mix format: AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
+        audio_format_t mFormat;          // input track format
+        audio_format_t mMixerInFormat;   // mix internal format AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
+                                         // each track must be converted to this format.
+
+        float          mVolume[MAX_NUM_VOLUMES];     // floating point set volume
+        float          mPrevVolume[MAX_NUM_VOLUMES]; // floating point previous volume
+        float          mVolumeInc[MAX_NUM_VOLUMES];  // floating point volume increment
+
+        float          mAuxLevel;                     // floating point set aux level
+        float          mPrevAuxLevel;                 // floating point prev aux level
+        float          mAuxInc;                       // floating point aux increment
+
+        audio_channel_mask_t mMixerChannelMask;
+        uint32_t             mMixerChannelCount;
+
+      protected:
+
+        // hooks
+        void track__genericResample(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+        void track__16BitsStereo(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+        void track__16BitsMono(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+
+        void volumeRampStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
+        void volumeStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
+
+        // multi-format track hooks
+        template <int MIXTYPE, typename TO, typename TI, typename TA>
+        void track__Resample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
+        template <int MIXTYPE, typename TO, typename TI, typename TA>
+        void track__NoResample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
+    };
+
+    // preCreateTrack must create an instance of a proper TrackBase descendant.
+    // postCreateTrack is called after filling out fields of TrackBase. It can
+    // abort track creation by returning non-OK status. See the implementation
+    // of create() for details.
+    virtual std::shared_ptr<TrackBase> preCreateTrack();
+    virtual status_t postCreateTrack(TrackBase *track __unused) { return OK; }
+
+    // preProcess is called before the process hook, postProcess after,
+    // see the implementation of process() method.
+    virtual void preProcess() {}
+    virtual void postProcess() {}
+
+    virtual bool setChannelMasks(int name,
+            audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask);
+
+    // Called when track info changes and a new process hook should be determined.
+    void invalidate() {
+        mHook = &AudioMixerBase::process__validate;
+    }
+
+    void process__validate();
+    void process__nop();
+    void process__genericNoResampling();
+    void process__genericResampling();
+    void process__oneTrack16BitsStereoNoResampling();
+
+    template <int MIXTYPE, typename TO, typename TI, typename TA>
+    void process__noResampleOneTrack();
+
+    static process_hook_t getProcessHook(int processType, uint32_t channelCount,
+            audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
+
+    static void convertMixerFormat(void *out, audio_format_t mixerOutFormat,
+            void *in, audio_format_t mixerInFormat, size_t sampleCount);
+
+    // initialization constants
+    const uint32_t mSampleRate;
+    const size_t mFrameCount;
+
+    process_hook_t mHook = &AudioMixerBase::process__nop;   // one of process__*, never nullptr
+
+    // the size of the type (int32_t) should be the largest of all types supported
+    // by the mixer.
+    std::unique_ptr<int32_t[]> mOutputTemp;
+    std::unique_ptr<int32_t[]> mResampleTemp;
+
+    // track names grouped by main buffer, in no particular order of main buffer.
+    // however names for a particular main buffer are in order (by construction).
+    std::unordered_map<void * /* mainBuffer */, std::vector<int /* name */>> mGroups;
+
+    // track names that are enabled, in increasing order (by construction).
+    std::vector<int /* name */> mEnabled;
+
+    // track smart pointers, by name, in increasing order of name.
+    std::map<int /* name */, std::shared_ptr<TrackBase>> mTracks;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_AUDIO_MIXER_BASE_H
diff --git a/media/libmedia/include/media/RecordBufferConverter.h b/media/libaudioprocessing/include/media/RecordBufferConverter.h
similarity index 100%
rename from media/libmedia/include/media/RecordBufferConverter.h
rename to media/libaudioprocessing/include/media/RecordBufferConverter.h
diff --git a/media/libaudioprocessing/tests/Android.bp b/media/libaudioprocessing/tests/Android.bp
index d990111..20c2c2c 100644
--- a/media/libaudioprocessing/tests/Android.bp
+++ b/media/libaudioprocessing/tests/Android.bp
@@ -3,8 +3,13 @@
 cc_defaults {
     name: "libaudioprocessing_test_defaults",
 
-    header_libs: ["libbase_headers"],
+    header_libs: [
+        "libbase_headers",
+        "libmedia_headers",
+    ],
+
     shared_libs: [
+        "libaudioclient",
         "libaudioprocessing",
         "libaudioutils",
         "libcutils",
diff --git a/media/libaudioprocessing/tests/fuzzer/Android.bp b/media/libaudioprocessing/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..1df47b7
--- /dev/null
+++ b/media/libaudioprocessing/tests/fuzzer/Android.bp
@@ -0,0 +1,10 @@
+cc_fuzz {
+  name: "libaudioprocessing_resampler_fuzzer",
+  srcs: [
+    "libaudioprocessing_resampler_fuzzer.cpp",
+  ],
+  defaults: ["libaudioprocessing_test_defaults"],
+  static_libs: [
+    "libsndfile",
+  ],
+}
diff --git a/media/libaudioprocessing/tests/fuzzer/libaudioprocessing_resampler_fuzzer.cpp b/media/libaudioprocessing/tests/fuzzer/libaudioprocessing_resampler_fuzzer.cpp
new file mode 100644
index 0000000..938c610
--- /dev/null
+++ b/media/libaudioprocessing/tests/fuzzer/libaudioprocessing_resampler_fuzzer.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2019 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 <android-base/macros.h>
+#include <audio_utils/primitives.h>
+#include <audio_utils/sndfile.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <math.h>
+#include <media/AudioBufferProvider.h>
+#include <media/AudioResampler.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <utils/Vector.h>
+
+#include <memory>
+
+using namespace android;
+
+const int MAX_FRAMES = 10;
+const int MIN_FREQ = 1e3;
+const int MAX_FREQ = 100e3;
+
+const AudioResampler::src_quality qualities[] = {
+    AudioResampler::DEFAULT_QUALITY,
+    AudioResampler::LOW_QUALITY,
+    AudioResampler::MED_QUALITY,
+    AudioResampler::HIGH_QUALITY,
+    AudioResampler::VERY_HIGH_QUALITY,
+    AudioResampler::DYN_LOW_QUALITY,
+    AudioResampler::DYN_MED_QUALITY,
+    AudioResampler::DYN_HIGH_QUALITY,
+};
+
+class Provider : public AudioBufferProvider {
+  const void* mAddr;        // base address
+  const size_t mNumFrames;  // total frames
+  const size_t mFrameSize;  // size of each frame in bytes
+  size_t mNextFrame;        // index of next frame to provide
+  size_t mUnrel;            // number of frames not yet released
+ public:
+  Provider(const void* addr, size_t frames, size_t frameSize)
+      : mAddr(addr),
+        mNumFrames(frames),
+        mFrameSize(frameSize),
+        mNextFrame(0),
+        mUnrel(0) {}
+  status_t getNextBuffer(Buffer* buffer) override {
+    if (buffer->frameCount > mNumFrames - mNextFrame) {
+      buffer->frameCount = mNumFrames - mNextFrame;
+    }
+    mUnrel = buffer->frameCount;
+    if (buffer->frameCount > 0) {
+      buffer->raw = (char*)mAddr + mFrameSize * mNextFrame;
+      return NO_ERROR;
+    } else {
+      buffer->raw = nullptr;
+      return NOT_ENOUGH_DATA;
+    }
+  }
+  virtual void releaseBuffer(Buffer* buffer) {
+    if (buffer->frameCount > mUnrel) {
+      mNextFrame += mUnrel;
+      mUnrel = 0;
+    } else {
+      mNextFrame += buffer->frameCount;
+      mUnrel -= buffer->frameCount;
+    }
+    buffer->frameCount = 0;
+    buffer->raw = nullptr;
+  }
+  void reset() { mNextFrame = 0; }
+};
+
+audio_format_t chooseFormat(AudioResampler::src_quality quality,
+                            uint8_t input_byte) {
+  switch (quality) {
+    case AudioResampler::DYN_LOW_QUALITY:
+    case AudioResampler::DYN_MED_QUALITY:
+    case AudioResampler::DYN_HIGH_QUALITY:
+      if (input_byte % 2) {
+        return AUDIO_FORMAT_PCM_FLOAT;
+      }
+      FALLTHROUGH_INTENDED;
+    default:
+      return AUDIO_FORMAT_PCM_16_BIT;
+  }
+}
+
+int parseValue(const uint8_t* src, int index, void* dst, size_t size) {
+  memcpy(dst, &src[index], size);
+  return size;
+}
+
+bool validFreq(int freq) { return freq > MIN_FREQ && freq < MAX_FREQ; }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  int input_freq = 0;
+  int output_freq = 0;
+  int input_channels = 0;
+
+  float left_volume = 0;
+  float right_volume = 0;
+
+  size_t metadata_size = 2 + 3 * sizeof(int) + 2 * sizeof(float);
+  if (size < metadata_size) {
+    // not enough data to set options
+    return 0;
+  }
+
+  AudioResampler::src_quality quality = qualities[data[0] % 8];
+  audio_format_t format = chooseFormat(quality, data[1]);
+
+  int index = 2;
+
+  index += parseValue(data, index, &input_freq, sizeof(int));
+  index += parseValue(data, index, &output_freq, sizeof(int));
+  index += parseValue(data, index, &input_channels, sizeof(int));
+
+  index += parseValue(data, index, &left_volume, sizeof(float));
+  index += parseValue(data, index, &right_volume, sizeof(float));
+
+  if (!validFreq(input_freq) || !validFreq(output_freq)) {
+    // sampling frequencies must be reasonable
+    return 0;
+  }
+
+  if (input_channels < 1 ||
+      input_channels > (quality < AudioResampler::DYN_LOW_QUALITY ? 2 : 8)) {
+    // invalid number of input channels
+    return 0;
+  }
+
+  size_t single_channel_size =
+      format == AUDIO_FORMAT_PCM_FLOAT ? sizeof(float) : sizeof(int16_t);
+  size_t input_frame_size = single_channel_size * input_channels;
+  size_t input_size = size - metadata_size;
+  uint8_t input_data[input_size];
+  memcpy(input_data, &data[metadata_size], input_size);
+
+  size_t input_frames = input_size / input_frame_size;
+  if (input_frames > MAX_FRAMES) {
+    return 0;
+  }
+
+  Provider provider(input_data, input_frames, input_frame_size);
+
+  std::unique_ptr<AudioResampler> resampler(
+      AudioResampler::create(format, input_channels, output_freq, quality));
+
+  resampler->setSampleRate(input_freq);
+  resampler->setVolume(left_volume, right_volume);
+
+  // output is at least stereo samples
+  int output_channels = input_channels > 2 ? input_channels : 2;
+  size_t output_frame_size = output_channels * sizeof(int32_t);
+  size_t output_frames = (input_frames * output_freq) / input_freq;
+  size_t output_size = output_frames * output_frame_size;
+
+  uint8_t output_data[output_size];
+  for (size_t i = 0; i < output_frames; i++) {
+    memset(output_data, 0, output_size);
+    resampler->resample((int*)output_data, i, &provider);
+  }
+
+  return 0;
+}
diff --git a/media/libcpustats/Android.bp b/media/libcpustats/Android.bp
index 8fcd8a4..6e8ca1d 100644
--- a/media/libcpustats/Android.bp
+++ b/media/libcpustats/Android.bp
@@ -6,6 +6,14 @@
         "ThreadCpuUsage.cpp",
     ],
 
+    local_include_dirs: [
+        "include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/media/libdatasource/Android.bp b/media/libdatasource/Android.bp
new file mode 100644
index 0000000..f191c21
--- /dev/null
+++ b/media/libdatasource/Android.bp
@@ -0,0 +1,63 @@
+cc_library {
+    name: "libdatasource",
+
+    srcs: [
+        "DataSourceFactory.cpp",
+        "DataURISource.cpp",
+        "FileSource.cpp",
+        "HTTPBase.cpp",
+        "MediaHTTP.cpp",
+        "NuCachedSource2.cpp",
+    ],
+
+    aidl: {
+        local_include_dirs: ["aidl"],
+        export_aidl_headers: true,
+    },
+
+    header_libs: [
+        "libstagefright_headers",
+        "media_ndk_headers",
+        "libmedia_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libstagefright_headers",
+        "media_ndk_headers",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libutils",
+        "libstagefright_foundation",
+        "libdl",
+    ],
+
+    static_libs: [
+        "libc_malloc_debug_backtrace",  // for memory heap analysis
+        "libmedia_midiiowrapper",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libstagefright/DataSourceFactory.cpp b/media/libdatasource/DataSourceFactory.cpp
similarity index 72%
rename from media/libstagefright/DataSourceFactory.cpp
rename to media/libdatasource/DataSourceFactory.cpp
index 54bf0cc..bb6a08c 100644
--- a/media/libstagefright/DataSourceFactory.cpp
+++ b/media/libdatasource/DataSourceFactory.cpp
@@ -16,20 +16,33 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "DataSource"
 
-#include "include/HTTPBase.h"
-#include "include/NuCachedSource2.h"
 
+#include <datasource/DataSourceFactory.h>
+#include <datasource/DataURISource.h>
+#include <datasource/HTTPBase.h>
+#include <datasource/FileSource.h>
+#include <datasource/MediaHTTP.h>
+#include <datasource/NuCachedSource2.h>
 #include <media/MediaHTTPConnection.h>
 #include <media/MediaHTTPService.h>
-#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/DataURISource.h>
-#include <media/stagefright/FileSource.h>
-#include <media/stagefright/MediaHTTP.h>
 #include <utils/String8.h>
 
 namespace android {
 
 // static
+sp<DataSourceFactory> DataSourceFactory::sInstance;
+// static
+Mutex DataSourceFactory::sInstanceLock;
+
+// static
+sp<DataSourceFactory> DataSourceFactory::getInstance() {
+    Mutex::Autolock l(sInstanceLock);
+    if (!sInstance) {
+        sInstance = new DataSourceFactory();
+    }
+    return sInstance;
+}
+
 sp<DataSource> DataSourceFactory::CreateFromURI(
         const sp<MediaHTTPService> &httpService,
         const char *uri,
@@ -42,20 +55,16 @@
 
     sp<DataSource> source;
     if (!strncasecmp("file://", uri, 7)) {
-        source = new FileSource(uri + 7);
+        source = CreateFileSource(uri + 7);
     } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
         if (httpService == NULL) {
             ALOGE("Invalid http service!");
             return NULL;
         }
 
-        if (httpSource == NULL) {
-            sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
-            if (conn == NULL) {
-                ALOGE("Failed to make http connection from http service!");
-                return NULL;
-            }
-            httpSource = new MediaHTTP(conn);
+        sp<HTTPBase> mediaHTTP = httpSource;
+        if (mediaHTTP == NULL) {
+            mediaHTTP = static_cast<HTTPBase *>(CreateMediaHTTP(httpService).get());
         }
 
         String8 cacheConfig;
@@ -69,24 +78,24 @@
                     &disconnectAtHighwatermark);
         }
 
-        if (httpSource->connect(uri, &nonCacheSpecificHeaders) != OK) {
+        if (mediaHTTP->connect(uri, &nonCacheSpecificHeaders) != OK) {
             ALOGE("Failed to connect http source!");
             return NULL;
         }
 
         if (contentType != NULL) {
-            *contentType = httpSource->getMIMEType();
+            *contentType = mediaHTTP->getMIMEType();
         }
 
         source = NuCachedSource2::Create(
-                httpSource,
+                mediaHTTP,
                 cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                 disconnectAtHighwatermark);
     } else if (!strncasecmp("data:", uri, 5)) {
         source = DataURISource::Create(uri);
     } else {
         // Assume it's a filename.
-        source = new FileSource(uri);
+        source = CreateFileSource(uri);
     }
 
     if (source == NULL || source->initCheck() != OK) {
@@ -108,10 +117,15 @@
 
     sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
     if (conn == NULL) {
+        ALOGE("Failed to make http connection from http service!");
         return NULL;
     } else {
         return new MediaHTTP(conn);
     }
 }
 
+sp<DataSource> DataSourceFactory::CreateFileSource(const char *uri) {
+    return new FileSource(uri);
+}
+
 }  // namespace android
diff --git a/media/libstagefright/DataURISource.cpp b/media/libdatasource/DataURISource.cpp
similarity index 98%
rename from media/libstagefright/DataURISource.cpp
rename to media/libdatasource/DataURISource.cpp
index b975b38..216f3d0 100644
--- a/media/libstagefright/DataURISource.cpp
+++ b/media/libdatasource/DataURISource.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <media/stagefright/DataURISource.h>
+#include <datasource/DataURISource.h>
 
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AString.h>
diff --git a/media/libstagefright/ClearFileSource.cpp b/media/libdatasource/FileSource.cpp
similarity index 85%
rename from media/libstagefright/ClearFileSource.cpp
rename to media/libdatasource/FileSource.cpp
index e3a2cb7..bbf7dda 100644
--- a/media/libstagefright/ClearFileSource.cpp
+++ b/media/libdatasource/FileSource.cpp
@@ -15,12 +15,12 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "ClearFileSource"
+#define LOG_TAG "FileSource"
 #include <utils/Log.h>
 
+#include <datasource/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/ClearFileSource.h>
-#include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -29,7 +29,7 @@
 
 namespace android {
 
-ClearFileSource::ClearFileSource(const char *filename)
+FileSource::FileSource(const char *filename)
     : mFd(-1),
       mOffset(0),
       mLength(-1),
@@ -48,7 +48,7 @@
     }
 }
 
-ClearFileSource::ClearFileSource(int fd, int64_t offset, int64_t length)
+FileSource::FileSource(int fd, int64_t offset, int64_t length)
     : mFd(fd),
       mOffset(offset),
       mLength(length),
@@ -89,18 +89,18 @@
 
 }
 
-ClearFileSource::~ClearFileSource() {
+FileSource::~FileSource() {
     if (mFd >= 0) {
         ::close(mFd);
         mFd = -1;
     }
 }
 
-status_t ClearFileSource::initCheck() const {
+status_t FileSource::initCheck() const {
     return mFd >= 0 ? OK : NO_INIT;
 }
 
-ssize_t ClearFileSource::readAt(off64_t offset, void *data, size_t size) {
+ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
     if (mFd < 0) {
         return NO_INIT;
     }
@@ -118,7 +118,7 @@
     return readAt_l(offset, data, size);
 }
 
-ssize_t ClearFileSource::readAt_l(off64_t offset, void *data, size_t size) {
+ssize_t FileSource::readAt_l(off64_t offset, void *data, size_t size) {
     off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET);
     if (result == -1) {
         ALOGE("seek to %lld failed", (long long)(offset + mOffset));
@@ -128,7 +128,7 @@
     return ::read(mFd, data, size);
 }
 
-status_t ClearFileSource::getSize(off64_t *size) {
+status_t FileSource::getSize(off64_t *size) {
     Mutex::Autolock autoLock(mLock);
 
     if (mFd < 0) {
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libdatasource/HTTPBase.cpp
similarity index 98%
rename from media/libstagefright/HTTPBase.cpp
rename to media/libdatasource/HTTPBase.cpp
index d118e8c..ef29c48 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libdatasource/HTTPBase.cpp
@@ -18,7 +18,7 @@
 #define LOG_TAG "HTTPBase"
 #include <utils/Log.h>
 
-#include "include/HTTPBase.h"
+#include <datasource/HTTPBase.h>
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
diff --git a/media/libstagefright/http/ClearMediaHTTP.cpp b/media/libdatasource/MediaHTTP.cpp
similarity index 82%
rename from media/libstagefright/http/ClearMediaHTTP.cpp
rename to media/libdatasource/MediaHTTP.cpp
index 9557c8a..58c1ce8 100644
--- a/media/libstagefright/http/ClearMediaHTTP.cpp
+++ b/media/libdatasource/MediaHTTP.cpp
@@ -15,30 +15,30 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "ClearMediaHTTP"
+#define LOG_TAG "MediaHTTP"
 #include <utils/Log.h>
 
-#include <media/stagefright/ClearMediaHTTP.h>
+#include <datasource/MediaHTTP.h>
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <media/MediaHTTPConnection.h>
 
 namespace android {
 
-ClearMediaHTTP::ClearMediaHTTP(const sp<MediaHTTPConnection> &conn)
+MediaHTTP::MediaHTTP(const sp<MediaHTTPConnection> &conn)
     : mInitCheck((conn != NULL) ? OK : NO_INIT),
       mHTTPConnection(conn),
       mCachedSizeValid(false),
       mCachedSize(0ll) {
 }
 
-ClearMediaHTTP::~ClearMediaHTTP() {
+MediaHTTP::~MediaHTTP() {
 }
 
-status_t ClearMediaHTTP::connect(
+status_t MediaHTTP::connect(
         const char *uri,
         const KeyedVector<String8, String8> *headers,
         off64_t /* offset */) {
@@ -68,18 +68,18 @@
 
     if (success) {
         AString sanitized = uriDebugString(mLastURI);
-        mName = String8::format("ClearMediaHTTP(%s)", sanitized.c_str());
+        mName = String8::format("MediaHTTP(%s)", sanitized.c_str());
     }
 
     return success ? OK : UNKNOWN_ERROR;
 }
 
-void ClearMediaHTTP::close() {
+void MediaHTTP::close() {
     disconnect();
 }
 
-void ClearMediaHTTP::disconnect() {
-    mName = String8("ClearMediaHTTP(<disconnected>)");
+void MediaHTTP::disconnect() {
+    mName = String8("MediaHTTP(<disconnected>)");
     if (mInitCheck != OK) {
         return;
     }
@@ -87,11 +87,11 @@
     mHTTPConnection->disconnect();
 }
 
-status_t ClearMediaHTTP::initCheck() const {
+status_t MediaHTTP::initCheck() const {
     return mInitCheck;
 }
 
-ssize_t ClearMediaHTTP::readAt(off64_t offset, void *data, size_t size) {
+ssize_t MediaHTTP::readAt(off64_t offset, void *data, size_t size) {
     if (mInitCheck != OK) {
         return mInitCheck;
     }
@@ -127,7 +127,7 @@
     return numBytesRead;
 }
 
-status_t ClearMediaHTTP::getSize(off64_t *size) {
+status_t MediaHTTP::getSize(off64_t *size) {
     if (mInitCheck != OK) {
         return mInitCheck;
     }
@@ -145,16 +145,16 @@
     return *size < 0 ? *size : static_cast<status_t>(OK);
 }
 
-uint32_t ClearMediaHTTP::flags() {
+uint32_t MediaHTTP::flags() {
     return kWantsPrefetching | kIsHTTPBasedSource;
 }
 
-status_t ClearMediaHTTP::reconnectAtOffset(off64_t offset) {
+status_t MediaHTTP::reconnectAtOffset(off64_t offset) {
     return connect(mLastURI.c_str(), &mLastHeaders, offset);
 }
 
 
-String8 ClearMediaHTTP::getUri() {
+String8 MediaHTTP::getUri() {
     if (mInitCheck != OK) {
         return String8::empty();
     }
@@ -166,7 +166,7 @@
     return String8(mLastURI.c_str());
 }
 
-String8 ClearMediaHTTP::getMIMEType() const {
+String8 MediaHTTP::getMIMEType() const {
     if (mInitCheck != OK) {
         return String8("application/octet-stream");
     }
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libdatasource/NuCachedSource2.cpp
similarity index 99%
rename from media/libstagefright/NuCachedSource2.cpp
rename to media/libdatasource/NuCachedSource2.cpp
index 522c81d..7f5ae61 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libdatasource/NuCachedSource2.cpp
@@ -20,8 +20,8 @@
 #define LOG_TAG "NuCachedSource2"
 #include <utils/Log.h>
 
-#include "include/NuCachedSource2.h"
-#include "include/HTTPBase.h"
+#include <datasource/NuCachedSource2.h>
+#include <datasource/HTTPBase.h>
 
 #include <cutils/properties.h>
 #include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libstagefright/include/media/stagefright/DataSourceFactory.h b/media/libdatasource/include/datasource/DataSourceFactory.h
similarity index 66%
rename from media/libstagefright/include/media/stagefright/DataSourceFactory.h
rename to media/libdatasource/include/datasource/DataSourceFactory.h
index 2a1d491..194abe2 100644
--- a/media/libstagefright/include/media/stagefright/DataSourceFactory.h
+++ b/media/libdatasource/include/datasource/DataSourceFactory.h
@@ -18,7 +18,9 @@
 
 #define DATA_SOURCE_FACTORY_H_
 
+#include <media/DataSource.h>
 #include <sys/types.h>
+#include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
 
 namespace android {
@@ -27,17 +29,27 @@
 class String8;
 struct HTTPBase;
 
-class DataSourceFactory {
+class DataSourceFactory : public RefBase {
 public:
-    static sp<DataSource> CreateFromURI(
+    static sp<DataSourceFactory> getInstance();
+    sp<DataSource> CreateFromURI(
             const sp<MediaHTTPService> &httpService,
             const char *uri,
             const KeyedVector<String8, String8> *headers = NULL,
             String8 *contentType = NULL,
             HTTPBase *httpSource = NULL);
 
-    static sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
-    static sp<DataSource> CreateFromFd(int fd, int64_t offset, int64_t length);
+    virtual sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
+    sp<DataSource> CreateFromFd(int fd, int64_t offset, int64_t length);
+
+protected:
+    virtual sp<DataSource> CreateFileSource(const char *uri);
+    DataSourceFactory() {};
+    virtual ~DataSourceFactory() {};
+
+private:
+    static sp<DataSourceFactory> sInstance;
+    static Mutex sInstanceLock;
 };
 
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/DataURISource.h b/media/libdatasource/include/datasource/DataURISource.h
similarity index 100%
rename from media/libstagefright/include/media/stagefright/DataURISource.h
rename to media/libdatasource/include/datasource/DataURISource.h
diff --git a/media/libstagefright/include/media/stagefright/ClearFileSource.h b/media/libdatasource/include/datasource/FileSource.h
similarity index 74%
rename from media/libstagefright/include/media/stagefright/ClearFileSource.h
rename to media/libdatasource/include/datasource/FileSource.h
index be83748..dee0c33 100644
--- a/media/libstagefright/include/media/stagefright/ClearFileSource.h
+++ b/media/libdatasource/include/datasource/FileSource.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef CLEAR_FILE_SOURCE_H_
+#ifndef FILE_SOURCE_H_
 
-#define CLEAR_FILE_SOURCE_H_
+#define FILE_SOURCE_H_
 
 #include <stdio.h>
 
@@ -26,11 +26,11 @@
 
 namespace android {
 
-class ClearFileSource : public DataSource {
+class FileSource : public DataSource {
 public:
-    ClearFileSource(const char *filename);
-    // ClearFileSource takes ownership and will close the fd
-    ClearFileSource(int fd, int64_t offset, int64_t length);
+    FileSource(const char *filename);
+    // FileSource takes ownership and will close the fd
+    FileSource(int fd, int64_t offset, int64_t length);
 
     virtual status_t initCheck() const;
 
@@ -47,7 +47,7 @@
     }
 
 protected:
-    virtual ~ClearFileSource();
+    virtual ~FileSource();
     virtual ssize_t readAt_l(off64_t offset, void *data, size_t size);
 
     int mFd;
@@ -58,11 +58,11 @@
 private:
     String8 mName;
 
-    ClearFileSource(const ClearFileSource &);
-    ClearFileSource &operator=(const ClearFileSource &);
+    FileSource(const FileSource &);
+    FileSource &operator=(const FileSource &);
 };
 
 }  // namespace android
 
-#endif  // CLEAR_FILE_SOURCE_H_
+#endif  // FILE_SOURCE_H_
 
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libdatasource/include/datasource/HTTPBase.h
similarity index 100%
rename from media/libstagefright/include/HTTPBase.h
rename to media/libdatasource/include/datasource/HTTPBase.h
diff --git a/media/libstagefright/include/media/stagefright/ClearMediaHTTP.h b/media/libdatasource/include/datasource/MediaHTTP.h
similarity index 83%
rename from media/libstagefright/include/media/stagefright/ClearMediaHTTP.h
rename to media/libdatasource/include/datasource/MediaHTTP.h
index 72907a9..a8d203b 100644
--- a/media/libstagefright/include/media/stagefright/ClearMediaHTTP.h
+++ b/media/libdatasource/include/datasource/MediaHTTP.h
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-#ifndef CLEAR_MEDIA_HTTP_H_
+#ifndef MEDIA_HTTP_H_
 
-#define CLEAR_MEDIA_HTTP_H_
+#define MEDIA_HTTP_H_
 
 #include <media/stagefright/foundation/AString.h>
 
-#include "include/HTTPBase.h"
+#include "HTTPBase.h"
 
 namespace android {
 
 struct MediaHTTPConnection;
 
-struct ClearMediaHTTP : public HTTPBase {
-    ClearMediaHTTP(const sp<MediaHTTPConnection> &conn);
+struct MediaHTTP : public HTTPBase {
+    MediaHTTP(const sp<MediaHTTPConnection> &conn);
 
     virtual status_t connect(
             const char *uri,
@@ -49,7 +49,7 @@
     virtual status_t reconnectAtOffset(off64_t offset);
 
 protected:
-    virtual ~ClearMediaHTTP();
+    virtual ~MediaHTTP();
 
     virtual String8 getUri();
     virtual String8 getMIMEType() const;
@@ -65,9 +65,9 @@
     bool mCachedSizeValid;
     off64_t mCachedSize;
 
-    DISALLOW_EVIL_CONSTRUCTORS(ClearMediaHTTP);
+    DISALLOW_EVIL_CONSTRUCTORS(MediaHTTP);
 };
 
 }  // namespace android
 
-#endif  // CLEAR_MEDIA_HTTP_H_
+#endif  // MEDIA_HTTP_H_
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libdatasource/include/datasource/NuCachedSource2.h
similarity index 100%
rename from media/libstagefright/include/NuCachedSource2.h
rename to media/libdatasource/include/datasource/NuCachedSource2.h
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 3fbbc09..10dda19 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -302,6 +302,8 @@
         for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
             pContext->pBundledContext->bandGaindB[i] = EQNB_5BandSoftPresets[i];
         }
+        pContext->pBundledContext->effectProcessCalled      = 0;
+        pContext->pBundledContext->effectInDrain            = 0;
 
         ALOGV("\tEffectCreate - Calling LvmBundle_init");
         ret = LvmBundle_init(pContext);
@@ -394,6 +396,8 @@
 
     // Clear the instantiated flag for the effect
     // protect agains the case where an effect is un-instantiated without being disabled
+
+    int &effectInDrain = pContext->pBundledContext->effectInDrain;
     if(pContext->EffectType == LVM_BASS_BOOST) {
         ALOGV("\tEffectRelease LVM_BASS_BOOST Clearing global intstantiated flag");
         pSessionContext->bBassInstantiated = LVM_FALSE;
@@ -418,12 +422,16 @@
     } else if(pContext->EffectType == LVM_VOLUME) {
         ALOGV("\tEffectRelease LVM_VOLUME Clearing global intstantiated flag");
         pSessionContext->bVolumeInstantiated = LVM_FALSE;
-        if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE){
+        // There is no samplesToExitCount for volume so we also use the drain flag to check
+        // if we should decrement the effects enabled.
+        if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE
+                || (effectInDrain & 1 << LVM_VOLUME) != 0) {
             pContext->pBundledContext->NumberEffectsEnabled--;
         }
     } else {
         ALOGV("\tLVM_ERROR : EffectRelease : Unsupported effect\n\n\n\n\n\n\n");
     }
+    effectInDrain &= ~(1 << pContext->EffectType); // no need to drain if released
 
     // Disable effect, in this case ignore errors (return codes)
     // if an effect has already been disabled
@@ -3124,8 +3132,9 @@
 
 int Effect_setEnabled(EffectContext *pContext, bool enabled)
 {
-    ALOGV("\tEffect_setEnabled() type %d, enabled %d", pContext->EffectType, enabled);
-
+    ALOGV("%s effectType %d, enabled %d, currently enabled %d", __func__,
+            pContext->EffectType, enabled, pContext->pBundledContext->NumberEffectsEnabled);
+    int &effectInDrain = pContext->pBundledContext->effectInDrain;
     if (enabled) {
         // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due
         // to their nature.
@@ -3139,6 +3148,7 @@
                 if(pContext->pBundledContext->SamplesToExitCountBb <= 0){
                     pContext->pBundledContext->NumberEffectsEnabled++;
                 }
+                effectInDrain &= ~(1 << LVM_BASS_BOOST);
                 pContext->pBundledContext->SamplesToExitCountBb =
                      (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
                 pContext->pBundledContext->bBassEnabled = LVM_TRUE;
@@ -3152,6 +3162,7 @@
                 if(pContext->pBundledContext->SamplesToExitCountEq <= 0){
                     pContext->pBundledContext->NumberEffectsEnabled++;
                 }
+                effectInDrain &= ~(1 << LVM_EQUALIZER);
                 pContext->pBundledContext->SamplesToExitCountEq =
                      (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
                 pContext->pBundledContext->bEqualizerEnabled = LVM_TRUE;
@@ -3164,6 +3175,7 @@
                 if(pContext->pBundledContext->SamplesToExitCountVirt <= 0){
                     pContext->pBundledContext->NumberEffectsEnabled++;
                 }
+                effectInDrain &= ~(1 << LVM_VIRTUALIZER);
                 pContext->pBundledContext->SamplesToExitCountVirt =
                      (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
                 pContext->pBundledContext->bVirtualizerEnabled = LVM_TRUE;
@@ -3174,7 +3186,10 @@
                     ALOGV("\tEffect_setEnabled() LVM_VOLUME is already enabled");
                     return -EINVAL;
                 }
-                pContext->pBundledContext->NumberEffectsEnabled++;
+                if ((effectInDrain & 1 << LVM_VOLUME) == 0) {
+                    pContext->pBundledContext->NumberEffectsEnabled++;
+                }
+                effectInDrain &= ~(1 << LVM_VOLUME);
                 pContext->pBundledContext->bVolumeEnabled = LVM_TRUE;
                 break;
             default:
@@ -3192,6 +3207,7 @@
                     return -EINVAL;
                 }
                 pContext->pBundledContext->bBassEnabled = LVM_FALSE;
+                effectInDrain |= 1 << LVM_BASS_BOOST;
                 break;
             case LVM_EQUALIZER:
                 if (pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE) {
@@ -3199,6 +3215,7 @@
                     return -EINVAL;
                 }
                 pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
+                effectInDrain |= 1 << LVM_EQUALIZER;
                 break;
             case LVM_VIRTUALIZER:
                 if (pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE) {
@@ -3206,6 +3223,7 @@
                     return -EINVAL;
                 }
                 pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
+                effectInDrain |= 1 << LVM_VIRTUALIZER;
                 break;
             case LVM_VOLUME:
                 if (pContext->pBundledContext->bVolumeEnabled == LVM_FALSE) {
@@ -3213,6 +3231,7 @@
                     return -EINVAL;
                 }
                 pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
+                effectInDrain |= 1 << LVM_VOLUME;
                 break;
             default:
                 ALOGV("\tEffect_setEnabled() invalid effect type");
@@ -3283,6 +3302,38 @@
         ALOGV("\tLVM_ERROR : Effect_process() ERROR NULL INPUT POINTER OR FRAME COUNT IS WRONG");
         return -EINVAL;
     }
+
+    int &effectProcessCalled = pContext->pBundledContext->effectProcessCalled;
+    int &effectInDrain = pContext->pBundledContext->effectInDrain;
+    if ((effectProcessCalled & 1 << pContext->EffectType) != 0) {
+        ALOGW("Effect %d already called", pContext->EffectType);
+        const int undrainedEffects = effectInDrain & ~effectProcessCalled;
+        if ((undrainedEffects & 1 << LVM_BASS_BOOST) != 0) {
+            ALOGW("Draining BASS_BOOST");
+            pContext->pBundledContext->SamplesToExitCountBb = 0;
+            --pContext->pBundledContext->NumberEffectsEnabled;
+            effectInDrain &= ~(1 << LVM_BASS_BOOST);
+        }
+        if ((undrainedEffects & 1 << LVM_EQUALIZER) != 0) {
+            ALOGW("Draining EQUALIZER");
+            pContext->pBundledContext->SamplesToExitCountEq = 0;
+            --pContext->pBundledContext->NumberEffectsEnabled;
+            effectInDrain &= ~(1 << LVM_EQUALIZER);
+        }
+        if ((undrainedEffects & 1 << LVM_VIRTUALIZER) != 0) {
+            ALOGW("Draining VIRTUALIZER");
+            pContext->pBundledContext->SamplesToExitCountVirt = 0;
+            --pContext->pBundledContext->NumberEffectsEnabled;
+            effectInDrain &= ~(1 << LVM_VIRTUALIZER);
+        }
+        if ((undrainedEffects & 1 << LVM_VOLUME) != 0) {
+            ALOGW("Draining VOLUME");
+            --pContext->pBundledContext->NumberEffectsEnabled;
+            effectInDrain &= ~(1 << LVM_VOLUME);
+        }
+    }
+    effectProcessCalled |= 1 << pContext->EffectType;
+
     if ((pContext->pBundledContext->bBassEnabled == LVM_FALSE)&&
         (pContext->EffectType == LVM_BASS_BOOST)){
         //ALOGV("\tEffect_process() LVM_BASS_BOOST Effect is not enabled");
@@ -3291,9 +3342,12 @@
             //ALOGV("\tEffect_process: Waiting to turn off BASS_BOOST, %d samples left",
             //    pContext->pBundledContext->SamplesToExitCountBb);
         }
-        if(pContext->pBundledContext->SamplesToExitCountBb <= 0) {
+        if (pContext->pBundledContext->SamplesToExitCountBb <= 0) {
             status = -ENODATA;
-            pContext->pBundledContext->NumberEffectsEnabled--;
+            if ((effectInDrain & 1 << LVM_BASS_BOOST) != 0) {
+                pContext->pBundledContext->NumberEffectsEnabled--;
+                effectInDrain &= ~(1 << LVM_BASS_BOOST);
+            }
             ALOGV("\tEffect_process() this is the last frame for LVM_BASS_BOOST");
         }
     }
@@ -3301,7 +3355,10 @@
         (pContext->EffectType == LVM_VOLUME)){
         //ALOGV("\tEffect_process() LVM_VOLUME Effect is not enabled");
         status = -ENODATA;
-        pContext->pBundledContext->NumberEffectsEnabled--;
+        if ((effectInDrain & 1 << LVM_VOLUME) != 0) {
+            pContext->pBundledContext->NumberEffectsEnabled--;
+            effectInDrain &= ~(1 << LVM_VOLUME);
+        }
     }
     if ((pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE)&&
         (pContext->EffectType == LVM_EQUALIZER)){
@@ -3311,9 +3368,12 @@
             //ALOGV("\tEffect_process: Waiting to turn off EQUALIZER, %d samples left",
             //    pContext->pBundledContext->SamplesToExitCountEq);
         }
-        if(pContext->pBundledContext->SamplesToExitCountEq <= 0) {
+        if (pContext->pBundledContext->SamplesToExitCountEq <= 0) {
             status = -ENODATA;
-            pContext->pBundledContext->NumberEffectsEnabled--;
+            if ((effectInDrain & 1 << LVM_EQUALIZER) != 0) {
+                pContext->pBundledContext->NumberEffectsEnabled--;
+                effectInDrain &= ~(1 << LVM_EQUALIZER);
+            }
             ALOGV("\tEffect_process() this is the last frame for LVM_EQUALIZER");
         }
     }
@@ -3326,9 +3386,12 @@
             //ALOGV("\tEffect_process: Waiting for to turn off VIRTUALIZER, %d samples left",
             //    pContext->pBundledContext->SamplesToExitCountVirt);
         }
-        if(pContext->pBundledContext->SamplesToExitCountVirt <= 0) {
+        if (pContext->pBundledContext->SamplesToExitCountVirt <= 0) {
             status = -ENODATA;
-            pContext->pBundledContext->NumberEffectsEnabled--;
+            if ((effectInDrain & 1 << LVM_VIRTUALIZER) != 0) {
+                pContext->pBundledContext->NumberEffectsEnabled--;
+                effectInDrain &= ~(1 << LVM_VIRTUALIZER);
+            }
             ALOGV("\tEffect_process() this is the last frame for LVM_VIRTUALIZER");
         }
     }
@@ -3337,8 +3400,18 @@
         pContext->pBundledContext->NumberEffectsCalled++;
     }
 
-    if(pContext->pBundledContext->NumberEffectsCalled ==
-       pContext->pBundledContext->NumberEffectsEnabled){
+    if (pContext->pBundledContext->NumberEffectsCalled >=
+            pContext->pBundledContext->NumberEffectsEnabled) {
+
+        // We expect the # effects called to be equal to # effects enabled in sequence (including
+        // draining effects).  Warn if this is not the case due to inconsistent calls.
+        ALOGW_IF(pContext->pBundledContext->NumberEffectsCalled >
+                pContext->pBundledContext->NumberEffectsEnabled,
+                "%s Number of effects called %d is greater than number of effects enabled %d",
+                __func__, pContext->pBundledContext->NumberEffectsCalled,
+                pContext->pBundledContext->NumberEffectsEnabled);
+        effectProcessCalled = 0; // reset our consistency check.
+
         //ALOGV("\tEffect_process     Calling process with %d effects enabled, %d called: Effect %d",
         //pContext->pBundledContext->NumberEffectsEnabled,
         //pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 6af4554..e4aacd0 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -110,6 +110,14 @@
 #ifdef SUPPORT_MC
     LVM_INT32                       ChMask;
 #endif
+
+    /* Bitmask whether drain is in progress due to disabling the effect.
+       The corresponding bit to an effect is set by 1 << lvm_effect_en. */
+    int                             effectInDrain;
+
+    /* Bitmask whether process() was called for a particular effect.
+       The corresponding bit to an effect is set by 1 << lvm_effect_en. */
+    int                             effectProcessCalled;
 };
 
 /* SessionContext : One session */
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 8de6381..b49df9e 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -60,10 +60,8 @@
     srcs: [
         ":libmedia_omx_aidl",
 
-        "IMediaCodecList.cpp",
         "IOMX.cpp",
         "MediaCodecBuffer.cpp",
-        "MediaCodecInfo.cpp",
         "OMXBuffer.cpp",
         "omx/1.0/WGraphicBufferSource.cpp",
         "omx/1.0/WOmxBufferSource.cpp",
@@ -75,7 +73,7 @@
         local_include_dirs: ["aidl"],
         export_aidl_headers: true,
     },
-    
+
     local_include_dirs: [
         "include",
     ],
@@ -199,6 +197,7 @@
     ],
 
     header_libs: [
+        "libmedia_headers",
         "media_ndk_headers",
     ],
 
@@ -217,6 +216,49 @@
     },
 }
 
+cc_library_shared {
+    name: "libmedia_codeclist",
+
+    srcs: [
+        "IMediaCodecList.cpp",
+        "MediaCodecInfo.cpp",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    shared_libs: [
+        "android.hardware.media.omx@1.0",
+        "libbinder",
+        "liblog",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+
+    include_dirs: [
+        "system/libhidl/transport/token/1.0/utils/include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
+
 cc_library {
     name: "libmedia",
 
@@ -244,8 +286,6 @@
         "mediarecorder.cpp",
         "IMediaMetadataRetriever.cpp",
         "mediametadataretriever.cpp",
-        "MidiDeviceInfo.cpp",
-        "JetPlayer.cpp",
         "MediaScanner.cpp",
         "MediaScannerClient.cpp",
         "CharacterEncodingDetector.cpp",
@@ -253,7 +293,6 @@
         "MediaProfiles.cpp",
         "MediaResource.cpp",
         "MediaResourcePolicy.cpp",
-        "Visualizer.cpp",
         "StringArray.cpp",
         "NdkMediaFormatPriv.cpp",
         "NdkMediaErrorPriv.cpp",
@@ -289,8 +328,8 @@
         "libstagefright_foundation",
         "libgui",
         "libdl",
-        "libaudioutils",
         "libaudioclient",
+        "libmedia_codeclist",
         "libmedia_omx",
     ],
 
@@ -304,7 +343,6 @@
 
     static_libs: [
         "libc_malloc_debug_backtrace",  // for memory heap analysis
-        "libmedia_midiiowrapper",
     ],
 
     export_include_dirs: [
@@ -327,64 +365,3 @@
         cfi: true,
     },
 }
-
-cc_library_static {
-    name: "libmedia_player2_util",
-
-    srcs: [
-        "AudioParameter.cpp",
-        "BufferingSettings.cpp",
-        "DataSourceDesc.cpp",
-        "MediaCodecBuffer.cpp",
-        "Metadata.cpp",
-        "NdkWrapper.cpp",
-    ],
-
-    shared_libs: [
-        "libbinder",
-        "libcutils",
-        "liblog",
-        "libmediandk",
-        "libnativewindow",
-        "libmediandk_utils",
-        "libstagefright_foundation",
-        "libui",
-        "libutils",
-    ],
-
-    export_shared_lib_headers: [
-        "libbinder",
-        "libmediandk",
-    ],
-
-    header_libs: [
-        "media_plugin_headers",
-    ],
-
-    include_dirs: [
-        "frameworks/av/media/ndk",
-    ],
-
-    static_libs: [
-        "libstagefright_rtsp",
-        "libstagefright_timedtext",
-    ],
-
-    export_include_dirs: [
-        "include",
-    ],
-
-    cflags: [
-        "-Werror",
-        "-Wno-error=deprecated-declarations",
-        "-Wall",
-    ],
-
-    sanitize: {
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-        cfi: true,
-    },
-}
diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp
index 1c95e27..9f34035 100644
--- a/media/libmedia/AudioParameter.cpp
+++ b/media/libmedia/AudioParameter.cpp
@@ -40,6 +40,8 @@
         AUDIO_PARAMETER_KEY_AUDIO_LANGUAGE_PREFERRED;
 const char * const AudioParameter::keyMonoOutput = AUDIO_PARAMETER_MONO_OUTPUT;
 const char * const AudioParameter::keyStreamHwAvSync = AUDIO_PARAMETER_STREAM_HW_AV_SYNC;
+const char * const AudioParameter::keyDeviceConnect = AUDIO_PARAMETER_DEVICE_CONNECT;
+const char * const AudioParameter::keyDeviceDisconnect = AUDIO_PARAMETER_DEVICE_DISCONNECT;
 const char * const AudioParameter::keyStreamConnect = AUDIO_PARAMETER_DEVICE_CONNECT;
 const char * const AudioParameter::keyStreamDisconnect = AUDIO_PARAMETER_DEVICE_DISCONNECT;
 const char * const AudioParameter::keyStreamSupportedFormats = AUDIO_PARAMETER_STREAM_SUP_FORMATS;
diff --git a/media/libmedia/DataSourceDesc.cpp b/media/libmedia/DataSourceDesc.cpp
deleted file mode 100644
index b7ccbce..0000000
--- a/media/libmedia/DataSourceDesc.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2018 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 "DataSourceDesc"
-
-#include <media/DataSource.h>
-#include <media/DataSourceDesc.h>
-#include <media/MediaHTTPService.h>
-
-namespace android {
-
-static const int64_t kLongMax = 0x7ffffffffffffffL;
-
-DataSourceDesc::DataSourceDesc()
-    : mType(TYPE_NONE),
-      mFDOffset(0),
-      mFDLength(kLongMax),
-      mId(0),
-      mStartPositionMs(0),
-      mEndPositionMs(0) {
-}
-
-}  // namespace android
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
deleted file mode 100644
index 0d3c1ba..0000000
--- a/media/libmedia/JetPlayer.cpp
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright (C) 2008 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 "JetPlayer-C"
-
-#include <utils/Log.h>
-#include <media/JetPlayer.h>
-
-
-namespace android
-{
-
-static const int MIX_NUM_BUFFERS = 4;
-static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
-
-//-------------------------------------------------------------------------------------------------
-JetPlayer::JetPlayer(void *javaJetPlayer, int maxTracks, int trackBufferSize) :
-        mEventCallback(NULL),
-        mJavaJetPlayerRef(javaJetPlayer),
-        mTid(-1),
-        mRender(false),
-        mPaused(false),
-        mMaxTracks(maxTracks),
-        mEasData(NULL),
-        mIoWrapper(NULL),
-        mTrackBufferSize(trackBufferSize)
-{
-    ALOGV("JetPlayer constructor");
-    mPreviousJetStatus.currentUserID = -1;
-    mPreviousJetStatus.segmentRepeatCount = -1;
-    mPreviousJetStatus.numQueuedSegments = -1;
-    mPreviousJetStatus.paused = true;
-}
-
-//-------------------------------------------------------------------------------------------------
-JetPlayer::~JetPlayer()
-{
-    ALOGV("~JetPlayer");
-    release();
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::init()
-{
-    //Mutex::Autolock lock(&mMutex);
-
-    EAS_RESULT result;
-
-    // retrieve the EAS library settings
-    if (pLibConfig == NULL)
-        pLibConfig = EAS_Config();
-    if (pLibConfig == NULL) {
-        ALOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting.");
-        return EAS_FAILURE;
-    }
-
-    // init the EAS library
-    result = EAS_Init(&mEasData);
-    if (result != EAS_SUCCESS) {
-        ALOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting.");
-        mState = EAS_STATE_ERROR;
-        return result;
-    }
-    // init the JET library with the default app event controller range
-    result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG));
-    if (result != EAS_SUCCESS) {
-        ALOGE("JetPlayer::init(): Error initializing JET library, aborting.");
-        mState = EAS_STATE_ERROR;
-        return result;
-    }
-
-    // create the output AudioTrack
-    mAudioTrack = new AudioTrack();
-    status_t status = mAudioTrack->set(AUDIO_STREAM_MUSIC,  //TODO parameterize this
-            pLibConfig->sampleRate,
-            AUDIO_FORMAT_PCM_16_BIT,
-            audio_channel_out_mask_from_count(pLibConfig->numChannels),
-            (size_t) mTrackBufferSize,
-            AUDIO_OUTPUT_FLAG_NONE);
-    if (status != OK) {
-        ALOGE("JetPlayer::init(): Error initializing JET library; AudioTrack error %d", status);
-        mAudioTrack.clear();
-        mState = EAS_STATE_ERROR;
-        return EAS_FAILURE;
-    }
-
-    // create render and playback thread
-    {
-        Mutex::Autolock l(mMutex);
-        ALOGV("JetPlayer::init(): trying to start render thread");
-        mThread = new JetPlayerThread(this);
-        mThread->run("jetRenderThread", ANDROID_PRIORITY_AUDIO);
-        mCondition.wait(mMutex);
-    }
-    if (mTid > 0) {
-        // render thread started, we're ready
-        ALOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid);
-        mState = EAS_STATE_READY;
-    } else {
-        ALOGE("JetPlayer::init(): failed to start render thread.");
-        mState = EAS_STATE_ERROR;
-        return EAS_FAILURE;
-    }
-
-    return EAS_SUCCESS;
-}
-
-void JetPlayer::setEventCallback(jetevent_callback eventCallback)
-{
-    Mutex::Autolock l(mMutex);
-    mEventCallback = eventCallback;
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::release()
-{
-    ALOGV("JetPlayer::release()");
-    Mutex::Autolock lock(mMutex);
-    mPaused = true;
-    mRender = false;
-    if (mEasData) {
-        JET_Pause(mEasData);
-        JET_CloseFile(mEasData);
-        JET_Shutdown(mEasData);
-        EAS_Shutdown(mEasData);
-    }
-    delete mIoWrapper;
-    mIoWrapper = NULL;
-    if (mAudioTrack != 0) {
-        mAudioTrack->stop();
-        mAudioTrack->flush();
-        mAudioTrack.clear();
-    }
-    if (mAudioBuffer) {
-        delete mAudioBuffer;
-        mAudioBuffer = NULL;
-    }
-    mEasData = NULL;
-
-    return EAS_SUCCESS;
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::render() {
-    EAS_RESULT result = EAS_FAILURE;
-    EAS_I32 count;
-    int temp;
-    bool audioStarted = false;
-
-    ALOGV("JetPlayer::render(): entering");
-
-    // allocate render buffer
-    mAudioBuffer =
-        new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS];
-
-    // signal main thread that we started
-    {
-        Mutex::Autolock l(mMutex);
-        mTid = gettid();
-        ALOGV("JetPlayer::render(): render thread(%d) signal", mTid);
-        mCondition.signal();
-    }
-
-    while (1) {
-
-        mMutex.lock(); // [[[[[[[[ LOCK ---------------------------------------
-
-        if (mEasData == NULL) {
-            mMutex.unlock();
-            ALOGV("JetPlayer::render(): NULL EAS data, exiting render.");
-            goto threadExit;
-        }
-
-        // nothing to render, wait for client thread to wake us up
-        while (!mRender)
-        {
-            ALOGV("JetPlayer::render(): signal wait");
-            if (audioStarted) {
-                mAudioTrack->pause();
-                // we have to restart the playback once we start rendering again
-                audioStarted = false;
-            }
-            mCondition.wait(mMutex);
-            ALOGV("JetPlayer::render(): signal rx'd");
-        }
-
-        // render midi data into the input buffer
-        int num_output = 0;
-        EAS_PCM* p = mAudioBuffer;
-        for (int i = 0; i < MIX_NUM_BUFFERS; i++) {
-            result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
-            if (result != EAS_SUCCESS) {
-                ALOGE("JetPlayer::render(): EAS_Render returned error %ld", result);
-            }
-            p += count * pLibConfig->numChannels;
-            num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
-
-            // send events that were generated (if any) to the event callback
-            fireEventsFromJetQueue();
-        }
-
-        // update playback state
-        //ALOGV("JetPlayer::render(): updating state");
-        JET_Status(mEasData, &mJetStatus);
-        fireUpdateOnStatusChange();
-        mPaused = mJetStatus.paused;
-
-        mMutex.unlock(); // UNLOCK ]]]]]]]] -----------------------------------
-
-        // check audio output track
-        if (mAudioTrack == NULL) {
-            ALOGE("JetPlayer::render(): output AudioTrack was not created");
-            goto threadExit;
-        }
-
-        // Write data to the audio hardware
-        //ALOGV("JetPlayer::render(): writing to audio output");
-        if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) {
-            ALOGE("JetPlayer::render(): Error in writing:%d",temp);
-            return temp;
-        }
-
-        // start audio output if necessary
-        if (!audioStarted) {
-            ALOGV("JetPlayer::render(): starting audio playback");
-            mAudioTrack->start();
-            audioStarted = true;
-        }
-
-    }//while (1)
-
-threadExit:
-    if (mAudioTrack != NULL) {
-        mAudioTrack->stop();
-        mAudioTrack->flush();
-    }
-    delete [] mAudioBuffer;
-    mAudioBuffer = NULL;
-    mMutex.lock();
-    mTid = -1;
-    mCondition.signal();
-    mMutex.unlock();
-    return result;
-}
-
-
-//-------------------------------------------------------------------------------------------------
-// fire up an update if any of the status fields has changed
-// precondition: mMutex locked
-void JetPlayer::fireUpdateOnStatusChange()
-{
-    if ( (mJetStatus.currentUserID      != mPreviousJetStatus.currentUserID)
-       ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) {
-        if (mEventCallback)  {
-            mEventCallback(
-                JetPlayer::JET_USERID_UPDATE,
-                mJetStatus.currentUserID,
-                mJetStatus.segmentRepeatCount,
-                mJavaJetPlayerRef);
-        }
-        mPreviousJetStatus.currentUserID      = mJetStatus.currentUserID;
-        mPreviousJetStatus.segmentRepeatCount = mJetStatus.segmentRepeatCount;
-    }
-
-    if (mJetStatus.numQueuedSegments != mPreviousJetStatus.numQueuedSegments) {
-        if (mEventCallback)  {
-            mEventCallback(
-                JetPlayer::JET_NUMQUEUEDSEGMENT_UPDATE,
-                mJetStatus.numQueuedSegments,
-                -1,
-                mJavaJetPlayerRef);
-        }
-        mPreviousJetStatus.numQueuedSegments  = mJetStatus.numQueuedSegments;
-    }
-
-    if (mJetStatus.paused != mPreviousJetStatus.paused) {
-        if (mEventCallback)  {
-            mEventCallback(JetPlayer::JET_PAUSE_UPDATE,
-                mJetStatus.paused,
-                -1,
-                mJavaJetPlayerRef);
-        }
-        mPreviousJetStatus.paused = mJetStatus.paused;
-    }
-
-}
-
-
-//-------------------------------------------------------------------------------------------------
-// fire up all the JET events in the JET engine queue (until the queue is empty)
-// precondition: mMutex locked
-void JetPlayer::fireEventsFromJetQueue()
-{
-    if (!mEventCallback) {
-        // no callback, just empty the event queue
-        while (JET_GetEvent(mEasData, NULL, NULL)) { }
-        return;
-    }
-
-    EAS_U32 rawEvent;
-    while (JET_GetEvent(mEasData, &rawEvent, NULL)) {
-        mEventCallback(
-            JetPlayer::JET_EVENT,
-            rawEvent,
-            -1,
-            mJavaJetPlayerRef);
-    }
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::loadFromFile(const char* path)
-{
-    ALOGV("JetPlayer::loadFromFile(): path=%s", path);
-
-    Mutex::Autolock lock(mMutex);
-
-    delete mIoWrapper;
-    mIoWrapper = new MidiIoWrapper(path);
-
-    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
-    if (result != EAS_SUCCESS)
-        mState = EAS_STATE_ERROR;
-    else
-        mState = EAS_STATE_OPEN;
-    return( result );
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length)
-{
-    ALOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length);
-
-    Mutex::Autolock lock(mMutex);
-
-    delete mIoWrapper;
-    mIoWrapper = new MidiIoWrapper(fd, offset, length);
-
-    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
-    if (result != EAS_SUCCESS)
-        mState = EAS_STATE_ERROR;
-    else
-        mState = EAS_STATE_OPEN;
-    return( result );
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::closeFile()
-{
-    Mutex::Autolock lock(mMutex);
-    return JET_CloseFile(mEasData);
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::play()
-{
-    ALOGV("JetPlayer::play(): entering");
-    Mutex::Autolock lock(mMutex);
-
-    EAS_RESULT result = JET_Play(mEasData);
-
-    mPaused = false;
-    mRender = true;
-
-    JET_Status(mEasData, &mJetStatus);
-    this->dumpJetStatus(&mJetStatus);
-
-    fireUpdateOnStatusChange();
-
-    // wake up render thread
-    ALOGV("JetPlayer::play(): wakeup render thread");
-    mCondition.signal();
-
-    return result;
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::pause()
-{
-    Mutex::Autolock lock(mMutex);
-    mPaused = true;
-    EAS_RESULT result = JET_Pause(mEasData);
-
-    mRender = false;
-
-    JET_Status(mEasData, &mJetStatus);
-    this->dumpJetStatus(&mJetStatus);
-    fireUpdateOnStatusChange();
-
-
-    return result;
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
-        EAS_U32 muteFlags, EAS_U8 userID)
-{
-    ALOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d",
-        segmentNum, libNum, repeatCount, transpose);
-    Mutex::Autolock lock(mMutex);
-    return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags,
-            userID);
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::setMuteFlags(EAS_U32 muteFlags, bool sync)
-{
-    Mutex::Autolock lock(mMutex);
-    return JET_SetMuteFlags(mEasData, muteFlags, sync);
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::setMuteFlag(int trackNum, bool muteFlag, bool sync)
-{
-    Mutex::Autolock lock(mMutex);
-    return JET_SetMuteFlag(mEasData, trackNum, muteFlag, sync);
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::triggerClip(int clipId)
-{
-    ALOGV("JetPlayer::triggerClip clipId=%d", clipId);
-    Mutex::Autolock lock(mMutex);
-    return JET_TriggerClip(mEasData, clipId);
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::clearQueue()
-{
-    ALOGV("JetPlayer::clearQueue");
-    Mutex::Autolock lock(mMutex);
-    return JET_Clear_Queue(mEasData);
-}
-
-//-------------------------------------------------------------------------------------------------
-void JetPlayer::dump()
-{
-}
-
-void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus)
-{
-    if (pJetStatus!=NULL)
-        ALOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d "
-                "paused=%d",
-                pJetStatus->currentUserID, pJetStatus->segmentRepeatCount,
-                pJetStatus->numQueuedSegments, pJetStatus->paused);
-    else
-        ALOGE(">> JET player status is NULL");
-}
-
-
-} // end namespace android
diff --git a/media/libmedia/MidiDeviceInfo.cpp b/media/libmedia/MidiDeviceInfo.cpp
deleted file mode 100644
index 7588e00..0000000
--- a/media/libmedia/MidiDeviceInfo.cpp
+++ /dev/null
@@ -1,138 +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 "MidiDeviceInfo"
-
-#include <media/MidiDeviceInfo.h>
-
-#include <binder/Parcel.h>
-#include <log/log.h>
-#include <utils/Errors.h>
-#include <utils/String16.h>
-
-namespace android {
-namespace media {
-namespace midi {
-
-// The constant values need to be kept in sync with MidiDeviceInfo.java.
-// static
-const char* const MidiDeviceInfo::PROPERTY_NAME = "name";
-const char* const MidiDeviceInfo::PROPERTY_MANUFACTURER = "manufacturer";
-const char* const MidiDeviceInfo::PROPERTY_PRODUCT = "product";
-const char* const MidiDeviceInfo::PROPERTY_VERSION = "version";
-const char* const MidiDeviceInfo::PROPERTY_SERIAL_NUMBER = "serial_number";
-const char* const MidiDeviceInfo::PROPERTY_ALSA_CARD = "alsa_card";
-const char* const MidiDeviceInfo::PROPERTY_ALSA_DEVICE = "alsa_device";
-
-String16 MidiDeviceInfo::getProperty(const char* propertyName) {
-    String16 value;
-    if (mProperties.getString(String16(propertyName), &value)) {
-        return value;
-    } else {
-        return String16();
-    }
-}
-
-#define RETURN_IF_FAILED(calledOnce)                                     \
-    {                                                                    \
-        status_t returnStatus = calledOnce;                              \
-        if (returnStatus) {                                              \
-            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
-            return returnStatus;                                         \
-         }                                                               \
-    }
-
-status_t MidiDeviceInfo::writeToParcel(Parcel* parcel) const {
-    // Needs to be kept in sync with code in MidiDeviceInfo.java
-    RETURN_IF_FAILED(parcel->writeInt32(mType));
-    RETURN_IF_FAILED(parcel->writeInt32(mId));
-    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mInputPortNames.size()));
-    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mOutputPortNames.size()));
-    RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames));
-    RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames));
-    RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0));
-    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
-    // This corresponds to "extra" properties written by Java code
-    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
-    return OK;
-}
-
-status_t MidiDeviceInfo::readFromParcel(const Parcel* parcel) {
-    // Needs to be kept in sync with code in MidiDeviceInfo.java
-    RETURN_IF_FAILED(parcel->readInt32(&mType));
-    RETURN_IF_FAILED(parcel->readInt32(&mId));
-    int32_t inputPortCount;
-    RETURN_IF_FAILED(parcel->readInt32(&inputPortCount));
-    int32_t outputPortCount;
-    RETURN_IF_FAILED(parcel->readInt32(&outputPortCount));
-    RETURN_IF_FAILED(readStringVector(parcel, &mInputPortNames, inputPortCount));
-    RETURN_IF_FAILED(readStringVector(parcel, &mOutputPortNames, outputPortCount));
-    int32_t isPrivate;
-    RETURN_IF_FAILED(parcel->readInt32(&isPrivate));
-    mIsPrivate = isPrivate == 1;
-    RETURN_IF_FAILED(mProperties.readFromParcel(parcel));
-    // Ignore "extra" properties as they may contain Java Parcelables
-    return OK;
-}
-
-status_t MidiDeviceInfo::readStringVector(
-        const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength) {
-    std::unique_ptr<std::vector<std::unique_ptr<String16>>> v;
-    status_t result = parcel->readString16Vector(&v);
-    if (result != OK) return result;
-    vectorPtr->clear();
-    if (v.get() != nullptr) {
-        for (const auto& iter : *v) {
-            if (iter.get() != nullptr) {
-                vectorPtr->push_back(*iter);
-            } else {
-                vectorPtr->push_back(String16());
-            }
-        }
-    } else {
-        vectorPtr->resize(defaultLength);
-    }
-    return OK;
-}
-
-status_t MidiDeviceInfo::writeStringVector(Parcel* parcel, const Vector<String16>& vector) const {
-    std::vector<String16> v;
-    for (size_t i = 0; i < vector.size(); ++i) {
-        v.push_back(vector[i]);
-    }
-    return parcel->writeString16Vector(v);
-}
-
-// Vector does not define operator==
-static inline bool areVectorsEqual(const Vector<String16>& lhs, const Vector<String16>& rhs) {
-    if (lhs.size() != rhs.size()) return false;
-    for (size_t i = 0; i < lhs.size(); ++i) {
-        if (lhs[i] != rhs[i]) return false;
-    }
-    return true;
-}
-
-bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
-    return (lhs.mType == rhs.mType && lhs.mId == rhs.mId &&
-            areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) &&
-            areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) &&
-            lhs.mProperties == rhs.mProperties &&
-            lhs.mIsPrivate == rhs.mIsPrivate);
-}
-
-}  // namespace midi
-}  // namespace media
-}  // namespace android
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index d8ef9cf..6d46363 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -17,7 +17,6 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MidiIoWrapper"
 #include <utils/Log.h>
-#include <utils/RefBase.h>
 
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -50,7 +49,7 @@
     mDataSource = nullptr;
 }
 
-class DataSourceUnwrapper : public DataSourceBase {
+class DataSourceUnwrapper {
 
 public:
     explicit DataSourceUnwrapper(CDataSource *csource) {
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
deleted file mode 100644
index c150407..0000000
--- a/media/libmedia/NdkWrapper.cpp
+++ /dev/null
@@ -1,1290 +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 "NdkWrapper"
-
-#include <media/NdkWrapper.h>
-
-#include <android/native_window.h>
-#include <log/log.h>
-#include <media/NdkMediaCodec.h>
-#include <media/NdkMediaCrypto.h>
-#include <media/NdkMediaDrm.h>
-#include <media/NdkMediaFormat.h>
-#include <media/NdkMediaExtractor.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <utils/Errors.h>
-
-#include "NdkMediaDataSourceCallbacksPriv.h"
-
-namespace android {
-
-static const size_t kAESBlockSize = 16;  // AES_BLOCK_SIZE
-
-static const char *AMediaFormatKeyGroupInt32[] = {
-    AMEDIAFORMAT_KEY_AAC_DRC_ATTENUATION_FACTOR,
-    AMEDIAFORMAT_KEY_AAC_DRC_BOOST_FACTOR,
-    AMEDIAFORMAT_KEY_AAC_DRC_HEAVY_COMPRESSION,
-    AMEDIAFORMAT_KEY_AAC_DRC_TARGET_REFERENCE_LEVEL,
-    AMEDIAFORMAT_KEY_AAC_ENCODED_TARGET_LEVEL,
-    AMEDIAFORMAT_KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT,
-    AMEDIAFORMAT_KEY_AAC_PROFILE,
-    AMEDIAFORMAT_KEY_AAC_SBR_MODE,
-    AMEDIAFORMAT_KEY_AUDIO_SESSION_ID,
-    AMEDIAFORMAT_KEY_BITRATE_MODE,
-    AMEDIAFORMAT_KEY_BIT_RATE,
-    AMEDIAFORMAT_KEY_CAPTURE_RATE,
-    AMEDIAFORMAT_KEY_CHANNEL_COUNT,
-    AMEDIAFORMAT_KEY_CHANNEL_MASK,
-    AMEDIAFORMAT_KEY_COLOR_FORMAT,
-    AMEDIAFORMAT_KEY_COLOR_RANGE,
-    AMEDIAFORMAT_KEY_COLOR_STANDARD,
-    AMEDIAFORMAT_KEY_COLOR_TRANSFER,
-    AMEDIAFORMAT_KEY_COMPLEXITY,
-    AMEDIAFORMAT_KEY_CREATE_INPUT_SURFACE_SUSPENDED,
-    AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE,
-    AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK,
-    AMEDIAFORMAT_KEY_CRYPTO_MODE,
-    AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK,
-    AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL,
-    AMEDIAFORMAT_KEY_GRID_COLUMNS,
-    AMEDIAFORMAT_KEY_GRID_ROWS,
-    AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT,
-    AMEDIAFORMAT_KEY_HEIGHT,
-    AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD,
-    AMEDIAFORMAT_KEY_IS_ADTS,
-    AMEDIAFORMAT_KEY_IS_AUTOSELECT,
-    AMEDIAFORMAT_KEY_IS_DEFAULT,
-    AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE,
-    AMEDIAFORMAT_KEY_LATENCY,
-    AMEDIAFORMAT_KEY_LEVEL,
-    AMEDIAFORMAT_KEY_MAX_HEIGHT,
-    AMEDIAFORMAT_KEY_MAX_INPUT_SIZE,
-    AMEDIAFORMAT_KEY_MAX_WIDTH,
-    AMEDIAFORMAT_KEY_PCM_ENCODING,
-    AMEDIAFORMAT_KEY_PRIORITY,
-    AMEDIAFORMAT_KEY_PROFILE,
-    AMEDIAFORMAT_KEY_PUSH_BLANK_BUFFERS_ON_STOP,
-    AMEDIAFORMAT_KEY_ROTATION,
-    AMEDIAFORMAT_KEY_SAMPLE_RATE,
-    AMEDIAFORMAT_KEY_SLICE_HEIGHT,
-    AMEDIAFORMAT_KEY_STRIDE,
-    AMEDIAFORMAT_KEY_TRACK_ID,
-    AMEDIAFORMAT_KEY_WIDTH,
-    AMEDIAFORMAT_KEY_DISPLAY_HEIGHT,
-    AMEDIAFORMAT_KEY_DISPLAY_WIDTH,
-    AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID,
-    AMEDIAFORMAT_KEY_TILE_HEIGHT,
-    AMEDIAFORMAT_KEY_TILE_WIDTH,
-    AMEDIAFORMAT_KEY_TRACK_INDEX,
-};
-
-static const char *AMediaFormatKeyGroupInt64[] = {
-    AMEDIAFORMAT_KEY_DURATION,
-    AMEDIAFORMAT_KEY_MAX_PTS_GAP_TO_ENCODER,
-    AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER,
-    AMEDIAFORMAT_KEY_TIME_US,
-};
-
-static const char *AMediaFormatKeyGroupString[] = {
-    AMEDIAFORMAT_KEY_LANGUAGE,
-    AMEDIAFORMAT_KEY_MIME,
-    AMEDIAFORMAT_KEY_TEMPORAL_LAYERING,
-};
-
-static const char *AMediaFormatKeyGroupBuffer[] = {
-    AMEDIAFORMAT_KEY_CRYPTO_IV,
-    AMEDIAFORMAT_KEY_CRYPTO_KEY,
-    AMEDIAFORMAT_KEY_HDR_STATIC_INFO,
-    AMEDIAFORMAT_KEY_SEI,
-    AMEDIAFORMAT_KEY_MPEG_USER_DATA,
-};
-
-static const char *AMediaFormatKeyGroupCsd[] = {
-    AMEDIAFORMAT_KEY_CSD_0,
-    AMEDIAFORMAT_KEY_CSD_1,
-    AMEDIAFORMAT_KEY_CSD_2,
-};
-
-static const char *AMediaFormatKeyGroupRect[] = {
-    AMEDIAFORMAT_KEY_DISPLAY_CROP,
-};
-
-static const char *AMediaFormatKeyGroupFloatInt32[] = {
-    AMEDIAFORMAT_KEY_FRAME_RATE,
-    AMEDIAFORMAT_KEY_I_FRAME_INTERVAL,
-    AMEDIAFORMAT_KEY_MAX_FPS_TO_ENCODER,
-    AMEDIAFORMAT_KEY_OPERATING_RATE,
-};
-
-static status_t translateErrorCode(media_status_t err) {
-    if (err == AMEDIA_OK) {
-        return OK;
-    } else if (err == AMEDIA_ERROR_END_OF_STREAM) {
-        return ERROR_END_OF_STREAM;
-    } else if (err == AMEDIA_ERROR_IO) {
-        return ERROR_IO;
-    } else if (err == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
-        return -EAGAIN;
-    }
-
-    ALOGE("ndk error code: %d", err);
-    return UNKNOWN_ERROR;
-}
-
-static int32_t translateActionCode(int32_t actionCode) {
-    if (AMediaCodecActionCode_isTransient(actionCode)) {
-        return ACTION_CODE_TRANSIENT;
-    } else if (AMediaCodecActionCode_isRecoverable(actionCode)) {
-        return ACTION_CODE_RECOVERABLE;
-    }
-    return ACTION_CODE_FATAL;
-}
-
-static CryptoPlugin::Mode translateToCryptoPluginMode(cryptoinfo_mode_t mode) {
-    CryptoPlugin::Mode ret = CryptoPlugin::kMode_Unencrypted;
-    switch (mode) {
-        case AMEDIACODECRYPTOINFO_MODE_AES_CTR: {
-            ret = CryptoPlugin::kMode_AES_CTR;
-            break;
-        }
-
-        case AMEDIACODECRYPTOINFO_MODE_AES_WV: {
-            ret = CryptoPlugin::kMode_AES_WV;
-            break;
-        }
-
-        case AMEDIACODECRYPTOINFO_MODE_AES_CBC: {
-            ret = CryptoPlugin::kMode_AES_CBC;
-            break;
-        }
-
-        default:
-            break;
-    }
-
-    return ret;
-}
-
-static cryptoinfo_mode_t translateToCryptoInfoMode(CryptoPlugin::Mode mode) {
-    cryptoinfo_mode_t ret = AMEDIACODECRYPTOINFO_MODE_CLEAR;
-    switch (mode) {
-        case CryptoPlugin::kMode_AES_CTR: {
-            ret = AMEDIACODECRYPTOINFO_MODE_AES_CTR;
-            break;
-        }
-
-        case CryptoPlugin::kMode_AES_WV: {
-            ret = AMEDIACODECRYPTOINFO_MODE_AES_WV;
-            break;
-        }
-
-        case CryptoPlugin::kMode_AES_CBC: {
-            ret = AMEDIACODECRYPTOINFO_MODE_AES_CBC;
-            break;
-        }
-
-        default:
-            break;
-    }
-
-    return ret;
-}
-
-//////////// AMediaFormatWrapper
-// static
-sp<AMediaFormatWrapper> AMediaFormatWrapper::Create(const sp<AMessage> &message) {
-    sp<AMediaFormatWrapper> aMediaFormat = new AMediaFormatWrapper();
-
-    for (size_t i = 0; i < message->countEntries(); ++i) {
-        AMessage::Type valueType;
-        const char *key = message->getEntryNameAt(i, &valueType);
-
-        switch (valueType) {
-            case AMessage::kTypeInt32: {
-                int32_t val;
-                if (!message->findInt32(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setInt32(key, val);
-                break;
-            }
-
-            case AMessage::kTypeInt64: {
-                int64_t val;
-                if (!message->findInt64(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setInt64(key, val);
-                break;
-            }
-
-            case AMessage::kTypeFloat: {
-                float val;
-                if (!message->findFloat(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setFloat(key, val);
-                break;
-            }
-
-            case AMessage::kTypeDouble: {
-                double val;
-                if (!message->findDouble(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setDouble(key, val);
-                break;
-            }
-
-            case AMessage::kTypeSize: {
-                size_t val;
-                if (!message->findSize(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setSize(key, val);
-                break;
-            }
-
-            case AMessage::kTypeRect: {
-                int32_t left, top, right, bottom;
-                if (!message->findRect(key, &left, &top, &right, &bottom)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setRect(key, left, top, right, bottom);
-                break;
-            }
-
-            case AMessage::kTypeString: {
-                AString val;
-                if (!message->findString(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setString(key, val);
-                break;
-            }
-
-            case AMessage::kTypeBuffer: {
-                sp<ABuffer> val;
-                if (!message->findBuffer(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setBuffer(key, val->data(), val->size());
-                break;
-            }
-
-            default: {
-                break;
-            }
-        }
-    }
-
-    return aMediaFormat;
-}
-
-AMediaFormatWrapper::AMediaFormatWrapper() {
-    mAMediaFormat = AMediaFormat_new();
-}
-
-AMediaFormatWrapper::AMediaFormatWrapper(AMediaFormat *aMediaFormat)
-    : mAMediaFormat(aMediaFormat) {
-}
-
-AMediaFormatWrapper::~AMediaFormatWrapper() {
-    release();
-}
-
-status_t AMediaFormatWrapper::release() {
-    if (mAMediaFormat != NULL) {
-        media_status_t err = AMediaFormat_delete(mAMediaFormat);
-        mAMediaFormat = NULL;
-        return translateErrorCode(err);
-    }
-    return OK;
-}
-
-AMediaFormat *AMediaFormatWrapper::getAMediaFormat() const {
-    return mAMediaFormat;
-}
-
-sp<AMessage> AMediaFormatWrapper::toAMessage() const {
-  sp<AMessage> msg;
-  writeToAMessage(msg);
-  return msg;
-}
-
-void AMediaFormatWrapper::writeToAMessage(sp<AMessage> &msg) const {
-    if (mAMediaFormat == NULL) {
-        msg = NULL;
-    }
-
-    if (msg == NULL) {
-        msg = new AMessage;
-    }
-    for (auto& key : AMediaFormatKeyGroupInt32) {
-        int32_t val;
-        if (getInt32(key, &val)) {
-            msg->setInt32(key, val);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupInt64) {
-        int64_t val;
-        if (getInt64(key, &val)) {
-            msg->setInt64(key, val);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupString) {
-        AString val;
-        if (getString(key, &val)) {
-            msg->setString(key, val);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupBuffer) {
-        void *data;
-        size_t size;
-        if (getBuffer(key, &data, &size)) {
-            sp<ABuffer> buffer = ABuffer::CreateAsCopy(data, size);
-            msg->setBuffer(key, buffer);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupCsd) {
-        void *data;
-        size_t size;
-        if (getBuffer(key, &data, &size)) {
-            sp<ABuffer> buffer = ABuffer::CreateAsCopy(data, size);
-            buffer->meta()->setInt32(AMEDIAFORMAT_KEY_CSD, 1);
-            buffer->meta()->setInt64(AMEDIAFORMAT_KEY_TIME_US, 0);
-            msg->setBuffer(key, buffer);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupRect) {
-        int32_t left, top, right, bottom;
-        if (getRect(key, &left, &top, &right, &bottom)) {
-            msg->setRect(key, left, top, right, bottom);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupFloatInt32) {
-        float valFloat;
-        if (getFloat(key, &valFloat)) {
-            msg->setFloat(key, valFloat);
-        } else {
-            int32_t valInt32;
-            if (getInt32(key, &valInt32)) {
-                msg->setFloat(key, (float)valInt32);
-            }
-        }
-    }
-}
-
-const char* AMediaFormatWrapper::toString() const {
-    if (mAMediaFormat == NULL) {
-        return NULL;
-    }
-    return AMediaFormat_toString(mAMediaFormat);
-}
-
-bool AMediaFormatWrapper::getInt32(const char *name, int32_t *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getInt32(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getInt64(const char *name, int64_t *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getInt64(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getFloat(const char *name, float *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getFloat(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getDouble(const char *name, double *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getDouble(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getSize(const char *name, size_t *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getSize(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getRect(
-        const char *name, int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getRect(mAMediaFormat, name, left, top, right, bottom);
-}
-
-bool AMediaFormatWrapper::getBuffer(const char *name, void** data, size_t *outSize) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getBuffer(mAMediaFormat, name, data, outSize);
-}
-
-bool AMediaFormatWrapper::getString(const char *name, AString *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    const char *outChar = NULL;
-    bool ret = AMediaFormat_getString(mAMediaFormat, name, &outChar);
-    if (ret) {
-        *out = AString(outChar);
-    }
-    return ret;
-}
-
-void AMediaFormatWrapper::setInt32(const char* name, int32_t value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setInt32(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setInt64(const char* name, int64_t value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setInt64(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setFloat(const char* name, float value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setFloat(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setDouble(const char* name, double value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setDouble(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setSize(const char* name, size_t value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setSize(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setRect(
-        const char* name, int32_t left, int32_t top, int32_t right, int32_t bottom) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setRect(mAMediaFormat, name, left, top, right, bottom);
-    }
-}
-
-void AMediaFormatWrapper::setString(const char* name, const AString &value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setString(mAMediaFormat, name, value.c_str());
-    }
-}
-
-void AMediaFormatWrapper::setBuffer(const char* name, void* data, size_t size) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setBuffer(mAMediaFormat, name, data, size);
-    }
-}
-
-
-//////////// ANativeWindowWrapper
-ANativeWindowWrapper::ANativeWindowWrapper(ANativeWindow *aNativeWindow)
-    : mANativeWindow(aNativeWindow) {
-    if (aNativeWindow != NULL) {
-        ANativeWindow_acquire(aNativeWindow);
-    }
-}
-
-ANativeWindowWrapper::~ANativeWindowWrapper() {
-    release();
-}
-
-status_t ANativeWindowWrapper::release() {
-    if (mANativeWindow != NULL) {
-        ANativeWindow_release(mANativeWindow);
-        mANativeWindow = NULL;
-    }
-    return OK;
-}
-
-ANativeWindow *ANativeWindowWrapper::getANativeWindow() const {
-    return mANativeWindow;
-}
-
-
-//////////// AMediaDrmWrapper
-AMediaDrmWrapper::AMediaDrmWrapper(const uint8_t uuid[16]) {
-    mAMediaDrm = AMediaDrm_createByUUID(uuid);
-}
-
-AMediaDrmWrapper::AMediaDrmWrapper(AMediaDrm *aMediaDrm)
-    : mAMediaDrm(aMediaDrm) {
-}
-
-AMediaDrmWrapper::~AMediaDrmWrapper() {
-    release();
-}
-
-status_t AMediaDrmWrapper::release() {
-    if (mAMediaDrm != NULL) {
-        AMediaDrm_release(mAMediaDrm);
-        mAMediaDrm = NULL;
-    }
-    return OK;
-}
-
-AMediaDrm *AMediaDrmWrapper::getAMediaDrm() const {
-    return mAMediaDrm;
-}
-
-// static
-bool AMediaDrmWrapper::isCryptoSchemeSupported(
-        const uint8_t uuid[16],
-        const char *mimeType) {
-    return AMediaDrm_isCryptoSchemeSupported(uuid, mimeType);
-}
-
-
-//////////// AMediaCryptoWrapper
-AMediaCryptoWrapper::AMediaCryptoWrapper(
-        const uint8_t uuid[16], const void *initData, size_t initDataSize) {
-    mAMediaCrypto = AMediaCrypto_new(uuid, initData, initDataSize);
-}
-
-AMediaCryptoWrapper::AMediaCryptoWrapper(AMediaCrypto *aMediaCrypto)
-    : mAMediaCrypto(aMediaCrypto) {
-}
-
-AMediaCryptoWrapper::~AMediaCryptoWrapper() {
-    release();
-}
-
-status_t AMediaCryptoWrapper::release() {
-    if (mAMediaCrypto != NULL) {
-        AMediaCrypto_delete(mAMediaCrypto);
-        mAMediaCrypto = NULL;
-    }
-    return OK;
-}
-
-AMediaCrypto *AMediaCryptoWrapper::getAMediaCrypto() const {
-    return mAMediaCrypto;
-}
-
-bool AMediaCryptoWrapper::isCryptoSchemeSupported(const uint8_t uuid[16]) {
-    if (mAMediaCrypto == NULL) {
-        return false;
-    }
-    return AMediaCrypto_isCryptoSchemeSupported(uuid);
-}
-
-bool AMediaCryptoWrapper::requiresSecureDecoderComponent(const char *mime) {
-    if (mAMediaCrypto == NULL) {
-        return false;
-    }
-    return AMediaCrypto_requiresSecureDecoderComponent(mime);
-}
-
-
-//////////// AMediaCodecCryptoInfoWrapper
-// static
-sp<AMediaCodecCryptoInfoWrapper> AMediaCodecCryptoInfoWrapper::Create(MetaDataBase &meta) {
-
-    uint32_t type;
-    const void *crypteddata;
-    size_t cryptedsize;
-
-    if (!meta.findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
-        return NULL;
-    }
-
-    int numSubSamples = cryptedsize / sizeof(size_t);
-
-    if (numSubSamples <= 0) {
-        ALOGE("Create: INVALID numSubSamples: %d", numSubSamples);
-        return NULL;
-    }
-
-    const void *cleardata;
-    size_t clearsize;
-    if (meta.findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
-        if (clearsize != cryptedsize) {
-            // The two must be of the same length.
-            ALOGE("Create: mismatch cryptedsize: %zu != clearsize: %zu", cryptedsize, clearsize);
-            return NULL;
-        }
-    }
-
-    const void *key;
-    size_t keysize;
-    if (meta.findData(kKeyCryptoKey, &type, &key, &keysize)) {
-        if (keysize != kAESBlockSize) {
-            // Keys must be 16 bytes in length.
-            ALOGE("Create: Keys must be %zu bytes in length: %zu", kAESBlockSize, keysize);
-            return NULL;
-        }
-    }
-
-    const void *iv;
-    size_t ivsize;
-    if (meta.findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
-        if (ivsize != kAESBlockSize) {
-            // IVs must be 16 bytes in length.
-            ALOGE("Create: IV must be %zu bytes in length: %zu", kAESBlockSize, ivsize);
-            return NULL;
-        }
-    }
-
-    int32_t mode;
-    if (!meta.findInt32(kKeyCryptoMode, &mode)) {
-        mode = CryptoPlugin::kMode_AES_CTR;
-    }
-
-    return new AMediaCodecCryptoInfoWrapper(
-            numSubSamples,
-            (uint8_t*) key,
-            (uint8_t*) iv,
-            (CryptoPlugin::Mode)mode,
-            (size_t*) cleardata,
-            (size_t*) crypteddata);
-}
-
-AMediaCodecCryptoInfoWrapper::AMediaCodecCryptoInfoWrapper(
-        int numsubsamples,
-        uint8_t key[16],
-        uint8_t iv[16],
-        CryptoPlugin::Mode mode,
-        size_t *clearbytes,
-        size_t *encryptedbytes) {
-    mAMediaCodecCryptoInfo =
-        AMediaCodecCryptoInfo_new(numsubsamples,
-                                  key,
-                                  iv,
-                                  translateToCryptoInfoMode(mode),
-                                  clearbytes,
-                                  encryptedbytes);
-}
-
-AMediaCodecCryptoInfoWrapper::AMediaCodecCryptoInfoWrapper(
-        AMediaCodecCryptoInfo *aMediaCodecCryptoInfo)
-    : mAMediaCodecCryptoInfo(aMediaCodecCryptoInfo) {
-}
-
-AMediaCodecCryptoInfoWrapper::~AMediaCodecCryptoInfoWrapper() {
-    release();
-}
-
-status_t AMediaCodecCryptoInfoWrapper::release() {
-    if (mAMediaCodecCryptoInfo != NULL) {
-        media_status_t err = AMediaCodecCryptoInfo_delete(mAMediaCodecCryptoInfo);
-        mAMediaCodecCryptoInfo = NULL;
-        return translateErrorCode(err);
-    }
-    return OK;
-}
-
-AMediaCodecCryptoInfo *AMediaCodecCryptoInfoWrapper::getAMediaCodecCryptoInfo() const {
-    return mAMediaCodecCryptoInfo;
-}
-
-void AMediaCodecCryptoInfoWrapper::setPattern(CryptoPlugin::Pattern *pattern) {
-    if (mAMediaCodecCryptoInfo == NULL || pattern == NULL) {
-        return;
-    }
-    cryptoinfo_pattern_t ndkPattern = {(int32_t)pattern->mEncryptBlocks,
-                                       (int32_t)pattern->mSkipBlocks };
-    return AMediaCodecCryptoInfo_setPattern(mAMediaCodecCryptoInfo, &ndkPattern);
-}
-
-size_t AMediaCodecCryptoInfoWrapper::getNumSubSamples() {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return 0;
-    }
-    return AMediaCodecCryptoInfo_getNumSubSamples(mAMediaCodecCryptoInfo);
-}
-
-status_t AMediaCodecCryptoInfoWrapper::getKey(uint8_t *dst) {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return DEAD_OBJECT;
-    }
-    if (dst == NULL) {
-        return BAD_VALUE;
-    }
-    return translateErrorCode(
-        AMediaCodecCryptoInfo_getKey(mAMediaCodecCryptoInfo, dst));
-}
-
-status_t AMediaCodecCryptoInfoWrapper::getIV(uint8_t *dst) {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return DEAD_OBJECT;
-    }
-    if (dst == NULL) {
-        return BAD_VALUE;
-    }
-    return translateErrorCode(
-        AMediaCodecCryptoInfo_getIV(mAMediaCodecCryptoInfo, dst));
-}
-
-CryptoPlugin::Mode AMediaCodecCryptoInfoWrapper::getMode() {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return CryptoPlugin::kMode_Unencrypted;
-    }
-    return translateToCryptoPluginMode(
-        AMediaCodecCryptoInfo_getMode(mAMediaCodecCryptoInfo));
-}
-
-status_t AMediaCodecCryptoInfoWrapper::getClearBytes(size_t *dst) {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return DEAD_OBJECT;
-    }
-    if (dst == NULL) {
-        return BAD_VALUE;
-    }
-    return translateErrorCode(
-        AMediaCodecCryptoInfo_getClearBytes(mAMediaCodecCryptoInfo, dst));
-}
-
-status_t AMediaCodecCryptoInfoWrapper::getEncryptedBytes(size_t *dst) {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return DEAD_OBJECT;
-    }
-    if (dst == NULL) {
-        return BAD_VALUE;
-    }
-    return translateErrorCode(
-        AMediaCodecCryptoInfo_getEncryptedBytes(mAMediaCodecCryptoInfo, dst));
-}
-
-
-//////////// AMediaCodecWrapper
-// static
-sp<AMediaCodecWrapper> AMediaCodecWrapper::CreateCodecByName(const AString &name) {
-    AMediaCodec *aMediaCodec = AMediaCodec_createCodecByName(name.c_str());
-    return new AMediaCodecWrapper(aMediaCodec);
-}
-
-// static
-sp<AMediaCodecWrapper> AMediaCodecWrapper::CreateDecoderByType(const AString &mimeType) {
-    AMediaCodec *aMediaCodec = AMediaCodec_createDecoderByType(mimeType.c_str());
-    return new AMediaCodecWrapper(aMediaCodec);
-}
-
-// static
-void AMediaCodecWrapper::OnInputAvailableCB(
-        AMediaCodec * /* aMediaCodec */,
-        void *userdata,
-        int32_t index) {
-    ALOGV("OnInputAvailableCB: index(%d)", index);
-    sp<AMessage> msg = sp<AMessage>((AMessage *)userdata)->dup();
-    msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
-    msg->setInt32("index", index);
-    msg->post();
-}
-
-// static
-void AMediaCodecWrapper::OnOutputAvailableCB(
-        AMediaCodec * /* aMediaCodec */,
-        void *userdata,
-        int32_t index,
-        AMediaCodecBufferInfo *bufferInfo) {
-    ALOGV("OnOutputAvailableCB: index(%d), (%d, %d, %lld, 0x%x)",
-          index, bufferInfo->offset, bufferInfo->size,
-          (long long)bufferInfo->presentationTimeUs, bufferInfo->flags);
-    sp<AMessage> msg = sp<AMessage>((AMessage *)userdata)->dup();
-    msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
-    msg->setInt32("index", index);
-    msg->setSize("offset", (size_t)(bufferInfo->offset));
-    msg->setSize("size", (size_t)(bufferInfo->size));
-    msg->setInt64("timeUs", bufferInfo->presentationTimeUs);
-    msg->setInt32("flags", (int32_t)(bufferInfo->flags));
-    msg->post();
-}
-
-// static
-void AMediaCodecWrapper::OnFormatChangedCB(
-        AMediaCodec * /* aMediaCodec */,
-        void *userdata,
-        AMediaFormat *format) {
-    sp<AMediaFormatWrapper> formatWrapper = new AMediaFormatWrapper(format);
-    sp<AMessage> outputFormat = formatWrapper->toAMessage();
-    ALOGV("OnFormatChangedCB: format(%s)", outputFormat->debugString().c_str());
-
-    sp<AMessage> msg = sp<AMessage>((AMessage *)userdata)->dup();
-    msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
-    msg->setMessage("format", outputFormat);
-    msg->post();
-}
-
-// static
-void AMediaCodecWrapper::OnErrorCB(
-        AMediaCodec * /* aMediaCodec */,
-        void *userdata,
-        media_status_t err,
-        int32_t actionCode,
-        const char *detail) {
-    ALOGV("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
-    sp<AMessage> msg = sp<AMessage>((AMessage *)userdata)->dup();
-    msg->setInt32("callbackID", CB_ERROR);
-    msg->setInt32("err", translateErrorCode(err));
-    msg->setInt32("actionCode", translateActionCode(actionCode));
-    msg->setString("detail", detail);
-    msg->post();
-}
-
-AMediaCodecWrapper::AMediaCodecWrapper(AMediaCodec *aMediaCodec)
-    : mAMediaCodec(aMediaCodec) {
-}
-
-AMediaCodecWrapper::~AMediaCodecWrapper() {
-    release();
-}
-
-status_t AMediaCodecWrapper::release() {
-    if (mAMediaCodec != NULL) {
-        AMediaCodecOnAsyncNotifyCallback aCB = {};
-        AMediaCodec_setAsyncNotifyCallback(mAMediaCodec, aCB, NULL);
-        mCallback = NULL;
-
-        media_status_t err = AMediaCodec_delete(mAMediaCodec);
-        mAMediaCodec = NULL;
-        return translateErrorCode(err);
-    }
-    return OK;
-}
-
-AMediaCodec *AMediaCodecWrapper::getAMediaCodec() const {
-    return mAMediaCodec;
-}
-
-status_t AMediaCodecWrapper::getName(AString *outComponentName) const {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    char *name = NULL;
-    media_status_t err = AMediaCodec_getName(mAMediaCodec, &name);
-    if (err != AMEDIA_OK) {
-        return translateErrorCode(err);
-    }
-
-    *outComponentName = AString(name);
-    AMediaCodec_releaseName(mAMediaCodec, name);
-    return OK;
-}
-
-status_t AMediaCodecWrapper::configure(
-    const sp<AMediaFormatWrapper> &format,
-    const sp<ANativeWindowWrapper> &nww,
-    const sp<AMediaCryptoWrapper> &crypto,
-    uint32_t flags) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-
-    media_status_t err = AMediaCodec_configure(
-            mAMediaCodec,
-            format->getAMediaFormat(),
-            (nww == NULL ? NULL : nww->getANativeWindow()),
-            crypto == NULL ? NULL : crypto->getAMediaCrypto(),
-            flags);
-
-    return translateErrorCode(err);
-}
-
-status_t AMediaCodecWrapper::setCallback(const sp<AMessage> &callback) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-
-    mCallback = callback;
-
-    AMediaCodecOnAsyncNotifyCallback aCB = {
-        OnInputAvailableCB,
-        OnOutputAvailableCB,
-        OnFormatChangedCB,
-        OnErrorCB
-    };
-
-    return translateErrorCode(
-            AMediaCodec_setAsyncNotifyCallback(mAMediaCodec, aCB, callback.get()));
-}
-
-status_t AMediaCodecWrapper::releaseCrypto() {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaCodec_releaseCrypto(mAMediaCodec));
-}
-
-status_t AMediaCodecWrapper::start() {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaCodec_start(mAMediaCodec));
-}
-
-status_t AMediaCodecWrapper::stop() {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaCodec_stop(mAMediaCodec));
-}
-
-status_t AMediaCodecWrapper::flush() {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaCodec_flush(mAMediaCodec));
-}
-
-uint8_t* AMediaCodecWrapper::getInputBuffer(size_t idx, size_t *out_size) {
-    if (mAMediaCodec == NULL) {
-        return NULL;
-    }
-    return AMediaCodec_getInputBuffer(mAMediaCodec, idx, out_size);
-}
-
-uint8_t* AMediaCodecWrapper::getOutputBuffer(size_t idx, size_t *out_size) {
-    if (mAMediaCodec == NULL) {
-        return NULL;
-    }
-    return AMediaCodec_getOutputBuffer(mAMediaCodec, idx, out_size);
-}
-
-status_t AMediaCodecWrapper::queueInputBuffer(
-        size_t idx,
-        size_t offset,
-        size_t size,
-        uint64_t time,
-        uint32_t flags) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_queueInputBuffer(mAMediaCodec, idx, offset, size, time, flags));
-}
-
-status_t AMediaCodecWrapper::queueSecureInputBuffer(
-        size_t idx,
-        size_t offset,
-        sp<AMediaCodecCryptoInfoWrapper> &codecCryptoInfo,
-        uint64_t time,
-        uint32_t flags) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_queueSecureInputBuffer(
-            mAMediaCodec,
-            idx,
-            offset,
-            codecCryptoInfo->getAMediaCodecCryptoInfo(),
-            time,
-            flags));
-}
-
-sp<AMediaFormatWrapper> AMediaCodecWrapper::getOutputFormat() {
-    if (mAMediaCodec == NULL) {
-        return NULL;
-    }
-    return new AMediaFormatWrapper(AMediaCodec_getOutputFormat(mAMediaCodec));
-}
-
-sp<AMediaFormatWrapper> AMediaCodecWrapper::getInputFormat() {
-    if (mAMediaCodec == NULL) {
-        return NULL;
-    }
-    return new AMediaFormatWrapper(AMediaCodec_getInputFormat(mAMediaCodec));
-}
-
-status_t AMediaCodecWrapper::releaseOutputBuffer(size_t idx, bool render) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_releaseOutputBuffer(mAMediaCodec, idx, render));
-}
-
-status_t AMediaCodecWrapper::setOutputSurface(const sp<ANativeWindowWrapper> &nww) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_setOutputSurface(mAMediaCodec,
-                                     (nww == NULL ? NULL : nww->getANativeWindow())));
-}
-
-status_t AMediaCodecWrapper::releaseOutputBufferAtTime(size_t idx, int64_t timestampNs) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_releaseOutputBufferAtTime(mAMediaCodec, idx, timestampNs));
-}
-
-status_t AMediaCodecWrapper::setParameters(const sp<AMediaFormatWrapper> &params) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_setParameters(mAMediaCodec, params->getAMediaFormat()));
-}
-
-//////////// AMediaExtractorWrapper
-
-AMediaExtractorWrapper::AMediaExtractorWrapper(AMediaExtractor *aMediaExtractor)
-    : mAMediaExtractor(aMediaExtractor) {
-}
-
-AMediaExtractorWrapper::~AMediaExtractorWrapper() {
-    release();
-}
-
-status_t AMediaExtractorWrapper::release() {
-    if (mAMediaExtractor != NULL) {
-        media_status_t err = AMediaExtractor_delete(mAMediaExtractor);
-        mAMediaExtractor = NULL;
-        return translateErrorCode(err);
-    }
-    return OK;
-}
-
-AMediaExtractor *AMediaExtractorWrapper::getAMediaExtractor() const {
-    return mAMediaExtractor;
-}
-
-status_t AMediaExtractorWrapper::setDataSource(int fd, off64_t offset, off64_t length) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_setDataSourceFd(
-            mAMediaExtractor, fd, offset, length));
-}
-
-status_t AMediaExtractorWrapper::setDataSource(const char *location) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_setDataSource(mAMediaExtractor, location));
-}
-
-status_t AMediaExtractorWrapper::setDataSource(AMediaDataSource *source) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_setDataSourceCustom(mAMediaExtractor, source));
-}
-
-size_t AMediaExtractorWrapper::getTrackCount() {
-    if (mAMediaExtractor == NULL) {
-        return 0;
-    }
-    return AMediaExtractor_getTrackCount(mAMediaExtractor);
-}
-
-sp<AMediaFormatWrapper> AMediaExtractorWrapper::getFormat() {
-    if (mAMediaExtractor == NULL) {
-        return NULL;
-    }
-    return new AMediaFormatWrapper(AMediaExtractor_getFileFormat(mAMediaExtractor));
-}
-
-sp<AMediaFormatWrapper> AMediaExtractorWrapper::getTrackFormat(size_t idx) {
-    if (mAMediaExtractor == NULL) {
-        return NULL;
-    }
-    return new AMediaFormatWrapper(AMediaExtractor_getTrackFormat(mAMediaExtractor, idx));
-}
-
-status_t AMediaExtractorWrapper::selectTrack(size_t idx) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_selectTrack(mAMediaExtractor, idx));
-}
-
-status_t AMediaExtractorWrapper::unselectTrack(size_t idx) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_unselectTrack(mAMediaExtractor, idx));
-}
-
-status_t AMediaExtractorWrapper::selectSingleTrack(size_t idx) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    for (size_t i = 0; i < AMediaExtractor_getTrackCount(mAMediaExtractor); ++i) {
-        if (i == idx) {
-            media_status_t err = AMediaExtractor_selectTrack(mAMediaExtractor, i);
-            if (err != AMEDIA_OK) {
-                return translateErrorCode(err);
-            }
-        } else {
-            media_status_t err = AMediaExtractor_unselectTrack(mAMediaExtractor, i);
-            if (err != AMEDIA_OK) {
-                return translateErrorCode(err);
-            }
-        }
-    }
-    return OK;
-}
-
-ssize_t AMediaExtractorWrapper::readSampleData(const sp<ABuffer> &buffer) {
-    if (mAMediaExtractor == NULL) {
-        return -1;
-    }
-    return AMediaExtractor_readSampleData(mAMediaExtractor, buffer->data(), buffer->capacity());
-}
-
-ssize_t AMediaExtractorWrapper::getSampleSize() {
-    if (mAMediaExtractor == NULL) {
-        return 0;
-    }
-    return AMediaExtractor_getSampleSize(mAMediaExtractor);
-}
-
-uint32_t AMediaExtractorWrapper::getSampleFlags() {
-    if (mAMediaExtractor == NULL) {
-        return 0;
-    }
-    return AMediaExtractor_getSampleFlags(mAMediaExtractor);
-}
-
-int AMediaExtractorWrapper::getSampleTrackIndex() {
-    if (mAMediaExtractor == NULL) {
-        return -1;
-    }
-    return AMediaExtractor_getSampleTrackIndex(mAMediaExtractor);
-}
-
-int64_t AMediaExtractorWrapper::getSampleTime() {
-    if (mAMediaExtractor == NULL) {
-        return -1;
-    }
-    return AMediaExtractor_getSampleTime(mAMediaExtractor);
-}
-
-status_t AMediaExtractorWrapper::getSampleFormat(sp<AMediaFormatWrapper> &formatWrapper) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    AMediaFormat *format = AMediaFormat_new();
-    formatWrapper = new AMediaFormatWrapper(format);
-    return translateErrorCode(AMediaExtractor_getSampleFormat(mAMediaExtractor, format));
-}
-
-int64_t AMediaExtractorWrapper::getCachedDuration() {
-    if (mAMediaExtractor == NULL) {
-        return -1;
-    }
-    return AMediaExtractor_getCachedDuration(mAMediaExtractor);
-}
-
-bool AMediaExtractorWrapper::advance() {
-    if (mAMediaExtractor == NULL) {
-        return false;
-    }
-    return AMediaExtractor_advance(mAMediaExtractor);
-}
-
-status_t AMediaExtractorWrapper::seekTo(int64_t seekPosUs, MediaSource::ReadOptions::SeekMode mode) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-
-    SeekMode aMode;
-    switch (mode) {
-        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC: {
-            aMode = AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC;
-            break;
-        }
-        case MediaSource::ReadOptions::SEEK_NEXT_SYNC: {
-            aMode = AMEDIAEXTRACTOR_SEEK_NEXT_SYNC;
-            break;
-        }
-        default: {
-            aMode = AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC;
-            break;
-        }
-    }
-    return AMediaExtractor_seekTo(mAMediaExtractor, seekPosUs, aMode);
-}
-
-PsshInfo* AMediaExtractorWrapper::getPsshInfo() {
-    if (mAMediaExtractor == NULL) {
-        return NULL;
-    }
-    return AMediaExtractor_getPsshInfo(mAMediaExtractor);
-}
-
-sp<AMediaCodecCryptoInfoWrapper> AMediaExtractorWrapper::getSampleCryptoInfo() {
-    if (mAMediaExtractor == NULL) {
-        return NULL;
-    }
-    AMediaCodecCryptoInfo *cryptoInfo = AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor);
-    if (cryptoInfo == NULL) {
-        return NULL;
-    }
-    return new AMediaCodecCryptoInfoWrapper(cryptoInfo);
-}
-
-AMediaDataSourceWrapper::AMediaDataSourceWrapper(const sp<DataSource> &dataSource)
-    : mDataSource(dataSource),
-      mAMediaDataSource(convertDataSourceToAMediaDataSource(dataSource)) {
-}
-
-AMediaDataSourceWrapper::AMediaDataSourceWrapper(AMediaDataSource *aDataSource)
-    : mDataSource(NULL),
-      mAMediaDataSource(aDataSource) {
-}
-
-AMediaDataSourceWrapper::~AMediaDataSourceWrapper() {
-    if (mAMediaDataSource == NULL) {
-        return;
-    }
-    AMediaDataSource_close(mAMediaDataSource);
-    AMediaDataSource_delete(mAMediaDataSource);
-    mAMediaDataSource = NULL;
-}
-
-AMediaDataSource* AMediaDataSourceWrapper::getAMediaDataSource() {
-    return mAMediaDataSource;
-}
-
-void AMediaDataSourceWrapper::close() {
-    AMediaDataSource_close(mAMediaDataSource);
-}
-
-}  // namespace android
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
deleted file mode 100644
index cb8d375..0000000
--- a/media/libmedia/Visualizer.cpp
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
-**
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "Visualizer"
-#include <utils/Log.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <limits.h>
-
-#include <media/Visualizer.h>
-#include <audio_utils/fixedfft.h>
-#include <utils/Thread.h>
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-Visualizer::Visualizer (const String16& opPackageName,
-         int32_t priority,
-         effect_callback_t cbf,
-         void* user,
-         audio_session_t sessionId)
-    :   AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId),
-        mCaptureRate(CAPTURE_RATE_DEF),
-        mCaptureSize(CAPTURE_SIZE_DEF),
-        mSampleRate(44100000),
-        mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED),
-        mMeasurementMode(MEASUREMENT_MODE_NONE),
-        mCaptureCallBack(NULL),
-        mCaptureCbkUser(NULL)
-{
-    initCaptureSize();
-}
-
-Visualizer::~Visualizer()
-{
-    ALOGV("Visualizer::~Visualizer()");
-    setEnabled(false);
-    setCaptureCallBack(NULL, NULL, 0, 0);
-}
-
-void Visualizer::release()
-{
-    ALOGV("Visualizer::release()");
-    setEnabled(false);
-    Mutex::Autolock _l(mCaptureLock);
-
-    mCaptureThread.clear();
-    mCaptureCallBack = NULL;
-    mCaptureCbkUser = NULL;
-    mCaptureFlags = 0;
-    mCaptureRate = 0;
-}
-
-status_t Visualizer::setEnabled(bool enabled)
-{
-    Mutex::Autolock _l(mCaptureLock);
-
-    sp<CaptureThread> t = mCaptureThread;
-    if (t != 0) {
-        if (enabled) {
-            if (t->exitPending()) {
-                if (t->requestExitAndWait() == WOULD_BLOCK) {
-                    ALOGE("Visualizer::enable() called from thread");
-                    return INVALID_OPERATION;
-                }
-            }
-        }
-        t->mLock.lock();
-    }
-
-    status_t status = AudioEffect::setEnabled(enabled);
-
-    if (t != 0) {
-        if (enabled && status == NO_ERROR) {
-            t->run("Visualizer");
-        } else {
-            t->requestExit();
-        }
-    }
-
-    if (t != 0) {
-        t->mLock.unlock();
-    }
-
-    return status;
-}
-
-status_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags,
-        uint32_t rate)
-{
-    if (rate > CAPTURE_RATE_MAX) {
-        return BAD_VALUE;
-    }
-    Mutex::Autolock _l(mCaptureLock);
-
-    if (mEnabled) {
-        return INVALID_OPERATION;
-    }
-
-    if (mCaptureThread != 0) {
-        mCaptureLock.unlock();
-        mCaptureThread->requestExitAndWait();
-        mCaptureLock.lock();
-    }
-
-    mCaptureThread.clear();
-    mCaptureCallBack = cbk;
-    mCaptureCbkUser = user;
-    mCaptureFlags = flags;
-    mCaptureRate = rate;
-
-    if (cbk != NULL) {
-        mCaptureThread = new CaptureThread(this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
-    }
-    ALOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x",
-            rate, mCaptureThread.get(), mCaptureFlags);
-    return NO_ERROR;
-}
-
-status_t Visualizer::setCaptureSize(uint32_t size)
-{
-    if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
-        size < VISUALIZER_CAPTURE_SIZE_MIN ||
-        popcount(size) != 1) {
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock _l(mCaptureLock);
-    if (mEnabled) {
-        return INVALID_OPERATION;
-    }
-
-    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
-    effect_param_t *p = (effect_param_t *)buf32;
-
-    p->psize = sizeof(uint32_t);
-    p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
-    *((int32_t *)p->data + 1)= size;
-    status_t status = setParameter(p);
-
-    ALOGV("setCaptureSize size %d  status %d p->status %d", size, status, p->status);
-
-    if (status == NO_ERROR) {
-        status = p->status;
-        if (status == NO_ERROR) {
-            mCaptureSize = size;
-        }
-    }
-
-    return status;
-}
-
-status_t Visualizer::setScalingMode(uint32_t mode) {
-    if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED)
-            && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) {
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock _l(mCaptureLock);
-
-    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
-    effect_param_t *p = (effect_param_t *)buf32;
-
-    p->psize = sizeof(uint32_t);
-    p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE;
-    *((int32_t *)p->data + 1)= mode;
-    status_t status = setParameter(p);
-
-    ALOGV("setScalingMode mode %d  status %d p->status %d", mode, status, p->status);
-
-    if (status == NO_ERROR) {
-        status = p->status;
-        if (status == NO_ERROR) {
-            mScalingMode = mode;
-        }
-    }
-
-    return status;
-}
-
-status_t Visualizer::setMeasurementMode(uint32_t mode) {
-    if ((mode != MEASUREMENT_MODE_NONE)
-            //Note: needs to be handled as a mask when more measurement modes are added
-            && ((mode & MEASUREMENT_MODE_PEAK_RMS) != mode)) {
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock _l(mCaptureLock);
-
-    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
-    effect_param_t *p = (effect_param_t *)buf32;
-
-    p->psize = sizeof(uint32_t);
-    p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
-    *((int32_t *)p->data + 1)= mode;
-    status_t status = setParameter(p);
-
-    ALOGV("setMeasurementMode mode %d  status %d p->status %d", mode, status, p->status);
-
-    if (status == NO_ERROR) {
-        status = p->status;
-        if (status == NO_ERROR) {
-            mMeasurementMode = mode;
-        }
-    }
-    return status;
-}
-
-status_t Visualizer::getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements) {
-    if (mMeasurementMode == MEASUREMENT_MODE_NONE) {
-        ALOGE("Cannot retrieve int measurements, no measurement mode set");
-        return INVALID_OPERATION;
-    }
-    if (!(mMeasurementMode & type)) {
-        // measurement type has not been set on this Visualizer
-        ALOGE("Cannot retrieve int measurements, requested measurement mode 0x%x not set(0x%x)",
-                type, mMeasurementMode);
-        return INVALID_OPERATION;
-    }
-    // only peak+RMS measurement supported
-    if ((type != MEASUREMENT_MODE_PEAK_RMS)
-            // for peak+RMS measurement, the results are 2 int32_t values
-            || (number != 2)) {
-        ALOGE("Cannot retrieve int measurements, MEASUREMENT_MODE_PEAK_RMS returns 2 ints, not %d",
-                        number);
-        return BAD_VALUE;
-    }
-
-    status_t status = NO_ERROR;
-    if (mEnabled) {
-        uint32_t replySize = number * sizeof(int32_t);
-        status = command(VISUALIZER_CMD_MEASURE,
-                sizeof(uint32_t)  /*cmdSize*/,
-                &type /*cmdData*/,
-                &replySize, measurements);
-        ALOGV("getMeasurements() command returned %d", status);
-        if ((status == NO_ERROR) && (replySize == 0)) {
-            status = NOT_ENOUGH_DATA;
-        }
-    } else {
-        ALOGV("getMeasurements() disabled");
-        return INVALID_OPERATION;
-    }
-    return status;
-}
-
-status_t Visualizer::getWaveForm(uint8_t *waveform)
-{
-    if (waveform == NULL) {
-        return BAD_VALUE;
-    }
-    if (mCaptureSize == 0) {
-        return NO_INIT;
-    }
-
-    status_t status = NO_ERROR;
-    if (mEnabled) {
-        uint32_t replySize = mCaptureSize;
-        status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform);
-        ALOGV("getWaveForm() command returned %d", status);
-        if ((status == NO_ERROR) && (replySize == 0)) {
-            status = NOT_ENOUGH_DATA;
-        }
-    } else {
-        ALOGV("getWaveForm() disabled");
-        memset(waveform, 0x80, mCaptureSize);
-    }
-    return status;
-}
-
-status_t Visualizer::getFft(uint8_t *fft)
-{
-    if (fft == NULL) {
-        return BAD_VALUE;
-    }
-    if (mCaptureSize == 0) {
-        return NO_INIT;
-    }
-
-    status_t status = NO_ERROR;
-    if (mEnabled) {
-        uint8_t buf[mCaptureSize];
-        status = getWaveForm(buf);
-        if (status == NO_ERROR) {
-            status = doFft(fft, buf);
-        }
-    } else {
-        memset(fft, 0, mCaptureSize);
-    }
-    return status;
-}
-
-status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
-{
-    int32_t workspace[mCaptureSize >> 1];
-    int32_t nonzero = 0;
-
-    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
-        workspace[i >> 1] =
-                ((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8);
-        nonzero |= workspace[i >> 1];
-    }
-
-    if (nonzero) {
-        fixed_fft_real(mCaptureSize >> 1, workspace);
-    }
-
-    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
-        short tmp = workspace[i >> 1] >> 21;
-        while (tmp > 127 || tmp < -128) tmp >>= 1;
-        fft[i] = tmp;
-        tmp = workspace[i >> 1];
-        tmp >>= 5;
-        while (tmp > 127 || tmp < -128) tmp >>= 1;
-        fft[i + 1] = tmp;
-    }
-
-    return NO_ERROR;
-}
-
-void Visualizer::periodicCapture()
-{
-    Mutex::Autolock _l(mCaptureLock);
-    ALOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x",
-            this, mCaptureCallBack, mCaptureFlags);
-    if (mCaptureCallBack != NULL &&
-        (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) &&
-        mCaptureSize != 0) {
-        uint8_t waveform[mCaptureSize];
-        status_t status = getWaveForm(waveform);
-        if (status != NO_ERROR) {
-            return;
-        }
-        uint8_t fft[mCaptureSize];
-        if (mCaptureFlags & CAPTURE_FFT) {
-            status = doFft(fft, waveform);
-        }
-        if (status != NO_ERROR) {
-            return;
-        }
-        uint8_t *wavePtr = NULL;
-        uint8_t *fftPtr = NULL;
-        uint32_t waveSize = 0;
-        uint32_t fftSize = 0;
-        if (mCaptureFlags & CAPTURE_WAVEFORM) {
-            wavePtr = waveform;
-            waveSize = mCaptureSize;
-        }
-        if (mCaptureFlags & CAPTURE_FFT) {
-            fftPtr = fft;
-            fftSize = mCaptureSize;
-        }
-        mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate);
-    }
-}
-
-uint32_t Visualizer::initCaptureSize()
-{
-    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
-    effect_param_t *p = (effect_param_t *)buf32;
-
-    p->psize = sizeof(uint32_t);
-    p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
-    status_t status = getParameter(p);
-
-    if (status == NO_ERROR) {
-        status = p->status;
-    }
-
-    uint32_t size = 0;
-    if (status == NO_ERROR) {
-        size = *((int32_t *)p->data + 1);
-    }
-    mCaptureSize = size;
-
-    ALOGV("initCaptureSize size %d status %d", mCaptureSize, status);
-
-    return size;
-}
-
-void Visualizer::controlStatusChanged(bool controlGranted) {
-    if (controlGranted) {
-        // this Visualizer instance regained control of the effect, reset the scaling mode
-        //   and capture size as has been cached through it.
-        ALOGV("controlStatusChanged(true) causes effect parameter reset:");
-        ALOGV("    scaling mode reset to %d", mScalingMode);
-        setScalingMode(mScalingMode);
-        ALOGV("    capture size reset to %d", mCaptureSize);
-        setCaptureSize(mCaptureSize);
-    }
-    AudioEffect::controlStatusChanged(controlGranted);
-}
-
-//-------------------------------------------------------------------------
-
-Visualizer::CaptureThread::CaptureThread(Visualizer* receiver, uint32_t captureRate,
-        bool bCanCallJava)
-    : Thread(bCanCallJava), mReceiver(receiver)
-{
-    mSleepTimeUs = 1000000000 / captureRate;
-    ALOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs);
-}
-
-bool Visualizer::CaptureThread::threadLoop()
-{
-    ALOGV("CaptureThread %p enter", this);
-    sp<Visualizer> receiver = mReceiver.promote();
-    if (receiver == NULL) {
-        return false;
-    }
-    while (!exitPending())
-    {
-        usleep(mSleepTimeUs);
-        receiver->periodicCapture();
-    }
-    ALOGV("CaptureThread %p exiting", this);
-    return false;
-}
-
-} // namespace android
diff --git a/media/libmedia/include/media/DataSourceDesc.h b/media/libmedia/include/media/DataSourceDesc.h
deleted file mode 100644
index 4336767..0000000
--- a/media/libmedia/include/media/DataSourceDesc.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2018 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_DATASOURCEDESC_H
-#define ANDROID_DATASOURCEDESC_H
-
-#include <media/stagefright/foundation/ABase.h>
-#include <utils/RefBase.h>
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
-
-namespace android {
-
-class DataSource;
-struct MediaHTTPService;
-
-// A binder interface for implementing a stagefright DataSource remotely.
-struct DataSourceDesc : public RefBase {
-public:
-    // intentionally less than INT64_MAX
-    // keep consistent with JAVA code
-    static const int64_t kMaxTimeMs = 0x7ffffffffffffffll / 1000;
-    static const int64_t kMaxTimeUs = kMaxTimeMs * 1000;
-
-    enum {
-        /* No data source has been set yet */
-        TYPE_NONE     = 0,
-        /* data source is type of MediaDataSource */
-        TYPE_CALLBACK = 1,
-        /* data source is type of FileDescriptor */
-        TYPE_FD       = 2,
-        /* data source is type of Url */
-        TYPE_URL      = 3,
-    };
-
-    DataSourceDesc();
-
-    int mType;
-
-    sp<MediaHTTPService> mHttpService;
-    String8 mUrl;
-    KeyedVector<String8, String8> mHeaders;
-
-    int mFD;
-    int64_t mFDOffset;
-    int64_t mFDLength;
-
-    sp<DataSource> mCallbackSource;
-
-    int64_t mId;
-    int64_t mStartPositionMs;
-    int64_t mEndPositionMs;
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(DataSourceDesc);
-};
-
-}; // namespace android
-
-#endif // ANDROID_DATASOURCEDESC_H
diff --git a/media/libmedia/include/media/JetPlayer.h b/media/libmedia/include/media/JetPlayer.h
deleted file mode 100644
index bb569bc..0000000
--- a/media/libmedia/include/media/JetPlayer.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2008 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 JETPLAYER_H_
-#define JETPLAYER_H_
-
-#include <utils/threads.h>
-
-#include <libsonivox/jet.h>
-#include <libsonivox/eas_types.h>
-#include <media/AudioTrack.h>
-#include <media/MidiIoWrapper.h>
-
-
-namespace android {
-
-typedef void (*jetevent_callback)(int eventType, int val1, int val2, void *cookie);
-
-class JetPlayer {
-
-public:
-
-    // to keep in sync with the JetPlayer class constants
-    // defined in frameworks/base/media/java/android/media/JetPlayer.java
-    static const int JET_EVENT                   = 1;
-    static const int JET_USERID_UPDATE           = 2;
-    static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3;
-    static const int JET_PAUSE_UPDATE            = 4;
-
-    JetPlayer(void *javaJetPlayer,
-            int maxTracks = 32,
-            int trackBufferSize = 1200);
-    ~JetPlayer();
-    int init();
-    int release();
-
-    int loadFromFile(const char* url);
-    int loadFromFD(const int fd, const long long offset, const long long length);
-    int closeFile();
-    int play();
-    int pause();
-    int queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
-            EAS_U32 muteFlags, EAS_U8 userID);
-    int setMuteFlags(EAS_U32 muteFlags, bool sync);
-    int setMuteFlag(int trackNum, bool muteFlag, bool sync);
-    int triggerClip(int clipId);
-    int clearQueue();
-
-    void setEventCallback(jetevent_callback callback);
-
-    int getMaxTracks() { return mMaxTracks; };
-
-
-private:
-    int                 render();
-    void                fireUpdateOnStatusChange();
-    void                fireEventsFromJetQueue();
-
-    JetPlayer() {} // no default constructor
-    void dump();
-    void dumpJetStatus(S_JET_STATUS* pJetStatus);
-
-    jetevent_callback   mEventCallback;
-
-    void*               mJavaJetPlayerRef;
-    Mutex               mMutex; // mutex to sync the render and playback thread with the JET calls
-    pid_t               mTid;
-    Condition           mCondition;
-    volatile bool       mRender;
-    bool                mPaused;
-
-    EAS_STATE           mState;
-    int*                mMemFailedVar;
-
-    int                 mMaxTracks; // max number of MIDI tracks, usually 32
-    EAS_DATA_HANDLE     mEasData;
-    MidiIoWrapper*      mIoWrapper;
-    EAS_PCM*            mAudioBuffer;// EAS renders the MIDI data into this buffer,
-    sp<AudioTrack>      mAudioTrack; // and we play it in this audio track
-    int                 mTrackBufferSize;
-    S_JET_STATUS        mJetStatus;
-    S_JET_STATUS        mPreviousJetStatus;
-
-    class JetPlayerThread : public Thread {
-    public:
-        JetPlayerThread(JetPlayer *player) : mPlayer(player) {
-        }
-
-    protected:
-        virtual ~JetPlayerThread() {}
-
-    private:
-        JetPlayer *mPlayer;
-
-        bool threadLoop() {
-            int result;
-            result = mPlayer->render();
-            return false;
-        }
-
-        JetPlayerThread(const JetPlayerThread &);
-        JetPlayerThread &operator=(const JetPlayerThread &);
-    };
-
-    sp<JetPlayerThread> mThread;
-
-}; // end class JetPlayer
-
-} // end namespace android
-
-
-
-#endif /*JETPLAYER_H_*/
diff --git a/media/libmedia/include/media/MidiDeviceInfo.h b/media/libmedia/include/media/MidiDeviceInfo.h
deleted file mode 100644
index 5b4a241..0000000
--- a/media/libmedia/include/media/MidiDeviceInfo.h
+++ /dev/null
@@ -1,81 +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_MEDIA_MIDI_DEVICE_INFO_H
-#define ANDROID_MEDIA_MIDI_DEVICE_INFO_H
-
-#include <binder/Parcelable.h>
-#include <binder/PersistableBundle.h>
-#include <utils/String16.h>
-#include <utils/Vector.h>
-
-namespace android {
-namespace media {
-namespace midi {
-
-class MidiDeviceInfo : public Parcelable {
-public:
-    MidiDeviceInfo() = default;
-    virtual ~MidiDeviceInfo() = default;
-    MidiDeviceInfo(const MidiDeviceInfo& midiDeviceInfo) = default;
-
-    status_t writeToParcel(Parcel* parcel) const override;
-    status_t readFromParcel(const Parcel* parcel) override;
-
-    int getType() const { return mType; }
-    int getUid() const { return mId; }
-    bool isPrivate() const { return mIsPrivate; }
-    const Vector<String16>& getInputPortNames() const { return mInputPortNames; }
-    const Vector<String16>&  getOutputPortNames() const { return mOutputPortNames; }
-    String16 getProperty(const char* propertyName);
-
-    // The constants need to be kept in sync with MidiDeviceInfo.java
-    enum {
-        TYPE_USB = 1,
-        TYPE_VIRTUAL = 2,
-        TYPE_BLUETOOTH = 3,
-    };
-    static const char* const PROPERTY_NAME;
-    static const char* const PROPERTY_MANUFACTURER;
-    static const char* const PROPERTY_PRODUCT;
-    static const char* const PROPERTY_VERSION;
-    static const char* const PROPERTY_SERIAL_NUMBER;
-    static const char* const PROPERTY_ALSA_CARD;
-    static const char* const PROPERTY_ALSA_DEVICE;
-
-    friend bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs);
-    friend bool operator!=(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
-        return !(lhs == rhs);
-    }
-
-private:
-    status_t readStringVector(
-            const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength);
-    status_t writeStringVector(Parcel* parcel, const Vector<String16>& vector) const;
-
-    int32_t mType;
-    int32_t mId;
-    Vector<String16> mInputPortNames;
-    Vector<String16> mOutputPortNames;
-    os::PersistableBundle mProperties;
-    bool mIsPrivate;
-};
-
-}  // namespace midi
-}  // namespace media
-}  // namespace android
-
-#endif  // ANDROID_MEDIA_MIDI_DEVICE_INFO_H
diff --git a/media/libmedia/include/media/Visualizer.h b/media/libmedia/include/media/Visualizer.h
deleted file mode 100644
index 8078e36..0000000
--- a/media/libmedia/include/media/Visualizer.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_MEDIA_VISUALIZER_H
-#define ANDROID_MEDIA_VISUALIZER_H
-
-#include <media/AudioEffect.h>
-#include <system/audio_effects/effect_visualizer.h>
-#include <utils/Thread.h>
-
-/**
- * The Visualizer class enables application to retrieve part of the currently playing audio for
- * visualization purpose. It is not an audio recording interface and only returns partial and low
- * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use
- * of the visualizer requires the permission android.permission.RECORD_AUDIO.
- * The audio session ID passed to the constructor indicates which audio content should be
- * visualized:
- * - If the session is 0, the audio output mix is visualized
- * - If the session is not 0, the audio from a particular MediaPlayer or AudioTrack
- *   using this audio session is visualized
- * Two types of representation of audio content can be captured:
- * - Waveform data: consecutive 8-bit (unsigned) mono samples by using the getWaveForm() method
- * - Frequency data: 8-bit magnitude FFT by using the getFft() method
- *
- * The length of the capture can be retrieved or specified by calling respectively
- * getCaptureSize() and setCaptureSize() methods. Note that the size of the FFT
- * is half of the specified capture size but both sides of the spectrum are returned yielding in a
- * number of bytes equal to the capture size. The capture size must be a power of 2 in the range
- * returned by getMinCaptureSize() and getMaxCaptureSize().
- * In addition to the polling capture mode, a callback mode is also available by installing a
- * callback function by use of the setCaptureCallBack() method. The rate at which the callback
- * is called as well as the type of data returned is specified.
- * Before capturing data, the Visualizer must be enabled by calling the setEnabled() method.
- * When data capture is not needed any more, the Visualizer should be disabled.
- */
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class Visualizer: public AudioEffect {
-public:
-
-    enum callback_flags {
-        CAPTURE_WAVEFORM = 0x00000001,  // capture callback returns a PCM wave form
-        CAPTURE_FFT = 0x00000002,       // apture callback returns a frequency representation
-        CAPTURE_CALL_JAVA = 0x00000004  // the callback thread can call java
-    };
-
-
-    /* Constructor.
-     * See AudioEffect constructor for details on parameters.
-     */
-                        Visualizer(const String16& opPackageName,
-                                   int32_t priority = 0,
-                                   effect_callback_t cbf = NULL,
-                                   void* user = NULL,
-                                   audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX);
-
-                        ~Visualizer();
-
-    virtual status_t    setEnabled(bool enabled);
-
-    // maximum capture size in samples
-    static uint32_t getMaxCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MAX; }
-    // minimum capture size in samples
-    static uint32_t getMinCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MIN; }
-    // maximum capture rate in millihertz
-    static uint32_t getMaxCaptureRate() { return CAPTURE_RATE_MAX; }
-
-    // callback used to return periodic PCM or FFT captures to the application. Either one or both
-    // types of data are returned (PCM and FFT) according to flags indicated when installing the
-    // callback. When a type of data is not present, the corresponding size (waveformSize or
-    // fftSize) is 0.
-    typedef void (*capture_cbk_t)(void* user,
-                                    uint32_t waveformSize,
-                                    uint8_t *waveform,
-                                    uint32_t fftSize,
-                                    uint8_t *fft,
-                                    uint32_t samplingrate);
-
-    // install a callback to receive periodic captures. The capture rate is specified in milliHertz
-    // and the capture format is according to flags  (see callback_flags).
-    status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate);
-
-    // set the capture size capture size must be a power of two in the range
-    // [VISUALIZER_CAPTURE_SIZE_MAX. VISUALIZER_CAPTURE_SIZE_MIN]
-    // must be called when the visualizer is not enabled
-    status_t setCaptureSize(uint32_t size);
-    uint32_t getCaptureSize() { return mCaptureSize; }
-
-    // returns the capture rate indicated when installing the callback
-    uint32_t getCaptureRate() { return mCaptureRate; }
-
-    // returns the sampling rate of the audio being captured
-    uint32_t getSamplingRate() { return mSampleRate; }
-
-    // set the way volume affects the captured data
-    // mode must one of VISUALIZER_SCALING_MODE_NORMALIZED,
-    //  VISUALIZER_SCALING_MODE_AS_PLAYED
-    status_t setScalingMode(uint32_t mode);
-    uint32_t getScalingMode() { return mScalingMode; }
-
-    // set which measurements are done on the audio buffers processed by the effect.
-    // valid measurements (mask): MEASUREMENT_MODE_PEAK_RMS
-    status_t setMeasurementMode(uint32_t mode);
-    uint32_t getMeasurementMode() { return mMeasurementMode; }
-
-    // return a set of int32_t measurements
-    status_t getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements);
-
-    // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to
-    // getCaptureSize()
-    status_t getWaveForm(uint8_t *waveform);
-
-    // return a capture in FFT 8 bit signed format. The size of the capture is equal to
-    // getCaptureSize() but the length of the FFT is half of the size (both parts of the spectrum
-    // are returned
-    status_t getFft(uint8_t *fft);
-    void release();
-
-protected:
-    // from IEffectClient
-    virtual void controlStatusChanged(bool controlGranted);
-
-private:
-
-    static const uint32_t CAPTURE_RATE_MAX = 20000;
-    static const uint32_t CAPTURE_RATE_DEF = 10000;
-    static const uint32_t CAPTURE_SIZE_DEF = VISUALIZER_CAPTURE_SIZE_MAX;
-
-    /* internal class to handle the callback */
-    class CaptureThread : public Thread
-    {
-    public:
-        CaptureThread(Visualizer* visualizer, uint32_t captureRate, bool bCanCallJava = false);
-
-    private:
-        friend class Visualizer;
-        virtual bool        threadLoop();
-        wp<Visualizer> mReceiver;
-        Mutex       mLock;
-        uint32_t mSleepTimeUs;
-    };
-
-    status_t doFft(uint8_t *fft, uint8_t *waveform);
-    void periodicCapture();
-    uint32_t initCaptureSize();
-
-    Mutex mCaptureLock;
-    uint32_t mCaptureRate;
-    uint32_t mCaptureSize;
-    uint32_t mSampleRate;
-    uint32_t mScalingMode;
-    uint32_t mMeasurementMode;
-    capture_cbk_t mCaptureCallBack;
-    void *mCaptureCbkUser;
-    sp<CaptureThread> mCaptureThread;
-    uint32_t mCaptureFlags;
-};
-
-
-}; // namespace android
-
-#endif // ANDROID_MEDIA_VISUALIZER_H
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 6709585..5301f5c 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -7,6 +7,7 @@
         "MediaPlayerService.cpp",
         "MediaRecorderClient.cpp",
         "MetadataRetrieverClient.cpp",
+        "StagefrightMetadataRetriever.cpp",
         "StagefrightRecorder.cpp",
         "TestPlayerStub.cpp",
     ],
@@ -21,11 +22,14 @@
         "libcodec2_client",
         "libcrypto",
         "libcutils",
+        "libdatasource",
         "libdl",
+        "libdrmframework",
         "libgui",
         "libhidlbase",
         "liblog",
         "libmedia",
+        "libmedia_codeclist",
         "libmedia_omx",
         "libmediadrm",
         "libmediametrics",
@@ -44,6 +48,7 @@
     ],
 
     static_libs: [
+        "libplayerservice_datasource",
         "libstagefright_nuplayer",
         "libstagefright_rtsp",
         "libstagefright_timedtext",
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 1376ccc..05f7365 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -20,9 +20,9 @@
 #include <utils/Log.h>
 
 #include <cutils/properties.h>
+#include <datasource/FileSource.h>
 #include <media/DataSource.h>
 #include <media/IMediaPlayer.h>
-#include <media/stagefright/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <utils/Errors.h>
 #include <utils/misc.h>
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index dfd3933..46c130f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -48,6 +48,7 @@
 #include <utils/Vector.h>
 
 #include <codec2/hidl/client.h>
+#include <datasource/HTTPBase.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IRemoteDisplay.h>
 #include <media/IRemoteDisplayClient.h>
@@ -61,6 +62,7 @@
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooperRoster.h>
 #include <media/stagefright/SurfaceUtils.h>
@@ -80,7 +82,6 @@
 #include "TestPlayerStub.h"
 #include "nuplayer/NuPlayerDriver.h"
 
-#include "HTTPBase.h"
 
 static const int kDumpLockRetries = 50;
 static const int kDumpLockSleepUs = 20000;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 49688ce..2562b8f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -26,10 +26,12 @@
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
+#include <media/AudioSystem.h>
 #include <media/MediaPlayerInterface.h>
 #include <media/Metadata.h>
 #include <media/stagefright/foundation/ABase.h>
 
+
 #include <system/audio.h>
 
 namespace android {
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 40b17bf..4dbab0a 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -37,6 +37,7 @@
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 #include <private/media/VideoFrame.h>
 #include "MetadataRetrieverClient.h"
 #include "StagefrightMetadataRetriever.h"
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
similarity index 98%
rename from media/libstagefright/StagefrightMetadataRetriever.cpp
rename to media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index fa3d372..1aae241 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -22,14 +22,14 @@
 #include <utils/Log.h>
 #include <cutils/properties.h>
 
-#include "include/FrameDecoder.h"
-#include "include/StagefrightMetadataRetriever.h"
+#include "StagefrightMetadataRetriever.h"
+#include "FrameDecoder.h"
 
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
 #include <media/IMediaHTTPService.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
@@ -63,7 +63,8 @@
     ALOGV("setDataSource(%s)", uri);
 
     clearMetadata();
-    mSource = DataSourceFactory::CreateFromURI(httpService, uri, headers);
+    mSource = PlayerServiceDataSourceFactory::getInstance()->CreateFromURI(
+            httpService, uri, headers);
 
     if (mSource == NULL) {
         ALOGE("Unable to create data source for '%s'.", uri);
@@ -91,7 +92,7 @@
     ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
 
     clearMetadata();
-    mSource = new FileSource(fd, offset, length);
+    mSource = new PlayerServiceFileSource(fd, offset, length);
 
     status_t err;
     if ((err = mSource->initCheck()) != OK) {
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libmediaplayerservice/StagefrightMetadataRetriever.h
similarity index 100%
rename from media/libstagefright/include/StagefrightMetadataRetriever.h
rename to media/libmediaplayerservice/StagefrightMetadataRetriever.h
diff --git a/media/libmediaplayerservice/datasource/Android.bp b/media/libmediaplayerservice/datasource/Android.bp
new file mode 100644
index 0000000..71fa50b
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/Android.bp
@@ -0,0 +1,43 @@
+cc_library_static {
+    name: "libplayerservice_datasource",
+
+    srcs: [
+        "PlayerServiceDataSourceFactory.cpp",
+        "PlayerServiceFileSource.cpp",
+        "PlayerServiceMediaHTTP.cpp",
+    ],
+
+    header_libs: [
+        "media_ndk_headers",
+        "libmedia_headers",
+    ],
+
+    shared_libs: [
+        "libdatasource",
+        "libdrmframework",
+        "liblog",
+        "libutils",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp b/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp
new file mode 100644
index 0000000..ef946e9
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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 "PlayerServuceDataSourceFactory"
+
+
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
+#include <datasource/PlayerServiceMediaHTTP.h>
+#include <media/MediaHTTPConnection.h>
+#include <media/MediaHTTPService.h>
+
+namespace android {
+
+// static
+sp<PlayerServiceDataSourceFactory> PlayerServiceDataSourceFactory::sInstance;
+// static
+Mutex PlayerServiceDataSourceFactory::sInstanceLock;
+
+// static
+sp<PlayerServiceDataSourceFactory> PlayerServiceDataSourceFactory::getInstance() {
+    Mutex::Autolock l(sInstanceLock);
+    if (!sInstance) {
+        sInstance = new PlayerServiceDataSourceFactory();
+    }
+    return sInstance;
+}
+
+sp<DataSource> PlayerServiceDataSourceFactory::CreateMediaHTTP(
+        const sp<MediaHTTPService> &httpService) {
+    if (httpService == NULL) {
+        return NULL;
+    }
+
+    sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
+    if (conn == NULL) {
+        ALOGE("Failed to make http connection from http service!");
+        return NULL;
+    } else {
+        return new PlayerServiceMediaHTTP(conn);
+    }
+}
+
+sp<DataSource> PlayerServiceDataSourceFactory::CreateFileSource(const char *uri) {
+    return new PlayerServiceFileSource(uri);
+}
+
+}  // namespace android
diff --git a/media/libstagefright/FileSource.cpp b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
similarity index 84%
rename from media/libstagefright/FileSource.cpp
rename to media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
index aee7fd8..1580891 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
@@ -15,18 +15,17 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "FileSource"
+#define LOG_TAG "PlayerServiceFileSource"
 #include <utils/Log.h>
 
+#include <datasource/PlayerServiceFileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/FileSource.h>
-#include <media/stagefright/Utils.h>
 #include <private/android_filesystem_config.h>
 
 namespace android {
 
-FileSource::FileSource(const char *filename)
-    : ClearFileSource(filename),
+PlayerServiceFileSource::PlayerServiceFileSource(const char *filename)
+    : FileSource(filename),
       mDecryptHandle(NULL),
       mDrmManagerClient(NULL),
       mDrmBufOffset(0),
@@ -34,8 +33,8 @@
       mDrmBuf(NULL){
 }
 
-FileSource::FileSource(int fd, int64_t offset, int64_t length)
-    : ClearFileSource(fd, offset, length),
+PlayerServiceFileSource::PlayerServiceFileSource(int fd, int64_t offset, int64_t length)
+    : FileSource(fd, offset, length),
       mDecryptHandle(NULL),
       mDrmManagerClient(NULL),
       mDrmBufOffset(0),
@@ -43,7 +42,7 @@
       mDrmBuf(NULL) {
 }
 
-FileSource::~FileSource() {
+PlayerServiceFileSource::~PlayerServiceFileSource() {
     if (mDrmBuf != NULL) {
         delete[] mDrmBuf;
         mDrmBuf = NULL;
@@ -62,7 +61,7 @@
     }
 }
 
-ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
+ssize_t PlayerServiceFileSource::readAt(off64_t offset, void *data, size_t size) {
     if (mFd < 0) {
         return NO_INIT;
     }
@@ -87,7 +86,7 @@
     }
 }
 
-sp<DecryptHandle> FileSource::DrmInitialization(const char *mime) {
+sp<DecryptHandle> PlayerServiceFileSource::DrmInitialization(const char *mime) {
     if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor
     if (mDrmManagerClient == NULL) {
         mDrmManagerClient = new DrmManagerClient();
@@ -110,7 +109,7 @@
     return mDecryptHandle;
 }
 
-ssize_t FileSource::readAtDRM_l(off64_t offset, void *data, size_t size) {
+ssize_t PlayerServiceFileSource::readAtDRM_l(off64_t offset, void *data, size_t size) {
     size_t DRM_CACHE_SIZE = 1024;
     if (mDrmBuf == NULL) {
         mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
@@ -141,7 +140,7 @@
 }
 
 /* static */
-bool FileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) {
+bool PlayerServiceFileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) {
     std::unique_ptr<DrmManagerClient> drmClient(new DrmManagerClient());
     sp<DecryptHandle> decryptHandle =
             drmClient->openDecryptSession(fd, offset, length, mime);
diff --git a/media/libstagefright/http/MediaHTTP.cpp b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
similarity index 78%
rename from media/libstagefright/http/MediaHTTP.cpp
rename to media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
index 0fba3dc..0124720 100644
--- a/media/libstagefright/http/MediaHTTP.cpp
+++ b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
@@ -15,32 +15,32 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "MediaHTTP"
+#define LOG_TAG "PlayerServiceMediaHTTP"
 #include <utils/Log.h>
 
-#include <media/stagefright/MediaHTTP.h>
+#include <datasource/PlayerServiceMediaHTTP.h>
 
 #include <binder/IServiceManager.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <media/MediaHTTPConnection.h>
 
 namespace android {
 
-MediaHTTP::MediaHTTP(const sp<MediaHTTPConnection> &conn)
-    : ClearMediaHTTP(conn),
+PlayerServiceMediaHTTP::PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn)
+    : MediaHTTP(conn),
       mDrmManagerClient(NULL) {
 }
 
-MediaHTTP::~MediaHTTP() {
+PlayerServiceMediaHTTP::~PlayerServiceMediaHTTP() {
     clearDRMState_l();
 }
 
 // DRM...
 
-sp<DecryptHandle> MediaHTTP::DrmInitialization(const char* mime) {
+sp<DecryptHandle> PlayerServiceMediaHTTP::DrmInitialization(const char* mime) {
     if (mDrmManagerClient == NULL) {
         mDrmManagerClient = new DrmManagerClient();
     }
@@ -62,7 +62,7 @@
     return mDecryptHandle;
 }
 
-void MediaHTTP::clearDRMState_l() {
+void PlayerServiceMediaHTTP::clearDRMState_l() {
     if (mDecryptHandle != NULL) {
         // To release mDecryptHandle
         CHECK(mDrmManagerClient);
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h
new file mode 100644
index 0000000..7d58c5c
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h
@@ -0,0 +1,48 @@
+/*
+ * 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 PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_
+
+#define PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_
+
+#include <datasource/DataSourceFactory.h>
+#include <media/DataSource.h>
+#include <sys/types.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct MediaHTTPService;
+class String8;
+struct HTTPBase;
+
+class PlayerServiceDataSourceFactory : public DataSourceFactory {
+public:
+    static sp<PlayerServiceDataSourceFactory> getInstance();
+    virtual sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
+
+protected:
+    virtual sp<DataSource> CreateFileSource(const char *uri);
+
+private:
+    static sp<PlayerServiceDataSourceFactory> sInstance;
+    static Mutex sInstanceLock;
+    PlayerServiceDataSourceFactory() {};
+};
+
+}  // namespace android
+
+#endif  // PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_
diff --git a/media/libstagefright/include/media/stagefright/FileSource.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
similarity index 65%
rename from media/libstagefright/include/media/stagefright/FileSource.h
rename to media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
index b610eef..08a013e 100644
--- a/media/libstagefright/include/media/stagefright/FileSource.h
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
@@ -14,24 +14,26 @@
  * limitations under the License.
  */
 
-#ifndef FILE_SOURCE_H_
+#ifndef PLAYER_SERVICE_FILE_SOURCE_H_
 
-#define FILE_SOURCE_H_
+#define PLAYER_SERVICE_FILE_SOURCE_H_
 
 #include <stdio.h>
 
-#include <media/stagefright/ClearFileSource.h>
+#include <datasource/FileSource.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/threads.h>
 #include <drm/DrmManagerClient.h>
 
 namespace android {
 
-class FileSource : public ClearFileSource {
+// FileSource implementation which works on MediaPlayerService.
+// Supports OMA(forword-lock) files.
+class PlayerServiceFileSource : public FileSource {
 public:
-    FileSource(const char *filename);
-    // FileSource takes ownership and will close the fd
-    FileSource(int fd, int64_t offset, int64_t length);
+    PlayerServiceFileSource(const char *filename);
+    // PlayerServiceFileSource takes ownership and will close the fd
+    PlayerServiceFileSource(int fd, int64_t offset, int64_t length);
 
     virtual ssize_t readAt(off64_t offset, void *data, size_t size);
 
@@ -40,7 +42,7 @@
     static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime);
 
 protected:
-    virtual ~FileSource();
+    virtual ~PlayerServiceFileSource();
 
 private:
     /*for DRM*/
@@ -52,11 +54,11 @@
 
     ssize_t readAtDRM_l(off64_t offset, void *data, size_t size);
 
-    FileSource(const FileSource &);
-    FileSource &operator=(const FileSource &);
+    PlayerServiceFileSource(const PlayerServiceFileSource &);
+    PlayerServiceFileSource &operator=(const PlayerServiceFileSource &);
 };
 
 }  // namespace android
 
-#endif  // FILE_SOURCE_H_
+#endif  // PLAYER_SERVICE_FILE_SOURCE_H_
 
diff --git a/media/libstagefright/include/media/stagefright/MediaHTTP.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
similarity index 67%
rename from media/libstagefright/include/media/stagefright/MediaHTTP.h
rename to media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
index acaa6c4..0032cd7 100644
--- a/media/libstagefright/include/media/stagefright/MediaHTTP.h
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
@@ -14,22 +14,24 @@
  * limitations under the License.
  */
 
-#ifndef MEDIA_HTTP_H_
+#ifndef PLAYER_SERVICE_MEDIA_HTTP_H_
 
-#define MEDIA_HTTP_H_
+#define PLAYER_SERVICE_MEDIA_HTTP_H_
 
+#include <datasource/MediaHTTP.h>
 #include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/ClearMediaHTTP.h>
 
 namespace android {
 
 struct MediaHTTPConnection;
 
-struct MediaHTTP : public ClearMediaHTTP {
-    MediaHTTP(const sp<MediaHTTPConnection> &conn);
+// MediaHTTP implementation which works on MediaPlayerService.
+// Supports OMA(forword-lock) stream.
+struct PlayerServiceMediaHTTP : public MediaHTTP {
+    PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn);
 
 protected:
-    virtual ~MediaHTTP();
+    virtual ~PlayerServiceMediaHTTP();
 
     virtual sp<DecryptHandle> DrmInitialization(const char* mime);
 
@@ -39,9 +41,9 @@
 
     void clearDRMState_l();
 
-    DISALLOW_EVIL_CONSTRUCTORS(MediaHTTP);
+    DISALLOW_EVIL_CONSTRUCTORS(PlayerServiceMediaHTTP);
 };
 
 }  // namespace android
 
-#endif  // MEDIA_HTTP_H_
+#endif  // PLAYER_SERVICE_MEDIA_HTTP_H_
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index 0ad4d04..436cb31 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -27,7 +27,6 @@
 
 #include <media/mediaplayer.h>
 #include <media/AudioResamplerPublic.h>
-#include <media/AudioSystem.h>
 #include <media/AudioTimestamp.h>
 #include <media/AVSyncSettings.h>
 #include <media/BufferingSettings.h>
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index 23a19e7..c8f48a2 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -18,6 +18,7 @@
     ],
 
     header_libs: [
+        "libmediadrm_headers",
         "media_plugin_headers",
     ],
 
@@ -45,6 +46,7 @@
 
     shared_libs: [
         "libbinder",
+        "libdatasource",
         "libui",
         "libgui",
         "libmedia",
@@ -52,6 +54,10 @@
         "libpowermanager",
     ],
 
+    static_libs: [
+        "libplayerservice_datasource",
+    ],
+
     name: "libstagefright_nuplayer",
 
     sanitize: {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 4653711..00e3443 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -23,6 +23,10 @@
 #include "AnotherPacketSource.h"
 #include <binder/IServiceManager.h>
 #include <cutils/properties.h>
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
+#include <datasource/HTTPBase.h>
+#include <datasource/NuCachedSource2.h>
 #include <media/DataSource.h>
 #include <media/MediaBufferHolder.h>
 #include <media/MediaSource.h>
@@ -31,8 +35,6 @@
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/FileSource.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaClock.h>
@@ -41,8 +43,6 @@
 #include <media/stagefright/MediaExtractorFactory.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
-#include "../../libstagefright/include/NuCachedSource2.h"
-#include "../../libstagefright/include/HTTPBase.h"
 
 namespace android {
 
@@ -385,7 +385,8 @@
             if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
                 sp<DataSource> httpSource;
                 mDisconnectLock.unlock();
-                httpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
+                httpSource = PlayerServiceDataSourceFactory::getInstance()
+                        ->CreateMediaHTTP(mHTTPService);
                 if (httpSource == NULL) {
                     ALOGE("Failed to create http source!");
                     notifyPreparedAndCleanup(UNKNOWN_ERROR);
@@ -401,9 +402,9 @@
             mLock.unlock();
             mDisconnectLock.unlock();
             // This might take long time if connection has some issue.
-            sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
-                   mHTTPService, uri, &mUriHeaders, &contentType,
-                   static_cast<HTTPBase *>(mHttpSource.get()));
+            sp<DataSource> dataSource = PlayerServiceDataSourceFactory::getInstance()
+                    ->CreateFromURI(mHTTPService, uri, &mUriHeaders, &contentType,
+                            static_cast<HTTPBase *>(mHttpSource.get()));
             mDisconnectLock.lock();
             mLock.lock();
             if (!mDisconnected) {
@@ -411,7 +412,8 @@
             }
         } else {
             if (property_get_bool("media.stagefright.extractremote", true) &&
-                    !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
+                    !PlayerServiceFileSource::requiresDrm(
+                            mFd, mOffset, mLength, nullptr /* mime */)) {
                 sp<IBinder> binder =
                         defaultServiceManager()->getService(String16("media.extractor"));
                 if (binder != nullptr) {
@@ -438,7 +440,7 @@
             }
             if (mDataSource == nullptr) {
                 ALOGD("FileSource local");
-                mDataSource = new FileSource(mFd, mOffset, mLength);
+                mDataSource = new PlayerServiceFileSource(mFd, mOffset, mLength);
             }
             // TODO: close should always be done on mFd, see the lines following
             // CreateDataSourceFromIDataSource above,
@@ -782,7 +784,7 @@
         return;
     }
 
-    int64_t nextSubTimeUs;
+    int64_t nextSubTimeUs = 0;
     readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
 
     sp<ABuffer> buffer;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 9f5be06..0e58ec2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -19,7 +19,7 @@
 #define NU_PLAYER_H_
 
 #include <media/AudioResamplerPublic.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/foundation/AHandler.h>
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 2f0da2d..bd2b884 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -28,7 +28,7 @@
 #include "NuPlayerSource.h"
 
 #include <cutils/properties.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaBufferHolder.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index 0997e7d..793014e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -24,7 +24,7 @@
 #include "NuPlayerRenderer.h"
 #include "NuPlayerSource.h"
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 865cb2a..95c973a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -33,6 +33,7 @@
 #include <media/stagefright/MediaClock.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <media/IMediaAnalyticsService.h>
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
index 50f69ff..4360656 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
@@ -18,8 +18,8 @@
 #define NUPLAYER_DRM_H_
 
 #include <binder/Parcel.h>
-#include <media/ICrypto.h>
-#include <media/IDrm.h>
+#include <mediadrm/ICrypto.h>
+#include <mediadrm/IDrm.h>
 #include <media/stagefright/MetaData.h> // for CryptInfo
 
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 9f5ef78..f137c52 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -20,7 +20,7 @@
 
 #include "NuPlayer.h"
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/mediaplayer.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MetaData.h>
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3d67c91..d198d39 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -4505,22 +4505,38 @@
 status_t ACodec::configureImageGrid(
         const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
     int32_t tileWidth, tileHeight, gridRows, gridCols;
-    if (!msg->findInt32("tile-width", &tileWidth) ||
-        !msg->findInt32("tile-height", &tileHeight) ||
-        !msg->findInt32("grid-rows", &gridRows) ||
-        !msg->findInt32("grid-cols", &gridCols)) {
+    OMX_BOOL useGrid = OMX_FALSE;
+    if (msg->findInt32("tile-width", &tileWidth) &&
+        msg->findInt32("tile-height", &tileHeight) &&
+        msg->findInt32("grid-rows", &gridRows) &&
+        msg->findInt32("grid-cols", &gridCols)) {
+        useGrid = OMX_TRUE;
+    } else {
+        // when bEnabled is false, the tile info is not used,
+        // but clear out these too.
+        tileWidth = tileHeight = gridRows = gridCols = 0;
+    }
+
+    if (!mIsImage && !useGrid) {
         return OK;
     }
 
     OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE gridType;
     InitOMXParams(&gridType);
     gridType.nPortIndex = kPortIndexOutput;
-    gridType.bEnabled = OMX_TRUE;
+    gridType.bEnabled = useGrid;
     gridType.nTileWidth = tileWidth;
     gridType.nTileHeight = tileHeight;
     gridType.nGridRows = gridRows;
     gridType.nGridCols = gridCols;
 
+    ALOGV("sending image grid info to component: bEnabled %d, tile %dx%d, grid %dx%d",
+            gridType.bEnabled,
+            gridType.nTileWidth,
+            gridType.nTileHeight,
+            gridType.nGridRows,
+            gridType.nGridCols);
+
     status_t err = mOMXNode->setParameter(
             (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid,
             &gridType, sizeof(gridType));
@@ -4541,6 +4557,13 @@
             (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid,
             &gridType, sizeof(gridType));
 
+    ALOGV("received image grid info from component: bEnabled %d, tile %dx%d, grid %dx%d",
+            gridType.bEnabled,
+            gridType.nTileWidth,
+            gridType.nTileHeight,
+            gridType.nGridRows,
+            gridType.nGridCols);
+
     if (err == OK && gridType.bEnabled) {
         outputFormat->setInt32("tile-width", gridType.nTileWidth);
         outputFormat->setInt32("tile-height", gridType.nTileHeight);
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index bb7f2a5..59cc24b 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -19,8 +19,10 @@
         ],
         cfi: true,
     },
-
-    shared_libs: ["libmedia"],
+    shared_libs: [
+        "libstagefright_foundation",
+        "libutils"
+    ],
 }
 
 cc_library_static {
@@ -58,10 +60,14 @@
         "-Wall",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
     shared_libs: [
         "libgui",
         "liblog",
-        "libmedia_omx",
+        "libmedia_codeclist",
         "libstagefright_foundation",
         "libui",
         "libutils",
@@ -121,7 +127,6 @@
         "ACodecBufferChannel.cpp",
         "AHierarchicalStateMachine.cpp",
         "AMRWriter.cpp",
-        "AudioPlayer.cpp",
         "AudioSource.cpp",
         "BufferImpl.cpp",
         "CallbackDataSource.cpp",
@@ -129,13 +134,7 @@
         "CameraSource.cpp",
         "CameraSourceTimeLapse.cpp",
         "DataConverter.cpp",
-        "DataSourceBase.cpp",
-        "DataSourceFactory.cpp",
-        "DataURISource.cpp",
-        "ClearFileSource.cpp",
-        "FileSource.cpp",
         "FrameDecoder.cpp",
-        "HTTPBase.cpp",
         "HevcUtils.cpp",
         "InterfaceUtils.cpp",
         "JPEGSource.cpp",
@@ -152,10 +151,7 @@
         "MediaSource.cpp",
         "MediaSync.cpp",
         "MediaTrack.cpp",
-        "http/ClearMediaHTTP.cpp",
-        "http/MediaHTTP.cpp",
         "MediaMuxer.cpp",
-        "NuCachedSource2.cpp",
         "NuMediaExtractor.cpp",
         "OggWriter.cpp",
         "OMXClient.cpp",
@@ -165,11 +161,10 @@
         "SimpleDecodingSource.cpp",
         "SkipCutBuffer.cpp",
         "StagefrightMediaScanner.cpp",
-        "StagefrightMetadataRetriever.cpp",
         "StagefrightPluginLoader.cpp",
         "SurfaceUtils.cpp",
-        "Utils.cpp",
         "ThrottledSource.cpp",
+        "Utils.cpp",
         "VideoFrameSchedulerBase.cpp",
         "VideoFrameScheduler.cpp",
     ],
@@ -180,12 +175,13 @@
         "libbinder",
         "libcamera_client",
         "libcutils",
+        "libdatasource",
         "libdl",
         "libdl_android",
-        "libdrmframework",
         "libgui",
         "liblog",
         "libmedia",
+        "libmedia_codeclist",
         "libmedia_omx",
         "libmedia_omx_client",
         "libaudioclient",
@@ -207,6 +203,7 @@
     ],
 
     static_libs: [
+        "libstagefright_esds",
         "libstagefright_color_conversion",
         "libyuv_static",
         "libstagefright_mediafilter",
@@ -214,12 +211,11 @@
         "libstagefright_timedtext",
         "libogg",
         "libwebm",
-        "libstagefright_esds",
         "libstagefright_id3",
-        "libFLAC",
     ],
 
     header_libs:[
+        "libmediadrm_headers",
         "libnativeloader-headers",
         "libstagefright_xmlparser_headers",
         "media_ndk_headers",
@@ -260,4 +256,3 @@
         ],
     },
 }
-
diff --git a/media/libstagefright/BufferImpl.cpp b/media/libstagefright/BufferImpl.cpp
index b760273..f73b625 100644
--- a/media/libstagefright/BufferImpl.cpp
+++ b/media/libstagefright/BufferImpl.cpp
@@ -21,7 +21,7 @@
 #include <binder/IMemory.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <utils/NativeHandle.h>
 
 #include "include/SecureBuffer.h"
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
index d0610b2..97f38f8 100644
--- a/media/libstagefright/CodecBase.cpp
+++ b/media/libstagefright/CodecBase.cpp
@@ -18,7 +18,7 @@
 #define LOG_TAG "CodecBase"
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/stagefright/CodecBase.h>
 #include <utils/Log.h>
 
diff --git a/media/libstagefright/DataSourceBase.cpp b/media/libstagefright/DataSourceBase.cpp
deleted file mode 100644
index 8f47ee5..0000000
--- a/media/libstagefright/DataSourceBase.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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 "DataSourceBase"
-
-#include <media/DataSourceBase.h>
-#include <media/stagefright/foundation/ByteUtils.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/String8.h>
-
-namespace android {
-
-bool DataSourceBase::getUInt16(off64_t offset, uint16_t *x) {
-    *x = 0;
-
-    uint8_t byte[2];
-    if (readAt(offset, byte, 2) != 2) {
-        return false;
-    }
-
-    *x = (byte[0] << 8) | byte[1];
-
-    return true;
-}
-
-bool DataSourceBase::getUInt24(off64_t offset, uint32_t *x) {
-    *x = 0;
-
-    uint8_t byte[3];
-    if (readAt(offset, byte, 3) != 3) {
-        return false;
-    }
-
-    *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];
-
-    return true;
-}
-
-bool DataSourceBase::getUInt32(off64_t offset, uint32_t *x) {
-    *x = 0;
-
-    uint32_t tmp;
-    if (readAt(offset, &tmp, 4) != 4) {
-        return false;
-    }
-
-    *x = ntohl(tmp);
-
-    return true;
-}
-
-bool DataSourceBase::getUInt64(off64_t offset, uint64_t *x) {
-    *x = 0;
-
-    uint64_t tmp;
-    if (readAt(offset, &tmp, 8) != 8) {
-        return false;
-    }
-
-    *x = ntoh64(tmp);
-
-    return true;
-}
-
-bool DataSourceBase::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 DataSourceBase::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 DataSourceBase::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 DataSourceBase::getSize(off64_t *size) {
-    *size = 0;
-
-    return ERROR_UNSUPPORTED;
-}
-
-bool DataSourceBase::getUri(char *uriString __unused, size_t bufferSize __unused) {
-    return false;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index cebce3a..08f690b 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -22,7 +22,7 @@
 #include <binder/MemoryHeapBase.h>
 #include <gui/Surface.h>
 #include <inttypes.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaSource.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/avc_utils.h>
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 2f13dc9..f130c9b 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1635,8 +1635,13 @@
         return BAD_VALUE;
     }
 
+    // Increase moovExtraSize once only irrespective of how many times
+    // setCaptureRate is called.
+    bool containsCaptureFps = mMetaKeys->contains(kMetaKey_CaptureFps);
     mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
-    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
+    if (!containsCaptureFps) {
+        mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
+    }
 
     return OK;
 }
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index f579e9d..161c178 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -35,7 +35,7 @@
 #include <cutils/properties.h>
 #include <gui/BufferQueue.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IOMX.h>
 #include <media/IResourceManagerService.h>
 #include <media/MediaCodecBuffer.h>
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index dd7c3e6..b027a97 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -22,7 +22,7 @@
 
 #include <cutils/properties.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaCodecList.h>
 #include <media/MediaCodecInfo.h>
 #include <media/MediaResourcePolicy.h>
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 50e454c..7243b82 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -22,7 +22,7 @@
 
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaBufferHolder.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/MediaSource.h>
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index 9ba2add..7ebdb1a 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -96,10 +96,18 @@
 
     sp<MediaAdapter> newTrack = new MediaAdapter(trackMeta);
     status_t result = mWriter->addSource(newTrack);
-    if (result == OK) {
-        return mTrackList.add(newTrack);
+    if (result != OK) {
+        return -1;
     }
-    return -1;
+    float captureFps = -1.0;
+    if (format->findAsFloat("time-lapse-fps", &captureFps)) {
+        ALOGV("addTrack() time-lapse-fps: %f", captureFps);
+        result = mWriter->setCaptureRate(captureFps);
+        if (result != OK) {
+            ALOGW("addTrack() setCaptureRate failed :%d", result);
+        }
+    }
+    return mTrackList.add(newTrack);
 }
 
 status_t MediaMuxer::setOrientationHint(int degrees) {
diff --git a/media/libstagefright/NdkUtils.cpp b/media/libstagefright/NdkUtils.cpp
deleted file mode 100644
index 904fe72..0000000
--- a/media/libstagefright/NdkUtils.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2018 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
-
-#include <media/stagefright/NdkUtils.h>
-#include <media/stagefright/Utils.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-namespace android {
-
-sp<MetaData> convertMediaFormatWrapperToMetaData(const sp<AMediaFormatWrapper> &fmt) {
-    sp<AMessage> msg = fmt->toAMessage();
-    sp<MetaData> meta = new MetaData;
-    convertMessageToMetaData(msg, meta);
-    return meta;
-}
-
-}  // namespace android
-
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 680d426..66fb4b0 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -22,13 +22,13 @@
 
 #include "include/ESDS.h"
 
+#include <datasource/DataSourceFactory.h>
+#include <datasource/FileSource.h>
 #include <media/DataSource.h>
 #include <media/MediaSource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
@@ -36,6 +36,7 @@
 #include <media/stagefright/MediaExtractorFactory.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 namespace android {
 
@@ -81,7 +82,7 @@
     }
 
     sp<DataSource> dataSource =
-        DataSourceFactory::CreateFromURI(httpService, path, headers);
+        DataSourceFactory::getInstance()->CreateFromURI(httpService, path, headers);
 
     if (dataSource == NULL) {
         return -ENOENT;
diff --git a/media/libstagefright/SimpleDecodingSource.cpp b/media/libstagefright/SimpleDecodingSource.cpp
index babdc7a..b809848 100644
--- a/media/libstagefright/SimpleDecodingSource.cpp
+++ b/media/libstagefright/SimpleDecodingSource.cpp
@@ -20,7 +20,7 @@
 
 #include <gui/Surface.h>
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/foundation/ALooper.h>
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 135151f..bda6053 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1895,22 +1895,6 @@
 #endif
 }
 
-AString MakeUserAgent() {
-    AString ua;
-    ua.append("stagefright/1.2 (Linux;Android ");
-
-#if (PROPERTY_VALUE_MAX < 8)
-#error "PROPERTY_VALUE_MAX must be at least 8"
-#endif
-
-    char value[PROPERTY_VALUE_MAX];
-    property_get("ro.build.version.release", value, "Unknown");
-    ua.append(value);
-    ua.append(")");
-
-    return ua;
-}
-
 status_t sendMetaDataToHal(sp<MediaPlayerBase::AudioSink>& sink,
                            const sp<MetaData>& meta)
 {
@@ -2099,39 +2083,6 @@
     return AudioSystem::isOffloadSupported(info);
 }
 
-AString uriDebugString(const AString &uri, bool incognito) {
-    if (incognito) {
-        return AString("<URI suppressed>");
-    }
-
-    if (property_get_bool("media.stagefright.log-uri", false)) {
-        return uri;
-    }
-
-    // find scheme
-    AString scheme;
-    const char *chars = uri.c_str();
-    for (size_t i = 0; i < uri.size(); i++) {
-        const char c = chars[i];
-        if (!isascii(c)) {
-            break;
-        } else if (isalpha(c)) {
-            continue;
-        } else if (i == 0) {
-            // first character must be a letter
-            break;
-        } else if (isdigit(c) || c == '+' || c == '.' || c =='-') {
-            continue;
-        } else if (c != ':') {
-            break;
-        }
-        scheme = AString(uri, 0, i);
-        scheme.append("://<suppressed>");
-        return scheme;
-    }
-    return AString("<no-scheme URI suppressed>");
-}
-
 HLSTime::HLSTime(const sp<AMessage>& meta) :
     mSeq(-1),
     mTimeUs(-1LL),
@@ -2230,36 +2181,4 @@
     }
 }
 
-AString nameForFd(int fd) {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    AString result;
-    snprintf(buffer, SIZE, "/proc/%d/fd/%d", getpid(), fd);
-    struct stat s;
-    if (lstat(buffer, &s) == 0) {
-        if ((s.st_mode & S_IFMT) == S_IFLNK) {
-            char linkto[256];
-            int len = readlink(buffer, linkto, sizeof(linkto));
-            if(len > 0) {
-                if(len > 255) {
-                    linkto[252] = '.';
-                    linkto[253] = '.';
-                    linkto[254] = '.';
-                    linkto[255] = 0;
-                } else {
-                    linkto[len] = 0;
-                }
-                result.append(linkto);
-            }
-        } else {
-            result.append("unexpected type for ");
-            result.append(buffer);
-        }
-    } else {
-        result.append("couldn't open ");
-        result.append(buffer);
-    }
-    return result;
-}
-
 }  // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
index f18f789..679b091 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
@@ -1355,6 +1355,14 @@
             int tmpHeight = (tmpDisplayHeight + 15) & -16;
             int tmpWidth = (tmpDisplayWidth + 15) & -16;
 
+            if (tmpWidth > video->width)
+            {
+                // while allowed by the spec, this decoder does not actually
+                // support an increase in size.
+                ALOGE("width increase not supported");
+                status = PV_FAIL;
+                goto return_point;
+            }
             if (tmpHeight * tmpWidth > video->size)
             {
                 // This is just possibly "b/37079296".
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index b1f62c7..88f30c4 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -23,6 +23,10 @@
         "-Wall",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
     shared_libs: [
         "libgui",
         "libmedia",
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index 533cd72..b95f054 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -65,6 +65,7 @@
         "AudioPresentationInfo.cpp",
         "ByteUtils.cpp",
         "ColorUtils.cpp",
+        "FoundationUtils.cpp",
         "MediaBuffer.cpp",
         "MediaBufferBase.cpp",
         "MediaBufferGroup.cpp",
diff --git a/media/libstagefright/foundation/FoundationUtils.cpp b/media/libstagefright/foundation/FoundationUtils.cpp
new file mode 100644
index 0000000..8285e4c
--- /dev/null
+++ b/media/libstagefright/foundation/FoundationUtils.cpp
@@ -0,0 +1,112 @@
+/*
+ * 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 "FoundationUtils"
+#include <utils/Log.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <cutils/properties.h>
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+AString uriDebugString(const AString &uri, bool incognito) {
+    if (incognito) {
+        return AString("<URI suppressed>");
+    }
+
+    if (property_get_bool("media.stagefright.log-uri", false)) {
+        return uri;
+    }
+
+    // find scheme
+    AString scheme;
+    const char *chars = uri.c_str();
+    for (size_t i = 0; i < uri.size(); i++) {
+        const char c = chars[i];
+        if (!isascii(c)) {
+            break;
+        } else if (isalpha(c)) {
+            continue;
+        } else if (i == 0) {
+            // first character must be a letter
+            break;
+        } else if (isdigit(c) || c == '+' || c == '.' || c =='-') {
+            continue;
+        } else if (c != ':') {
+            break;
+        }
+        scheme = AString(uri, 0, i);
+        scheme.append("://<suppressed>");
+        return scheme;
+    }
+    return AString("<no-scheme URI suppressed>");
+}
+
+AString MakeUserAgent() {
+    AString ua;
+    ua.append("stagefright/1.2 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.build.version.release", value, "Unknown");
+    ua.append(value);
+    ua.append(")");
+
+    return ua;
+}
+
+AString nameForFd(int fd) {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    AString result;
+    snprintf(buffer, SIZE, "/proc/%d/fd/%d", getpid(), fd);
+    struct stat s;
+    if (lstat(buffer, &s) == 0) {
+        if ((s.st_mode & S_IFMT) == S_IFLNK) {
+            char linkto[256];
+            int len = readlink(buffer, linkto, sizeof(linkto));
+            if(len > 0) {
+                if(len > 255) {
+                    linkto[252] = '.';
+                    linkto[253] = '.';
+                    linkto[254] = '.';
+                    linkto[255] = 0;
+                } else {
+                    linkto[len] = 0;
+                }
+                result.append(linkto);
+            }
+        } else {
+            result.append("unexpected type for ");
+            result.append(buffer);
+        }
+    } else {
+        result.append("couldn't open ");
+        result.append(buffer);
+    }
+    return result;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/httplive/Android.bp b/media/libstagefright/httplive/Android.bp
index c0ee14e..12e7ca6 100644
--- a/media/libstagefright/httplive/Android.bp
+++ b/media/libstagefright/httplive/Android.bp
@@ -31,6 +31,7 @@
         "liblog",
         "libcrypto",
         "libcutils",
+        "libdatasource",
         "libmedia",
         "libmediandk",
         "libstagefright",
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index c7e92cd..68f1de9 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -21,13 +21,13 @@
 #include "HTTPDownloader.h"
 #include "M3UParser.h"
 
+#include <datasource/MediaHTTP.h>
+#include <datasource/FileSource.h>
 #include <media/DataSource.h>
 #include <media/MediaHTTPConnection.h>
 #include <media/MediaHTTPService.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/ClearMediaHTTP.h>
-#include <media/stagefright/ClearFileSource.h>
 #include <openssl/aes.h>
 #include <openssl/md5.h>
 #include <utils/Mutex.h>
@@ -38,7 +38,7 @@
 HTTPDownloader::HTTPDownloader(
         const sp<MediaHTTPService> &httpService,
         const KeyedVector<String8, String8> &headers) :
-    mHTTPDataSource(new ClearMediaHTTP(httpService->makeHTTPConnection())),
+    mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())),
     mExtraHeaders(headers),
     mDisconnecting(false) {
 }
@@ -91,7 +91,7 @@
 
     if (reconnect) {
         if (!strncasecmp(url, "file://", 7)) {
-            mDataSource = new ClearFileSource(url + 7);
+            mDataSource = new FileSource(url + 7);
         } else if (strncasecmp(url, "http://", 7)
                 && strncasecmp(url, "https://", 8)) {
             return ERROR_UNSUPPORTED;
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 9cf97c7..3bad015 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -34,6 +34,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <utils/Mutex.h>
 
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index cb97a3c..e0324e3 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -27,6 +27,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 #include <media/mediaplayer.h>
 
 namespace android {
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 635ecfe..4d0848a 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -28,17 +28,18 @@
 #include "mpeg2ts/AnotherPacketSource.h"
 #include "mpeg2ts/HlsSampleDecryptor.h"
 
+#include <datasource/DataURISource.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 #include <media/stagefright/foundation/MediaKeys.h>
 #include <media/stagefright/foundation/avc_utils.h>
-#include <media/stagefright/DataURISource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MetaDataUtils.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <ctype.h>
 #include <inttypes.h>
diff --git a/media/libstagefright/id3/Android.bp b/media/libstagefright/id3/Android.bp
index 7151d07..c8173cf 100644
--- a/media/libstagefright/id3/Android.bp
+++ b/media/libstagefright/id3/Android.bp
@@ -4,6 +4,7 @@
     srcs: ["ID3.cpp"],
 
     header_libs: [
+        "libmedia_headers",
         "media_ndk_headers",
     ],
 
@@ -33,6 +34,7 @@
     ],
 
     shared_libs: [
+        "libdatasource",
         "libstagefright",
         "libutils",
         "liblog",
diff --git a/media/libstagefright/id3/testid3.cpp b/media/libstagefright/id3/testid3.cpp
index 86e6adf..9984d85 100644
--- a/media/libstagefright/id3/testid3.cpp
+++ b/media/libstagefright/id3/testid3.cpp
@@ -22,7 +22,7 @@
 #include <dirent.h>
 
 #include <binder/ProcessState.h>
-#include <media/stagefright/FileSource.h>
+#include <datasource/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 
 #define MAXPATHLEN 256
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index 7c01e45..3a087d1 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -25,7 +25,7 @@
 
 #include <media/openmax/OMX_Types.h>
 #include <media/stagefright/CodecBase.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IOMX.h>
 
 namespace android {
diff --git a/media/libstagefright/include/SecureBuffer.h b/media/libstagefright/include/SecureBuffer.h
index cf7933a..c45e0e5 100644
--- a/media/libstagefright/include/SecureBuffer.h
+++ b/media/libstagefright/include/SecureBuffer.h
@@ -18,7 +18,7 @@
 
 #define SECURE_BUFFER_H_
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 
 namespace android {
diff --git a/media/libstagefright/include/media/stagefright/DataSourceBase.h b/media/libstagefright/include/media/stagefright/DataSourceBase.h
index af5b83d..c607c91 100644
--- a/media/libstagefright/include/media/stagefright/DataSourceBase.h
+++ b/media/libstagefright/include/media/stagefright/DataSourceBase.h
@@ -18,6 +18,8 @@
 
 #define DATA_SOURCE_BASE_H_
 
+#include <media/stagefright/foundation/ByteUtils.h>
+#include <media/stagefright/MediaErrors.h>
 #include <sys/types.h>
 #include <utils/Errors.h>
 
@@ -45,20 +47,106 @@
     virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0;
 
     // Convenience methods:
-    bool getUInt16(off64_t offset, uint16_t *x);
-    bool getUInt24(off64_t offset, uint32_t *x); // 3 byte int, returned as a 32-bit int
-    bool getUInt32(off64_t offset, uint32_t *x);
-    bool getUInt64(off64_t offset, uint64_t *x);
+    bool getUInt16(off64_t offset, uint16_t *x) {
+        *x = 0;
+
+        uint8_t byte[2];
+        if (readAt(offset, byte, 2) != 2) {
+            return false;
+        }
+
+        *x = (byte[0] << 8) | byte[1];
+
+        return true;
+    }
+    // 3 byte int, returned as a 32-bit int
+    bool getUInt24(off64_t offset, uint32_t *x) {
+        *x = 0;
+
+        uint8_t byte[3];
+        if (readAt(offset, byte, 3) != 3) {
+            return false;
+        }
+
+        *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];
+
+        return true;
+    }
+    bool getUInt32(off64_t offset, uint32_t *x) {
+        *x = 0;
+
+        uint32_t tmp;
+        if (readAt(offset, &tmp, 4) != 4) {
+            return false;
+        }
+
+        *x = ntohl(tmp);
+
+        return true;
+    }
+    bool getUInt64(off64_t offset, uint64_t *x) {
+        *x = 0;
+
+        uint64_t tmp;
+        if (readAt(offset, &tmp, 8) != 8) {
+            return false;
+        }
+
+        *x = ntoh64(tmp);
+
+        return true;
+    }
 
     // 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);
+    bool 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 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 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;
+    }
 
     // May return ERROR_UNSUPPORTED.
-    virtual status_t getSize(off64_t *size);
+    virtual status_t getSize(off64_t *size) {
+        *size = 0;
+        return ERROR_UNSUPPORTED;
+    }
 
-    virtual bool getUri(char *uriString, size_t bufferSize);
+    virtual bool getUri(char * /*uriString*/, size_t /*bufferSize*/) {
+        return false;
+    }
 
     virtual uint32_t flags() {
         return 0;
diff --git a/media/libstagefright/include/media/stagefright/NdkUtils.h b/media/libstagefright/include/media/stagefright/FoundationUtils.h
similarity index 66%
rename from media/libstagefright/include/media/stagefright/NdkUtils.h
rename to media/libstagefright/include/media/stagefright/FoundationUtils.h
index a68884a..1548981 100644
--- a/media/libstagefright/include/media/stagefright/NdkUtils.h
+++ b/media/libstagefright/include/media/stagefright/FoundationUtils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,18 +14,19 @@
  * limitations under the License.
  */
 
-#ifndef NDK_UTILS_H_
+#ifndef FOUNDATION_UTILS_H_
 
-#define NDK_UTILS_H_
+#define FOUNDATION_UTILS_H_
 
-#include <media/stagefright/MetaData.h>
-#include <media/NdkWrapper.h>
+#include <media/stagefright/foundation/AString.h>
 
 namespace android {
 
-sp<MetaData> convertMediaFormatWrapperToMetaData(
-        const sp<AMediaFormatWrapper> &fmt);
+AString MakeUserAgent();
 
+AString uriDebugString(const AString &uri, bool incognito = false);
+
+AString nameForFd(int fd);
 }  // namespace android
 
-#endif  // NDK_UTILS_H_
+#endif  // FOUNDATION_UTILS_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaWriter.h b/media/libstagefright/include/media/stagefright/MediaWriter.h
index 2c12a87..972ae1d 100644
--- a/media/libstagefright/include/media/stagefright/MediaWriter.h
+++ b/media/libstagefright/include/media/stagefright/MediaWriter.h
@@ -35,6 +35,10 @@
     virtual status_t start(MetaData *params = NULL) = 0;
     virtual status_t stop() = 0;
     virtual status_t pause() = 0;
+    virtual status_t setCaptureRate(float /* captureFps */) {
+        ALOGW("setCaptureRate unsupported");
+        return ERROR_UNSUPPORTED;
+    }
 
     virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; }
     virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; }
diff --git a/media/libstagefright/include/media/stagefright/Utils.h b/media/libstagefright/include/media/stagefright/Utils.h
index e8e0a11..2b9b759 100644
--- a/media/libstagefright/include/media/stagefright/Utils.h
+++ b/media/libstagefright/include/media/stagefright/Utils.h
@@ -41,8 +41,6 @@
 // TODO: combine this with avc_utils::getNextNALUnit
 const uint8_t *findNextNalStartCode(const uint8_t *data, size_t length);
 
-AString MakeUserAgent();
-
 // Convert a MIME type to a AudioSystem::audio_format
 status_t mapMimeToAudioFormat(audio_format_t& format, const char* mime);
 
@@ -60,8 +58,6 @@
 bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo,
                       bool isStreaming, audio_stream_type_t streamType);
 
-AString uriDebugString(const AString &uri, bool incognito = false);
-
 struct HLSTime {
     int32_t mSeq;
     int64_t mTimeUs;
@@ -85,7 +81,6 @@
 void writeToAMessage(const sp<AMessage> &msg, const BufferingSettings &buffering);
 void readFromAMessage(const sp<AMessage> &msg, BufferingSettings *buffering /* nonnull */);
 
-AString nameForFd(int fd);
 }  // namespace android
 
 #endif  // UTILS_H_
diff --git a/media/libstagefright/omx/tests/Android.bp b/media/libstagefright/omx/tests/Android.bp
index 569fa88..eb01543 100644
--- a/media/libstagefright/omx/tests/Android.bp
+++ b/media/libstagefright/omx/tests/Android.bp
@@ -7,6 +7,7 @@
     shared_libs: [
         "libstagefright",
         "libbinder",
+        "libdatasource",
         "libmedia",
         "libmedia_omx",
         "libutils",
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index cc8c234..6848a83 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -27,13 +27,13 @@
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 #include <cutils/properties.h>
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
 #include <media/IMediaHTTPService.h>
 #include <media/MediaSource.h>
 #include <media/OMXBuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDefs.h>
@@ -278,7 +278,7 @@
 
 static sp<IMediaExtractor> CreateExtractorFromURI(const char *uri) {
     sp<DataSource> source =
-        DataSourceFactory::CreateFromURI(NULL /* httpService */, uri);
+        DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, uri);
 
     if (source == NULL) {
         return NULL;
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 789e62a..cac1af9 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -21,12 +21,14 @@
 #include "ARTSPConnection.h"
 #include "NetworkUtils.h"
 
+#include <datasource/HTTPBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/base64.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <arpa/inet.h>
 #include <fcntl.h>
@@ -34,7 +36,6 @@
 #include <openssl/md5.h>
 #include <sys/socket.h>
 
-#include "include/HTTPBase.h"
 
 namespace android {
 
diff --git a/media/libstagefright/rtsp/Android.bp b/media/libstagefright/rtsp/Android.bp
index 9bc9c89..a5a895e 100644
--- a/media/libstagefright/rtsp/Android.bp
+++ b/media/libstagefright/rtsp/Android.bp
@@ -21,6 +21,7 @@
 
     shared_libs: [
         "libcrypto",
+        "libdatasource",
         "libmedia",
     ],
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 48bc8ce..9c30623 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -36,18 +36,19 @@
 #include <ctype.h>
 #include <cutils/properties.h>
 
+#include <datasource/HTTPBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <arpa/inet.h>
 #include <sys/socket.h>
 #include <netdb.h>
 
-#include "HTTPBase.h"
 
 #if LOG_NDEBUG
 #define UNUSED_UNLESS_VERBOSE(x) (void)(x)
diff --git a/media/libstagefright/rtsp/SDPLoader.cpp b/media/libstagefright/rtsp/SDPLoader.cpp
index 665d51a..e236267 100644
--- a/media/libstagefright/rtsp/SDPLoader.cpp
+++ b/media/libstagefright/rtsp/SDPLoader.cpp
@@ -22,12 +22,13 @@
 
 #include "ASessionDescription.h"
 
+#include <datasource/MediaHTTP.h>
 #include <media/MediaHTTPConnection.h>
 #include <media/MediaHTTPService.h>
-#include <media/stagefright/ClearMediaHTTP.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #define DEFAULT_SDP_SIZE 100000
 
@@ -41,7 +42,7 @@
       mFlags(flags),
       mNetLooper(new ALooper),
       mCancelled(false),
-      mHTTPDataSource(new ClearMediaHTTP(httpService->makeHTTPConnection())) {
+      mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())) {
     mNetLooper->setName("sdp net");
     mNetLooper->start(false /* runOnCallingThread */,
                       false /* canCallJava */,
diff --git a/media/libstagefright/webm/Android.bp b/media/libstagefright/webm/Android.bp
index 64ecc2d..2cebe8f 100644
--- a/media/libstagefright/webm/Android.bp
+++ b/media/libstagefright/webm/Android.bp
@@ -27,12 +27,14 @@
     include_dirs: ["frameworks/av/include"],
 
     shared_libs: [
+        "libdatasource",
         "libstagefright_foundation",
         "libutils",
         "liblog",
     ],
 
     header_libs: [
+        "libmedia_headers",
         "media_ndk_headers",
     ],
 }
diff --git a/media/libstagefright/webm/WebmFrameThread.h b/media/libstagefright/webm/WebmFrameThread.h
index 1ddaf9a..2dde20a 100644
--- a/media/libstagefright/webm/WebmFrameThread.h
+++ b/media/libstagefright/webm/WebmFrameThread.h
@@ -20,8 +20,8 @@
 #include "WebmFrame.h"
 #include "LinkedBlockingQueue.h"
 
+#include <datasource/FileSource.h>
 #include <media/MediaSource.h>
-#include <media/stagefright/FileSource.h>
 
 #include <utils/List.h>
 #include <utils/Errors.h>
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index 9783e9b..d905b8d 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -1269,7 +1269,7 @@
 void MediaCodecsXmlParser::Impl::State::addDetail(
         const std::string &key, const std::string &value) {
     CHECK(inType());
-    ALOGI("limit: %s = %s", key.c_str(), value.c_str());
+    ALOGV("limit: %s = %s", key.c_str(), value.c_str());
     const StringSet &variants = mVariantsStack.back();
     if (variants.empty()) {
         type()[key] = value;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index ca8cb78..a291939 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -42,6 +42,7 @@
 #include "MtpServer.h"
 #include "MtpStorage.h"
 #include "MtpStringBuffer.h"
+#include "android-base/strings.h"
 
 namespace android {
 
@@ -955,6 +956,11 @@
     if (!mData.getString(modified)) return MTP_RESPONSE_INVALID_PARAMETER;     // date modified
     // keywords follow
 
+    int type = storage->getType();
+    if (type == MTP_STORAGE_REMOVABLE_RAM) {
+        std::string str = android::base::Trim((const char*)name);
+        name.set(str.c_str());
+    }
     ALOGV("name: %s format: 0x%04X (%s)\n", (const char*)name, format,
           MtpDebug::getFormatCodeName(format));
     time_t modifiedTime;
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 78c8df5..aac6d71 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -54,7 +54,6 @@
     ],
 
     include_dirs: [
-        "bionic/libc/private",
         "frameworks/base/core/jni",
         "frameworks/native/include/media/openmax",
         "system/media/camera/include",
@@ -70,16 +69,21 @@
         "libgrallocusage",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
     shared_libs: [
         "android.hardware.graphics.bufferqueue@1.0",
         "android.hidl.token@1.0-utils",
         "libandroid_runtime_lazy",
         "libbase",
         "libbinder",
+        "libdatasource",
         "libmedia",
+        "libmediadrm",
         "libmedia_omx",
         "libmedia_jni_utils",
-        "libmediadrm",
         "libstagefright",
         "libstagefright_foundation",
         "liblog",
@@ -145,6 +149,10 @@
         "-Wall",
     ],
 
+    header_libs: [
+        "libmedia_headers",
+    ],
+
     shared_libs: [
     ],
 
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 1883f63..1145b7b 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -35,6 +35,7 @@
         int64_t timestamp, int32_t width, int32_t height, int32_t numPlanes) :
         mReader(reader), mFormat(format), mUsage(usage), mBuffer(buffer), mLockedBuffer(nullptr),
         mTimestamp(timestamp), mWidth(width), mHeight(height), mNumPlanes(numPlanes) {
+    LOG_FATAL_IF(reader == nullptr, "AImageReader shouldn't be null while creating AImage");
 }
 
 AImage::~AImage() {
@@ -57,14 +58,9 @@
     if (mIsClosed) {
         return;
     }
-    sp<AImageReader> reader = mReader.promote();
-    if (reader != nullptr) {
-        reader->releaseImageLocked(this, releaseFenceFd);
-    } else if (mBuffer != nullptr) {
-        LOG_ALWAYS_FATAL("%s: parent AImageReader closed without releasing image %p",
-                __FUNCTION__, this);
+    if (!mReader->mIsClosed) {
+        mReader->releaseImageLocked(this, releaseFenceFd);
     }
-
     // Should have been set to nullptr in releaseImageLocked
     // Set to nullptr here for extra safety only
     mBuffer = nullptr;
@@ -83,22 +79,12 @@
 
 void
 AImage::lockReader() const {
-    sp<AImageReader> reader = mReader.promote();
-    if (reader == nullptr) {
-        // Reader has been closed
-        return;
-    }
-    reader->mLock.lock();
+    mReader->mLock.lock();
 }
 
 void
 AImage::unlockReader() const {
-    sp<AImageReader> reader = mReader.promote();
-    if (reader == nullptr) {
-        // Reader has been closed
-        return;
-    }
-    reader->mLock.unlock();
+    mReader->mLock.unlock();
 }
 
 media_status_t
diff --git a/media/ndk/NdkImagePriv.h b/media/ndk/NdkImagePriv.h
index e0f16da..0e8cbcb 100644
--- a/media/ndk/NdkImagePriv.h
+++ b/media/ndk/NdkImagePriv.h
@@ -72,7 +72,7 @@
     uint32_t getJpegSize() const;
 
     // When reader is close, AImage will only accept close API call
-    wp<AImageReader>           mReader;
+    const sp<AImageReader>     mReader;
     const int32_t              mFormat;
     const uint64_t             mUsage;  // AHARDWAREBUFFER_USAGE_* flags.
     BufferItem*                mBuffer;
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index baa4fc7..c0ceb3d 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -113,12 +113,12 @@
 
 void
 AImageReader::FrameListener::onFrameAvailable(const BufferItem& /*item*/) {
-    Mutex::Autolock _l(mLock);
     sp<AImageReader> reader = mReader.promote();
     if (reader == nullptr) {
         ALOGW("A frame is available after AImageReader closed!");
         return; // reader has been closed
     }
+    Mutex::Autolock _l(mLock);
     if (mListener.onImageAvailable == nullptr) {
         return; // No callback registered
     }
@@ -143,12 +143,12 @@
 
 void
 AImageReader::BufferRemovedListener::onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) {
-    Mutex::Autolock _l(mLock);
     sp<AImageReader> reader = mReader.promote();
     if (reader == nullptr) {
         ALOGW("A frame is available after AImageReader closed!");
         return; // reader has been closed
     }
+    Mutex::Autolock _l(mLock);
     if (mListener.onBufferRemoved == nullptr) {
         return; // No callback registered
     }
@@ -272,6 +272,11 @@
       mFrameListener(new FrameListener(this)),
       mBufferRemovedListener(new BufferRemovedListener(this)) {}
 
+AImageReader::~AImageReader() {
+    Mutex::Autolock _l(mLock);
+    LOG_FATAL_IF("AImageReader not closed before destruction", mIsClosed != true);
+}
+
 media_status_t
 AImageReader::init() {
     PublicFormat publicFormat = static_cast<PublicFormat>(mFormat);
@@ -347,8 +352,12 @@
     return AMEDIA_OK;
 }
 
-AImageReader::~AImageReader() {
+void AImageReader::close() {
     Mutex::Autolock _l(mLock);
+    if (mIsClosed) {
+        return;
+    }
+    mIsClosed = true;
     AImageReader_ImageListener nullListener = {nullptr, nullptr};
     setImageListenerLocked(&nullListener);
 
@@ -741,6 +750,7 @@
 void AImageReader_delete(AImageReader* reader) {
     ALOGV("%s", __FUNCTION__);
     if (reader != nullptr) {
+        reader->close();
         reader->decStrong((void*) AImageReader_delete);
     }
     return;
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index e328cb1..0779a71 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -76,6 +76,7 @@
     int32_t        getHeight()    const { return mHeight; };
     int32_t        getFormat()    const { return mFormat; };
     int32_t        getMaxImages() const { return mMaxImages; };
+    void           close();
 
   private:
 
@@ -134,7 +135,7 @@
 
       private:
         AImageReader_ImageListener mListener = {nullptr, nullptr};
-        wp<AImageReader>           mReader;
+        const wp<AImageReader>     mReader;
         Mutex                      mLock;
     };
     sp<FrameListener> mFrameListener;
@@ -149,7 +150,7 @@
 
        private:
         AImageReader_BufferRemovedListener mListener = {nullptr, nullptr};
-        wp<AImageReader>           mReader;
+        const wp<AImageReader>     mReader;
         Mutex                      mLock;
     };
     sp<BufferRemovedListener> mBufferRemovedListener;
@@ -165,6 +166,7 @@
     native_handle_t*           mWindowHandle = nullptr;
 
     List<AImage*>              mAcquiredImages;
+    bool                       mIsClosed = false;
 
     Mutex                      mLock;
 };
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index c23f19b..51b516a 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -244,8 +244,8 @@
                          ALOGE("CB_ERROR: err is expected.");
                          break;
                      }
-                     if (!msg->findInt32("action", &actionCode)) {
-                         ALOGE("CB_ERROR: action is expected.");
+                     if (!msg->findInt32("actionCode", &actionCode)) {
+                         ALOGE("CB_ERROR: actionCode is expected.");
                          break;
                      }
                      msg->findString("detail", &detail);
diff --git a/media/ndk/NdkMediaCrypto.cpp b/media/ndk/NdkMediaCrypto.cpp
index ce2c660..792fc00 100644
--- a/media/ndk/NdkMediaCrypto.cpp
+++ b/media/ndk/NdkMediaCrypto.cpp
@@ -27,8 +27,8 @@
 #include <utils/Log.h>
 #include <utils/StrongPointer.h>
 #include <binder/IServiceManager.h>
-#include <media/ICrypto.h>
-#include <media/IMediaDrmService.h>
+#include <mediadrm/ICrypto.h>
+#include <mediadrm/IMediaDrmService.h>
 #include <android_util_Binder.h>
 
 #include <jni.h>
diff --git a/media/ndk/NdkMediaCryptoPriv.h b/media/ndk/NdkMediaCryptoPriv.h
index 14ea928..8664d95 100644
--- a/media/ndk/NdkMediaCryptoPriv.h
+++ b/media/ndk/NdkMediaCryptoPriv.h
@@ -30,7 +30,7 @@
 
 #include <sys/types.h>
 #include <utils/StrongPointer.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 
 using namespace android;
 
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index e567613..c1d4686 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -26,16 +26,16 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <android_util_Binder.h>
 #include <cutils/properties.h>
-#include <utils/Log.h>
-#include <utils/StrongPointer.h>
+#include <datasource/DataSourceFactory.h>
+#include <datasource/HTTPBase.h>
+#include <datasource/NuCachedSource2.h>
 #include <media/IMediaHTTPService.h>
 #include <media/NdkMediaError.h>
 #include <media/NdkMediaDataSource.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/InterfaceUtils.h>
+#include <utils/Log.h>
+#include <utils/StrongPointer.h>
 
-#include "../../libstagefright/include/HTTPBase.h"
-#include "../../libstagefright/include/NuCachedSource2.h"
 #include "NdkMediaDataSourceCallbacksPriv.h"
 
 
@@ -202,7 +202,7 @@
         headers.add(key8, value8);
     }
 
-    sp<DataSource> source = DataSourceFactory::CreateFromURI(service, uri, &headers);
+    sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromURI(service, uri, &headers);
     if (source == NULL) {
         ALOGE("AMediaDataSource_newUri source is null");
         return NULL;
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index 85dbffe..60f3e8e 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -29,12 +29,12 @@
 
 #include <android-base/properties.h>
 #include <binder/PermissionController.h>
-#include <media/IDrm.h>
-#include <media/IDrmClient.h>
+#include <mediadrm/IDrm.h>
+#include <mediadrm/IDrmClient.h>
 #include <media/stagefright/MediaErrors.h>
 #include <binder/IServiceManager.h>
-#include <media/IMediaDrmService.h>
 #include <media/NdkMediaCrypto.h>
+#include <mediadrm/IMediaDrmService.h>
 
 
 using namespace android;
diff --git a/media/tests/benchmark/Android.bp b/media/tests/benchmark/Android.bp
index 8a7a59f..de408dd 100644
--- a/media/tests/benchmark/Android.bp
+++ b/media/tests/benchmark/Android.bp
@@ -17,4 +17,5 @@
 subdirs = [
     "src",
     "tests",
-]
\ No newline at end of file
+    "MediaBenchmarkTest",
+]
diff --git a/media/tests/benchmark/MediaBenchmarkTest/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
new file mode 100644
index 0000000..91b03f1
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+android_test {
+    name: "MediaBenchmarkTest",
+
+    // Include all the test code
+    srcs: ["src/androidTest/**/*.java"],
+
+    sdk_version: "system_current",
+
+    resource_dirs: ["res"],
+
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+
+    static_libs: [
+        "libMediaBenchmark",
+        "junit",
+        "androidx.test.runner",
+    ],
+}
+
+android_library {
+    name: "libMediaBenchmark",
+
+    // Include all the libraries
+    srcs: ["src/main/**/*.java"],
+
+    sdk_version: "system_current",
+
+    static_libs: [
+        "androidx.test.core",
+    ],
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
new file mode 100644
index 0000000..eea9914
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.android.media.benchmark">
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
+
+    <application
+        tools:ignore="AllowBackup,GoogleAppIndexingWarning,MissingApplicationIcon"
+        tools:remove="android:appComponentFactory">
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.media.benchmark"
+            android:label="Benchmark Media Test"/>
+</manifest>
\ No newline at end of file
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
new file mode 100644
index 0000000..89d6ce2
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<configuration description="Runs Media Benchmark Tests">
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="MediaBenchmarkTest.apk" />
+    </target_preparer>
+
+    <option name="test-tag" value="MediaBenchmarkTest" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.media.benchmark" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/build.gradle b/media/tests/benchmark/MediaBenchmarkTest/build.gradle
new file mode 100644
index 0000000..b0ee692
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/build.gradle
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.5.0'
+    }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 29
+    defaultConfig {
+        applicationId "com.android.media.benchmark"
+        minSdkVersion 21
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+    sourceSets {
+        main {
+            java.srcDirs 'src/main/java'
+            res.srcDirs 'res'
+            manifest.srcFile 'AndroidManifest.xml'
+        }
+        androidTest {
+            java.srcDirs  'src/androidTest/java'
+            res.srcDirs 'res'
+            manifest.srcFile 'AndroidManifest.xml'
+        }
+    }
+}
+
+repositories {
+    google()
+    jcenter()
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'androidx.appcompat:appcompat:1.1.0'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test:runner:1.2.0'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+}
\ No newline at end of file
diff --git a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
new file mode 100644
index 0000000..24dbccc
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
@@ -0,0 +1,4 @@
+<resources>
+    <string name="input_file_path">/data/local/tmp/MediaBenchmark/res/</string>
+    <string name="output_file_path">/data/local/tmp/MediaBenchmark/output/</string>
+</resources>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
new file mode 100644
index 0000000..be2633d
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.tests;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.CodecUtils;
+import com.android.media.benchmark.library.Decoder;
+import com.android.media.benchmark.library.Extractor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+public class DecoderTest {
+    private static final Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+    private static final String mOutputFilePath = mContext.getString(R.string.output_file_path);
+    private static final String TAG = "DecoderTest";
+    private static final long PER_TEST_TIMEOUT_MS = 60000;
+    private static final boolean DEBUG = false;
+    private static final boolean WRITE_OUTPUT = false;
+    private String mInputFile;
+    private boolean mAsyncMode;
+
+    public DecoderTest(String inputFile, boolean asyncMode) {
+        this.mInputFile = inputFile;
+        this.mAsyncMode = asyncMode;
+    }
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> input() {
+        return Arrays.asList(new Object[][]{
+                //Audio Sync Test
+                {"bbb_44100hz_2ch_128kbps_aac_30sec.mp4", false},
+                {"bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", false},
+                {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", false},
+                {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", false},
+                {"bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", false},
+                {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4", false},
+                {"bbb_48000hz_2ch_100kbps_opus_30sec.webm", false},
+                // Audio Async Test
+                {"bbb_44100hz_2ch_128kbps_aac_30sec.mp4", true},
+                {"bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", true},
+                {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", true},
+                {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", true},
+                {"bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", true},
+                {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4", true},
+                {"bbb_48000hz_2ch_100kbps_opus_30sec.webm", true},
+                // Video Sync Test
+                {"crowd_1920x1080_25fps_4000kbps_vp9.webm", false},
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm", false},
+                {"crowd_1920x1080_25fps_4000kbps_av1.webm", false},
+                {"crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", false},
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", false},
+                {"crowd_352x288_25fps_6000kbps_h263.3gp", false},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", false},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", false},
+                // Video Async Test
+                {"crowd_1920x1080_25fps_4000kbps_vp9.webm", true},
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm", true},
+                {"crowd_1920x1080_25fps_4000kbps_av1.webm", true},
+                {"crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", true},
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", true},
+                {"crowd_352x288_25fps_6000kbps_h263.3gp", true},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", true},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", true}});
+    }
+
+    @Test(timeout = PER_TEST_TIMEOUT_MS)
+    public void testDecoder() throws IOException {
+        File inputFile = new File(mInputFilePath + mInputFile);
+        if (inputFile.exists()) {
+            FileInputStream fileInput = new FileInputStream(inputFile);
+            FileDescriptor fileDescriptor = fileInput.getFD();
+            Extractor extractor = new Extractor();
+            int trackCount = extractor.setUpExtractor(fileDescriptor);
+            ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
+            ArrayList<MediaCodec.BufferInfo> frameInfo = new ArrayList<>();
+            if (trackCount <= 0) {
+                Log.e(TAG, "Extraction failed. No tracks for file: " + mInputFile);
+                return;
+            }
+            for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+                extractor.selectExtractorTrack(currentTrack);
+                MediaFormat format = extractor.getFormat(currentTrack);
+                String mime = format.getString(MediaFormat.KEY_MIME);
+                ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
+                if (mediaCodecs.size() <= 0) {
+                    Log.e(TAG,
+                            "No suitable codecs found for file: " + mInputFile
+                                    + " track : " + currentTrack + " mime: " + mime);
+                    continue;
+                }
+                // Get samples from extractor
+                int sampleSize;
+                do {
+                    sampleSize = extractor.getFrameSample();
+                    MediaCodec.BufferInfo bufInfo = new MediaCodec.BufferInfo();
+                    MediaCodec.BufferInfo info = extractor.getBufferInfo();
+                    ByteBuffer dataBuffer = ByteBuffer.allocate(info.size);
+                    dataBuffer.put(extractor.getFrameBuffer().array(), 0, info.size);
+                    bufInfo.set(info.offset, info.size, info.presentationTimeUs, info.flags);
+                    inputBuffer.add(dataBuffer);
+                    frameInfo.add(bufInfo);
+                    if (DEBUG) {
+                        Log.d(TAG,
+                                "Extracted bufInfo: flag = " + bufInfo.flags + " timestamp = "
+                                        + bufInfo.presentationTimeUs + " size = " + bufInfo.size);
+                    }
+                } while (sampleSize > 0);
+                for (String codecName : mediaCodecs) {
+                    FileOutputStream decodeOutputStream = null;
+                    if (WRITE_OUTPUT) {
+                        if (!Paths.get(mOutputFilePath).toFile().exists()) {
+                            Files.createDirectories(Paths.get(mOutputFilePath));
+                        }
+                        File outFile = new File(mOutputFilePath + "decoder.out");
+                        if (outFile.exists()) {
+                            if (!outFile.delete()) {
+                                Log.e(TAG, " Unable to delete existing file" + outFile.toString());
+                            }
+                        }
+                        if (outFile.createNewFile()) {
+                            decodeOutputStream = new FileOutputStream(outFile);
+                        } else {
+                            Log.e(TAG, "Unable to create file: " + outFile.toString());
+                        }
+                    }
+                    Decoder decoder = new Decoder();
+                    decoder.setupDecoder(decodeOutputStream);
+                    int status =
+                            decoder.decode(inputBuffer, frameInfo, mAsyncMode, format, codecName);
+                    decoder.deInitCodec();
+                    if (status == 0) {
+                        decoder.dumpStatistics(
+                                mInputFile + " " + codecName, extractor.getClipDuration());
+                        Log.i(TAG,
+                                "Decoding Successful for file: " + mInputFile
+                                        + " with codec: " + codecName);
+                    } else {
+                        Log.e(TAG,
+                                "Decoder returned error " + status + " for file: " + mInputFile
+                                        + " with codec: " + codecName);
+                    }
+                    decoder.resetDecoder();
+                    if (decodeOutputStream != null) {
+                        decodeOutputStream.close();
+                    }
+                }
+                extractor.unselectExtractorTrack(currentTrack);
+                inputBuffer.clear();
+                frameInfo.clear();
+            }
+            extractor.deinitExtractor();
+            fileInput.close();
+        } else {
+            Log.w(TAG,
+                    "Warning: Test Skipped. Cannot find " + mInputFile + " in directory "
+                            + mInputFilePath);
+        }
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
new file mode 100644
index 0000000..9db9c84
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.tests;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.CodecUtils;
+import com.android.media.benchmark.library.Decoder;
+import com.android.media.benchmark.library.Encoder;
+import com.android.media.benchmark.library.Extractor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.nio.ByteBuffer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+public class EncoderTest {
+    private static final Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+    private static final String mOutputFilePath = mContext.getString(R.string.output_file_path);
+    private static final String TAG = "EncoderTest";
+    private static final long PER_TEST_TIMEOUT_MS = 120000;
+    private static final boolean DEBUG = false;
+    private static final boolean WRITE_OUTPUT = false;
+    private static final int ENCODE_DEFAULT_FRAME_RATE = 25;
+    private static final int ENCODE_DEFAULT_BIT_RATE = 8000000 /* 8 Mbps */;
+    private static final int ENCODE_MIN_BIT_RATE = 600000 /* 600 Kbps */;
+
+    private String mInputFile;
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> inputFiles() {
+        return Arrays.asList(new Object[][]{
+                // Audio Test
+                {"bbb_44100hz_2ch_128kbps_aac_30sec.mp4"},
+                {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp"},
+                {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp"},
+                {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4"},
+                {"bbb_48000hz_2ch_100kbps_opus_30sec.webm"},
+                // Video Test
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm"},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts"},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv"},
+                {"crowd_1920x1080_25fps_4000kbps_vp9.webm"},
+                {"crowd_176x144_25fps_6000kbps_mpeg4.mp4"},
+                {"crowd_176x144_25fps_6000kbps_h263.3gp"}});
+    }
+
+    public EncoderTest(String inputFileName) {
+        this.mInputFile = inputFileName;
+    }
+
+    @Test(timeout = PER_TEST_TIMEOUT_MS)
+    public void sampleEncoderTest() throws Exception {
+        int status;
+        int frameSize;
+
+        //Parameters for video
+        int width = 0;
+        int height = 0;
+        int profile = 0;
+        int level = 0;
+        int frameRate = 0;
+
+        //Parameters for audio
+        int bitRate = 0;
+        int sampleRate = 0;
+        int numChannels = 0;
+
+        File inputFile = new File(mInputFilePath + mInputFile);
+        if (inputFile.exists()) {
+            FileInputStream fileInput = new FileInputStream(inputFile);
+            FileDescriptor fileDescriptor = fileInput.getFD();
+            Extractor extractor = new Extractor();
+            int trackCount = extractor.setUpExtractor(fileDescriptor);
+            if (trackCount <= 0) {
+                Log.e(TAG, "Extraction failed. No tracks for file: " + mInputFile);
+                return;
+            }
+            ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
+            ArrayList<MediaCodec.BufferInfo> frameInfo = new ArrayList<>();
+            for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+                extractor.selectExtractorTrack(currentTrack);
+                MediaFormat format = extractor.getFormat(currentTrack);
+                // Get samples from extractor
+                int sampleSize;
+                do {
+                    sampleSize = extractor.getFrameSample();
+                    MediaCodec.BufferInfo bufInfo = new MediaCodec.BufferInfo();
+                    MediaCodec.BufferInfo info = extractor.getBufferInfo();
+                    ByteBuffer dataBuffer = ByteBuffer.allocate(info.size);
+                    dataBuffer.put(extractor.getFrameBuffer().array(), 0, info.size);
+                    bufInfo.set(info.offset, info.size, info.presentationTimeUs, info.flags);
+                    inputBuffer.add(dataBuffer);
+                    frameInfo.add(bufInfo);
+                    if (DEBUG) {
+                        Log.d(TAG, "Extracted bufInfo: flag = " + bufInfo.flags + " timestamp = " +
+                                bufInfo.presentationTimeUs + " size = " + bufInfo.size);
+                    }
+                } while (sampleSize > 0);
+
+                int tid = android.os.Process.myTid();
+                File decodedFile = new File(mContext.getFilesDir() + "/decoder_" + tid + ".out");
+                FileOutputStream decodeOutputStream = new FileOutputStream(decodedFile);
+                Decoder decoder = new Decoder();
+                decoder.setupDecoder(decodeOutputStream);
+                status = decoder.decode(inputBuffer, frameInfo, false, format, "");
+                if (status == 0) {
+                    Log.i(TAG, "Decoding complete.");
+                } else {
+                    Log.e(TAG, "Decode returned error. Encoding did not take place." + status);
+                    return;
+                }
+                decoder.deInitCodec();
+                extractor.unselectExtractorTrack(currentTrack);
+                inputBuffer.clear();
+                frameInfo.clear();
+                if (decodeOutputStream != null) {
+                    decodeOutputStream.close();
+                }
+                String mime = format.getString(MediaFormat.KEY_MIME);
+                ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, true);
+                if (mediaCodecs.size() <= 0) {
+                    Log.e(TAG, "No suitable codecs found for file: " + mInputFile + " track : " +
+                            currentTrack + " mime: " + mime);
+                    return;
+                }
+                Boolean[] encodeMode = {true, false};
+                /* Encoding the decoder's output */
+                for (Boolean asyncMode : encodeMode) {
+                    for (String codecName : mediaCodecs) {
+                        FileOutputStream encodeOutputStream = null;
+                        if (WRITE_OUTPUT) {
+                            File outEncodeFile = new File(mOutputFilePath + "encoder.out");
+                            if (outEncodeFile.exists()) {
+                                if (!outEncodeFile.delete()) {
+                                    Log.e(TAG, "Unable to delete existing file" +
+                                            decodedFile.toString());
+                                }
+                            }
+                            if (outEncodeFile.createNewFile()) {
+                                encodeOutputStream = new FileOutputStream(outEncodeFile);
+                            } else {
+                                Log.e(TAG, "Unable to create file to write encoder output: " +
+                                        outEncodeFile.toString());
+                            }
+                        }
+                        File rawFile =
+                                new File(mContext.getFilesDir() + "/decoder_" + tid + ".out");
+                        if (rawFile.exists()) {
+                            if (DEBUG) {
+                                Log.i(TAG, "Path of decoded input file: " + rawFile.toString());
+                            }
+                            FileInputStream eleStream = new FileInputStream(rawFile);
+                            if (mime.startsWith("video/")) {
+                                width = format.getInteger(MediaFormat.KEY_WIDTH);
+                                height = format.getInteger(MediaFormat.KEY_HEIGHT);
+                                if (format.containsKey(MediaFormat.KEY_FRAME_RATE)) {
+                                    frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
+                                } else if (frameRate <= 0) {
+                                    frameRate = ENCODE_DEFAULT_FRAME_RATE;
+                                }
+                                if (format.containsKey(MediaFormat.KEY_BIT_RATE)) {
+                                    bitRate = format.getInteger(MediaFormat.KEY_BIT_RATE);
+                                } else if (bitRate <= 0) {
+                                    if (mime.contains("video/3gpp") ||
+                                            mime.contains("video/mp4v-es")) {
+                                        bitRate = ENCODE_MIN_BIT_RATE;
+                                    } else {
+                                        bitRate = ENCODE_DEFAULT_BIT_RATE;
+                                    }
+                                }
+                                if (format.containsKey(MediaFormat.KEY_PROFILE)) {
+                                    profile = format.getInteger(MediaFormat.KEY_PROFILE);
+                                }
+                                if (format.containsKey(MediaFormat.KEY_PROFILE)) {
+                                    level = format.getInteger(MediaFormat.KEY_LEVEL);
+                                }
+                            } else {
+                                sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+                                numChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+                                bitRate = sampleRate * numChannels * 16;
+                            }
+                            /*Setup Encode Format*/
+                            MediaFormat encodeFormat;
+                            if (mime.startsWith("video/")) {
+                                frameSize = width * height * 3 / 2;
+                                encodeFormat = MediaFormat.createVideoFormat(mime, width, height);
+                                encodeFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
+                                encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+                                encodeFormat.setInteger(MediaFormat.KEY_PROFILE, profile);
+                                encodeFormat.setInteger(MediaFormat.KEY_LEVEL, level);
+                                encodeFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
+                                encodeFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, frameSize);
+                            } else {
+                                encodeFormat = MediaFormat
+                                        .createAudioFormat(mime, sampleRate, numChannels);
+                                encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+                                frameSize = 4096;
+                            }
+                            Encoder encoder = new Encoder();
+                            encoder.setupEncoder(encodeOutputStream, eleStream);
+                            status = encoder.encode(codecName, encodeFormat, mime, frameRate,
+                                    sampleRate, frameSize, asyncMode);
+                            encoder.deInitEncoder();
+                            if (status == 0) {
+                                encoder.dumpStatistics(mInputFile + "with " + codecName + " for " +
+                                        "aSyncMode = " + asyncMode, extractor.getClipDuration());
+                                Log.i(TAG, "Encoding complete for file: " + mInputFile +
+                                        " with codec: " + codecName + " for aSyncMode = " +
+                                        asyncMode);
+                            } else {
+                                Log.e(TAG,
+                                        codecName + " encoder returned error " + status + " for " +
+                                                "file:" + " " + mInputFile);
+                            }
+                            encoder.resetEncoder();
+                            eleStream.close();
+                            if (encodeOutputStream != null) {
+                                encodeOutputStream.close();
+                            }
+                        }
+                    }
+                }
+                //Cleanup temporary input file
+                if (decodedFile.exists()) {
+                    if (decodedFile.delete()) {
+                        Log.i(TAG, "Successfully deleted decoded file");
+                    } else {
+                        Log.e(TAG, "Unable to delete decoded file");
+                    }
+                }
+            }
+            extractor.deinitExtractor();
+            fileInput.close();
+        } else {
+            Log.w(TAG, "Warning: Test Skipped. Cannot find " + mInputFile + " in directory " +
+                    mInputFilePath);
+        }
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java
new file mode 100644
index 0000000..a02011c
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.tests;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.Extractor;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+@RunWith(Parameterized.class)
+public class ExtractorTest {
+    private static Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+    private static final String TAG = "ExtractorTest";
+    private String mInputFileName;
+    private int mTrackId;
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> inputFiles() {
+        return Arrays.asList(new Object[][]{/* Parameters: filename, trackId*/
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", 0},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", 0},
+                {"crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", 0},
+                {"crowd_1920x1080_25fps_4000kbps_av1.webm", 0},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", 0},
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm", 0},
+                {"bbb_44100hz_2ch_128kbps_aac_5mins.mp4", 0},
+                {"bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 0},
+                {"bbb_44100hz_2ch_600kbps_flac_5mins.flac", 0},
+                {"bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", 0},
+                {"bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", 0},
+                {"bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", 0},
+                {"bbb_48000hz_2ch_100kbps_opus_5mins.webm", 0}});
+    }
+
+    public ExtractorTest(String filename, int track) {
+        this.mInputFileName = filename;
+        this.mTrackId = track;
+    }
+
+    @Test
+    public void sampleExtractTest() throws IOException {
+        int status = -1;
+        File inputFile = new File(mInputFilePath + mInputFileName);
+        if (inputFile.exists()) {
+            FileInputStream fileInput = new FileInputStream(inputFile);
+            FileDescriptor fileDescriptor = fileInput.getFD();
+            Extractor extractor = new Extractor();
+            extractor.setUpExtractor(fileDescriptor);
+            status = extractor.extractSample(mTrackId);
+            extractor.deinitExtractor();
+            extractor.dumpStatistics(mInputFileName);
+            fileInput.close();
+        } else {
+            Log.e(TAG, "Cannot find " + mInputFileName + " in directory " + mInputFilePath);
+        }
+        assertThat(status, is(equalTo(0)));
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
new file mode 100644
index 0000000..8c3080c
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.tests;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.Extractor;
+import com.android.media.benchmark.library.Muxer;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+import android.util.Log;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+@RunWith(Parameterized.class)
+public class MuxerTest {
+    private static Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+    private static final String TAG = "MuxerTest";
+    private static final Map<String, Integer> mMapFormat = new Hashtable<String, Integer>() {
+        {
+            put("mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
+            put("webm", MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM);
+            put("3gpp", MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP);
+            put("ogg", MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG);
+        }
+    };
+    private String mInputFileName;
+    private String mFormat;
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> inputFiles() {
+        return Arrays.asList(new Object[][]{
+                /* Parameters: filename, format */
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm", "webm"},
+                {"crowd_1920x1080_25fps_4000kbps_vp9.webm", "webm"},
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "mp4"},
+                {"crowd_352x288_25fps_6000kbps_h263.3gp", "mp4"},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", "mp4"},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", "mp4"},
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "3gpp"},
+                {"crowd_352x288_25fps_6000kbps_h263.3gp", "3gpp"},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", "3gpp"},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", "3gpp"},
+                {"bbb_48000hz_2ch_100kbps_opus_5mins.webm", "ogg"},
+                {"bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", "webm"},
+                {"bbb_48000hz_2ch_100kbps_opus_5mins.webm", "webm"},
+                {"bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "mp4"},
+                {"bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "mp4"},
+                {"bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "mp4"},
+                {"bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "3gpp"},
+                {"bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "3gpp"},
+                {"bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "3gpp"}});
+    }
+
+    public MuxerTest(String filename, String outputFormat) {
+        this.mInputFileName = filename;
+        this.mFormat = outputFormat;
+    }
+
+    @Test
+    public void sampleMuxerTest() throws IOException {
+        int status = -1;
+        File inputFile = new File(mInputFilePath + mInputFileName);
+        if (inputFile.exists()) {
+            FileInputStream fileInput = new FileInputStream(inputFile);
+            FileDescriptor fileDescriptor = fileInput.getFD();
+            ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
+            ArrayList<MediaCodec.BufferInfo> inputBufferInfo = new ArrayList<>();
+            Extractor extractor = new Extractor();
+            int trackCount = extractor.setUpExtractor(fileDescriptor);
+            for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+                extractor.selectExtractorTrack(currentTrack);
+                while (true) {
+                    int sampleSize = extractor.getFrameSample();
+                    MediaCodec.BufferInfo bufferInfo = extractor.getBufferInfo();
+                    MediaCodec.BufferInfo tempBufferInfo = new MediaCodec.BufferInfo();
+                    tempBufferInfo
+                            .set(bufferInfo.offset, bufferInfo.size, bufferInfo.presentationTimeUs,
+                                    bufferInfo.flags);
+                    inputBufferInfo.add(tempBufferInfo);
+                    ByteBuffer tempSampleBuffer = ByteBuffer.allocate(tempBufferInfo.size);
+                    tempSampleBuffer.put(extractor.getFrameBuffer().array(), 0, bufferInfo.size);
+                    inputBuffer.add(tempSampleBuffer);
+                    if (sampleSize < 0) {
+                        break;
+                    }
+                }
+                MediaFormat format = extractor.getFormat(currentTrack);
+                int outputFormat = mMapFormat.getOrDefault(mFormat, -1);
+                if (outputFormat != -1) {
+                    Muxer muxer = new Muxer();
+                    int trackIndex = muxer.setUpMuxer(mContext, outputFormat, format);
+                    status = muxer.mux(trackIndex, inputBuffer, inputBufferInfo);
+                    if (status != 0) {
+                        Log.e(TAG, "Cannot perform write operation for " + mInputFileName);
+                    }
+                    muxer.deInitMuxer();
+                    muxer.dumpStatistics(mInputFileName, extractor.getClipDuration());
+                    muxer.resetMuxer();
+                    extractor.unselectExtractorTrack(currentTrack);
+                    inputBufferInfo.clear();
+                    inputBuffer.clear();
+                } else {
+                    Log.e(TAG, "Test failed for " + mInputFileName + ". Returned invalid " +
+                            "output format for given " + mFormat + " format.");
+                }
+            }
+            extractor.deinitExtractor();
+            fileInput.close();
+        } else {
+            Log.w(TAG, "Warning: Test Skipped. Cannot find " + mInputFileName + " in directory " +
+                    mInputFilePath);
+        }
+        assertThat(status, is(equalTo(0)));
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
new file mode 100644
index 0000000..08035c9
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
@@ -0,0 +1,39 @@
+package com.android.media.benchmark.library;
+
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.os.Build;
+
+import java.util.ArrayList;
+
+public class CodecUtils {
+    private CodecUtils() {}
+
+    /**
+     * Queries the MediaCodecList and returns codec names of supported codecs.
+     *
+     * @param mimeType  Mime type of input
+     * @param isEncoder Specifies encoder or decoder
+     * @return ArrayList of codec names
+     */
+    public static ArrayList<String> selectCodecs(String mimeType, boolean isEncoder) {
+        MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
+        ArrayList<String> supportedCodecs = new ArrayList<>();
+        for (MediaCodecInfo codecInfo : codecInfos) {
+            if (isEncoder != codecInfo.isEncoder()) {
+                continue;
+            }
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && codecInfo.isAlias()) {
+                continue;
+            }
+            String[] types = codecInfo.getSupportedTypes();
+            for (String type : types) {
+                if (type.equalsIgnoreCase(mimeType)) {
+                    supportedCodecs.add(codecInfo.getName());
+                }
+            }
+        }
+        return supportedCodecs;
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
new file mode 100644
index 0000000..2cd27c2
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+public class Decoder {
+    private static final String TAG = "Decoder";
+    private static final boolean DEBUG = false;
+    private static final int kQueueDequeueTimeoutUs = 1000;
+
+    private final Object mLock = new Object();
+    private MediaCodec mCodec;
+    private ArrayList<BufferInfo> mInputBufferInfo;
+    private Stats mStats;
+
+    private boolean mSawInputEOS;
+    private boolean mSawOutputEOS;
+    private boolean mSignalledError;
+
+    private int mNumOutputFrame;
+    private int mIndex;
+
+    private ArrayList<ByteBuffer> mInputBuffer;
+    private FileOutputStream mOutputStream;
+
+    public Decoder() { mStats = new Stats(); }
+
+    /**
+     * Setup of decoder
+     *
+     * @param outputStream Will dump the output in this stream if not null.
+     */
+    public void setupDecoder(FileOutputStream outputStream) {
+        mSignalledError = false;
+        mOutputStream = outputStream;
+    }
+
+    private MediaCodec createCodec(String codecName, MediaFormat format) throws IOException {
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        try {
+            MediaCodec codec;
+            if (codecName.isEmpty()) {
+                Log.i(TAG, "File mime type: " + mime);
+                if (mime != null) {
+                    codec = MediaCodec.createDecoderByType(mime);
+                    Log.i(TAG, "Decoder created for mime type " + mime);
+                    return codec;
+                } else {
+                    Log.e(TAG, "Mime type is null, please specify a mime type to create decoder");
+                    return null;
+                }
+            } else {
+                codec = MediaCodec.createByCodecName(codecName);
+                Log.i(TAG, "Decoder created with codec name: " + codecName + " mime: " + mime);
+                return codec;
+            }
+        } catch (IllegalArgumentException ex) {
+            ex.printStackTrace();
+            Log.e(TAG, "Failed to create decoder for " + codecName + " mime:" + mime);
+            return null;
+        }
+    }
+
+    /**
+     * Decodes the given input buffer,
+     * provided valid list of buffer info and format are passed as inputs.
+     *
+     * @param inputBuffer     Decode the provided list of ByteBuffers
+     * @param inputBufferInfo List of buffer info corresponding to provided input buffers
+     * @param asyncMode       Will run on async implementation if true
+     * @param format          For creating the decoder if codec name is empty and configuring it
+     * @param codecName       Will create the decoder with codecName
+     * @return 0 if decode was successful , -1 for fail, -2 for decoder not created
+     * @throws IOException if the codec cannot be created.
+     */
+    public int decode(@NonNull ArrayList<ByteBuffer> inputBuffer,
+            @NonNull ArrayList<BufferInfo> inputBufferInfo, final boolean asyncMode,
+            @NonNull MediaFormat format, String codecName) throws IOException {
+        mInputBuffer = new ArrayList<>(inputBuffer.size());
+        mInputBuffer.addAll(inputBuffer);
+        mInputBufferInfo = new ArrayList<>(inputBufferInfo.size());
+        mInputBufferInfo.addAll(inputBufferInfo);
+        mSawInputEOS = false;
+        mSawOutputEOS = false;
+        mNumOutputFrame = 0;
+        mIndex = 0;
+        long sTime = mStats.getCurTime();
+        mCodec = createCodec(codecName, format);
+        if (mCodec == null) {
+            return -2;
+        }
+        if (asyncMode) {
+            mCodec.setCallback(new MediaCodec.Callback() {
+                @Override
+                public void onInputBufferAvailable(
+                        @NonNull MediaCodec mediaCodec, int inputBufferId) {
+                    try {
+                        mStats.addInputTime();
+                        onInputAvailable(inputBufferId, mediaCodec);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        Log.e(TAG, e.toString());
+                    }
+                }
+
+                @Override
+                public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+                        int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
+                    mStats.addOutputTime();
+                    onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+                    if (mSawOutputEOS) {
+                        Log.i(TAG, "Saw output EOS");
+                        synchronized (mLock) { mLock.notify(); }
+                    }
+                }
+
+                @Override
+                public void onOutputFormatChanged(
+                        @NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
+                    Log.i(TAG, "Output format changed. Format: " + format.toString());
+                }
+
+                @Override
+                public void onError(
+                        @NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
+                    mSignalledError = true;
+                    Log.e(TAG, "Codec Error: " + e.toString());
+                    e.printStackTrace();
+                    synchronized (mLock) { mLock.notify(); }
+                }
+            });
+        }
+        int isEncoder = 0;
+        if (DEBUG) {
+            Log.d(TAG, "Media Format : " + format.toString());
+        }
+        mCodec.configure(format, null, null, isEncoder);
+        mCodec.start();
+        Log.i(TAG, "Codec started ");
+        long eTime = mStats.getCurTime();
+        mStats.setInitTime(mStats.getTimeDiff(sTime, eTime));
+        mStats.setStartTime();
+        if (asyncMode) {
+            try {
+                synchronized (mLock) { mLock.wait(); }
+                if (mSignalledError) {
+                    return -1;
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        } else {
+            while (!mSawOutputEOS && !mSignalledError) {
+                /* Queue input data */
+                if (!mSawInputEOS) {
+                    int inputBufferId = mCodec.dequeueInputBuffer(kQueueDequeueTimeoutUs);
+                    if (inputBufferId < 0 && inputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG,
+                                "MediaCodec.dequeueInputBuffer "
+                                        + " returned invalid index : " + inputBufferId);
+                        return -1;
+                    }
+                    mStats.addInputTime();
+                    onInputAvailable(inputBufferId, mCodec);
+                }
+                /* Dequeue output data */
+                BufferInfo outputBufferInfo = new BufferInfo();
+                int outputBufferId =
+                        mCodec.dequeueOutputBuffer(outputBufferInfo, kQueueDequeueTimeoutUs);
+                if (outputBufferId < 0) {
+                    if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                        MediaFormat outFormat = mCodec.getOutputFormat();
+                        Log.i(TAG, "Output format changed. Format: " + outFormat.toString());
+                    } else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                        Log.i(TAG, "Ignoring deprecated flag: INFO_OUTPUT_BUFFERS_CHANGED");
+                    } else if (outputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG,
+                                "MediaCodec.dequeueOutputBuffer"
+                                        + " returned invalid index " + outputBufferId);
+                        return -1;
+                    }
+                } else {
+                    mStats.addOutputTime();
+                    if (DEBUG) {
+                        Log.d(TAG, "Dequeue O/P buffer with BufferID " + outputBufferId);
+                    }
+                    onOutputAvailable(mCodec, outputBufferId, outputBufferInfo);
+                }
+                if (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
+                    Log.i(TAG, "Saw output EOS");
+                }
+            }
+        }
+        mInputBuffer.clear();
+        mInputBufferInfo.clear();
+        return 0;
+    }
+
+    /**
+     * Stops the codec and releases codec resources.
+     */
+    public void deInitCodec() {
+        long sTime = mStats.getCurTime();
+        if (mCodec != null) {
+            mCodec.stop();
+            mCodec.release();
+            mCodec = null;
+        }
+        long eTime = mStats.getCurTime();
+        mStats.setDeInitTime(mStats.getTimeDiff(sTime, eTime));
+    }
+
+    /**
+     * Prints out the statistics in the information log
+     *
+     * @param inputReference The operation being performed, in this case decode
+     * @param durationUs     Duration of the clip in microseconds
+     */
+    public void dumpStatistics(String inputReference, long durationUs) {
+        String operation = "decode";
+        mStats.dumpStatistics(operation, inputReference, durationUs);
+    }
+
+    /**
+     * Resets the stats
+     */
+    public void resetDecoder() { mStats.reset(); }
+
+    private void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
+        if ((inputBufferId >= 0) && !mSawInputEOS) {
+            ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
+            BufferInfo bufInfo = mInputBufferInfo.get(mIndex);
+            inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
+            mIndex++;
+            if (bufInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
+                mSawInputEOS = true;
+                Log.i(TAG, "Saw input EOS");
+            }
+            mStats.addFrameSize(bufInfo.size);
+            mediaCodec.queueInputBuffer(inputBufferId, bufInfo.offset, bufInfo.size,
+                    bufInfo.presentationTimeUs, bufInfo.flags);
+            if (DEBUG) {
+                Log.d(TAG,
+                        "Codec Input: "
+                                + "flag = " + bufInfo.flags + " timestamp = "
+                                + bufInfo.presentationTimeUs + " size = " + bufInfo.size);
+            }
+        }
+    }
+
+    private void onOutputAvailable(
+            MediaCodec mediaCodec, int outputBufferId, BufferInfo outputBufferInfo) {
+        if (mSawOutputEOS || outputBufferId < 0) {
+            return;
+        }
+        mNumOutputFrame++;
+        if (DEBUG) {
+            Log.d(TAG,
+                    "In OutputBufferAvailable ,"
+                            + " output frame number = " + mNumOutputFrame);
+        }
+        if (mOutputStream != null) {
+            try {
+                ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferId);
+                byte[] bytesOutput = new byte[outputBuffer.remaining()];
+                outputBuffer.get(bytesOutput);
+                mOutputStream.write(bytesOutput);
+            } catch (IOException e) {
+                e.printStackTrace();
+                Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+            }
+        }
+        mediaCodec.releaseOutputBuffer(outputBufferId, false);
+        mSawOutputEOS = (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
new file mode 100644
index 0000000..03db294
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.media.MediaCodec;
+import android.media.MediaCodec.CodecException;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class Encoder {
+    private static final int ENCODE_DEFAULT_MAX_INPUT_SIZE = 3840;
+    private static final String TAG = "Encoder";
+    private static final boolean DEBUG = false;
+    private static final int kQueueDequeueTimeoutUs = 1000;
+
+    private final Object mLock = new Object();
+    private MediaCodec mCodec;
+    private String mMime;
+    private Stats mStats;
+
+    private int mOffset;
+    private int mFrameSize;
+    private int mNumInputFrame;
+    private int mNumFrames;
+    private int mFrameRate;
+    private int mSampleRate;
+    private long mInputBufferSize;
+
+    private boolean mSawInputEOS;
+    private boolean mSawOutputEOS;
+    private boolean mSignalledError;
+
+    private FileInputStream mInputStream;
+    private FileOutputStream mOutputStream;
+
+    public Encoder() {
+        mStats = new Stats();
+        mNumInputFrame = 0;
+        mSawInputEOS = false;
+        mSawOutputEOS = false;
+        mSignalledError = false;
+    }
+
+    /**
+     * Setup of encoder
+     *
+     * @param encoderOutputStream Will dump the encoder output in this stream if not null.
+     * @param fileInputStream     Will read the decoded output from this stream
+     */
+    public void setupEncoder(FileOutputStream encoderOutputStream,
+                             FileInputStream fileInputStream) {
+        this.mInputStream = fileInputStream;
+        this.mOutputStream = encoderOutputStream;
+    }
+
+    private MediaCodec createCodec(String codecName, String mime) throws IOException {
+        try {
+            MediaCodec codec;
+            if (codecName.isEmpty()) {
+                Log.i(TAG, "Mime type: " + mime);
+                if (mime != null) {
+                    codec = MediaCodec.createEncoderByType(mime);
+                    Log.i(TAG, "Encoder created for mime type " + mime);
+                    return codec;
+                } else {
+                    Log.e(TAG, "Mime type is null, please specify a mime type to create encoder");
+                    return null;
+                }
+            } else {
+                codec = MediaCodec.createByCodecName(codecName);
+                Log.i(TAG, "Encoder created with codec name: " + codecName + " and mime: " + mime);
+                return codec;
+            }
+        } catch (IllegalArgumentException ex) {
+            ex.printStackTrace();
+            Log.e(TAG, "Failed to create encoder for " + codecName + " mime: " + mime);
+            return null;
+        }
+    }
+
+    /**
+     * Encodes the given raw input file and measures the performance of encode operation,
+     * provided a valid list of parameters are passed as inputs.
+     *
+     * @param codecName    Will create the encoder with codecName
+     * @param mime         For creating encode format
+     * @param encodeFormat Format of the output data
+     * @param frameSize    Size of the frame
+     * @param asyncMode    Will run on async implementation if true
+     * @return 0 if encode was successful , -1 for fail, -2 for encoder not created
+     * @throws IOException If the codec cannot be created.
+     */
+    public int encode(String codecName, MediaFormat encodeFormat, String mime, int frameRate,
+                      int sampleRate, int frameSize, boolean asyncMode) throws IOException {
+        mInputBufferSize = mInputStream.getChannel().size();
+        mMime = mime;
+        mOffset = 0;
+        mFrameRate = frameRate;
+        mSampleRate = sampleRate;
+        long sTime = mStats.getCurTime();
+        mCodec = createCodec(codecName, mime);
+        if (mCodec == null) {
+            return -2;
+        }
+        /*Configure Codec*/
+        try {
+            mCodec.configure(encodeFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+        } catch (IllegalArgumentException | IllegalStateException | MediaCodec.CryptoException e) {
+            Log.e(TAG, "Failed to configure " + mCodec.getName() + " encoder.");
+            e.printStackTrace();
+            return -2;
+        }
+        if (mMime.startsWith("video/")) {
+            mFrameSize = frameSize;
+        } else {
+            int maxInputSize = ENCODE_DEFAULT_MAX_INPUT_SIZE;
+            MediaFormat format = mCodec.getInputFormat();
+            if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
+                maxInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
+            }
+            mFrameSize = frameSize;
+            if (mFrameSize > maxInputSize && maxInputSize > 0) {
+                mFrameSize = maxInputSize;
+            }
+        }
+        mNumFrames = (int) ((mInputBufferSize + mFrameSize - 1) / mFrameSize);
+        if (asyncMode) {
+            mCodec.setCallback(new MediaCodec.Callback() {
+                @Override
+                public void onInputBufferAvailable(@NonNull MediaCodec mediaCodec,
+                                                   int inputBufferId) {
+                    try {
+                        mStats.addInputTime();
+                        onInputAvailable(mediaCodec, inputBufferId);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        Log.e(TAG, e.toString());
+                    }
+                }
+
+                @Override
+                public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+                                                    int outputBufferId,
+                                                    @NonNull MediaCodec.BufferInfo bufferInfo) {
+                    mStats.addOutputTime();
+                    onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+                    if (mSawOutputEOS) {
+                        Log.i(TAG, "Saw output EOS");
+                        synchronized (mLock) { mLock.notify(); }
+                    }
+                }
+
+                @Override
+                public void onError(@NonNull MediaCodec mediaCodec, @NonNull CodecException e) {
+                    mediaCodec.stop();
+                    mediaCodec.release();
+                    Log.e(TAG, "CodecError: " + e.toString());
+                    e.printStackTrace();
+                }
+
+                @Override
+                public void onOutputFormatChanged(@NonNull MediaCodec mediaCodec,
+                                                  @NonNull MediaFormat format) {
+                    Log.i(TAG, "Output format changed. Format: " + format.toString());
+                }
+            });
+        }
+        mCodec.start();
+        long eTime = mStats.getCurTime();
+        mStats.setInitTime(mStats.getTimeDiff(sTime, eTime));
+        mStats.setStartTime();
+        if (asyncMode) {
+            try {
+                synchronized (mLock) { mLock.wait(); }
+                if (mSignalledError) {
+                    return -1;
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        } else {
+            while (!mSawOutputEOS && !mSignalledError) {
+                /* Queue input data */
+                if (!mSawInputEOS) {
+                    int inputBufferId = mCodec.dequeueInputBuffer(kQueueDequeueTimeoutUs);
+                    if (inputBufferId < 0 && inputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG, "MediaCodec.dequeueInputBuffer " + "returned invalid index : " +
+                                inputBufferId);
+                        return -1;
+                    }
+                    mStats.addInputTime();
+                    onInputAvailable(mCodec, inputBufferId);
+                }
+                /* Dequeue output data */
+                MediaCodec.BufferInfo outputBufferInfo = new MediaCodec.BufferInfo();
+                int outputBufferId =
+                        mCodec.dequeueOutputBuffer(outputBufferInfo, kQueueDequeueTimeoutUs);
+                if (outputBufferId < 0) {
+                    if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                        MediaFormat outFormat = mCodec.getOutputFormat();
+                        Log.i(TAG, "Output format changed. Format: " + outFormat.toString());
+                    } else if (outputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG, "MediaCodec.dequeueOutputBuffer" + " returned invalid index " +
+                                outputBufferId);
+                        return -1;
+                    }
+                } else {
+                    mStats.addOutputTime();
+                    if (DEBUG) {
+                        Log.d(TAG, "Dequeue O/P buffer with BufferID " + outputBufferId);
+                    }
+                    onOutputAvailable(mCodec, outputBufferId, outputBufferInfo);
+                }
+            }
+        }
+        return 0;
+    }
+
+    private void onOutputAvailable(MediaCodec mediaCodec, int outputBufferId,
+                                   MediaCodec.BufferInfo outputBufferInfo) {
+        if (mSawOutputEOS || outputBufferId < 0) {
+            if (mSawOutputEOS) {
+                Log.i(TAG, "Saw output EOS");
+            }
+            return;
+        }
+        ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferId);
+        if (mOutputStream != null) {
+            try {
+
+                byte[] bytesOutput = new byte[outputBuffer.remaining()];
+                outputBuffer.get(bytesOutput);
+                mOutputStream.write(bytesOutput);
+            } catch (IOException e) {
+                e.printStackTrace();
+                Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+                return;
+            }
+        }
+        mStats.addFrameSize(outputBuffer.remaining());
+        mediaCodec.releaseOutputBuffer(outputBufferId, false);
+        mSawOutputEOS = (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+    }
+
+    private void onInputAvailable(MediaCodec mediaCodec, int inputBufferId) throws IOException {
+        if (mSawOutputEOS || inputBufferId < 0) {
+            if (mSawOutputEOS) {
+                Log.i(TAG, "Saw input EOS");
+            }
+            return;
+        }
+        if (mInputBufferSize < mOffset) {
+            Log.e(TAG, "Out of bound access of input buffer");
+            mSignalledError = true;
+            return;
+        }
+        ByteBuffer inputBuffer = mCodec.getInputBuffer(inputBufferId);
+        if (inputBuffer == null) {
+            mSignalledError = true;
+            return;
+        }
+        int bufSize = inputBuffer.capacity();
+        int bytesRead = mFrameSize;
+        if (mInputBufferSize - mOffset < mFrameSize) {
+            bytesRead = (int) (mInputBufferSize - mOffset);
+        }
+        if (bufSize < bytesRead) {
+            mSignalledError = true;
+            return;
+        }
+        byte[] inputArray = new byte[bytesRead];
+        mInputStream.read(inputArray, 0, bytesRead);
+        inputBuffer.put(inputArray);
+        int flag = 0;
+        if (mNumInputFrame >= mNumFrames - 1 || bytesRead == 0) {
+            Log.i(TAG, "Sending EOS on input last frame");
+            mSawInputEOS = true;
+            flag = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+        }
+        int presentationTimeUs;
+        if (mMime.startsWith("video/")) {
+            presentationTimeUs = mNumInputFrame * (1000000 / mFrameRate);
+        } else {
+            presentationTimeUs = mNumInputFrame * mFrameSize * 1000000 / mSampleRate;
+        }
+        mediaCodec.queueInputBuffer(inputBufferId, 0, bytesRead, presentationTimeUs, flag);
+        mNumInputFrame++;
+        mOffset += bytesRead;
+    }
+
+    /**
+     * Stops the codec and releases codec resources.
+     */
+    public void deInitEncoder() {
+        long sTime = mStats.getCurTime();
+        if (mCodec != null) {
+            mCodec.stop();
+            mCodec.release();
+            mCodec = null;
+        }
+        long eTime = mStats.getCurTime();
+        mStats.setDeInitTime(mStats.getTimeDiff(sTime, eTime));
+    }
+
+    /**
+     * Prints out the statistics in the information log
+     *
+     * @param inputReference The operation being performed, in this case encode
+     * @param durationUs     Duration of the clip in microseconds
+     */
+    public void dumpStatistics(String inputReference, long durationUs) {
+        String operation = "encode";
+        mStats.dumpStatistics(operation, inputReference, durationUs);
+    }
+
+    /**
+     * Resets the stats
+     */
+    public void resetEncoder() {
+        mOffset = 0;
+        mInputBufferSize = 0;
+        mNumInputFrame = 0;
+        mSawInputEOS = false;
+        mSawOutputEOS = false;
+        mSignalledError = false;
+        mStats.reset();
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
new file mode 100644
index 0000000..459e2a9
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class Extractor {
+    private static final String TAG = "Extractor";
+    private static final int kMaxBufSize = 1024 * 1024 * 16;
+    private MediaExtractor mExtractor;
+    private ByteBuffer mFrameBuffer;
+    private MediaCodec.BufferInfo mBufferInfo;
+    private Stats mStats;
+    private long mDurationUs;
+
+    public Extractor() {
+        mFrameBuffer = ByteBuffer.allocate(kMaxBufSize);
+        mBufferInfo = new MediaCodec.BufferInfo();
+        mStats = new Stats();
+    }
+
+    /**
+     * Creates a Media Extractor and sets data source(FileDescriptor)to use
+     *
+     * @param fileDescriptor FileDescriptor for the file which is to be extracted
+     * @return TrackCount of the sample
+     * @throws IOException If FileDescriptor is null
+     */
+    public int setUpExtractor(FileDescriptor fileDescriptor) throws IOException {
+        long sTime = mStats.getCurTime();
+        mExtractor = new MediaExtractor();
+        mExtractor.setDataSource(fileDescriptor);
+        long eTime = mStats.getCurTime();
+        long timeTaken = mStats.getTimeDiff(sTime, eTime);
+        mStats.setInitTime(timeTaken);
+        return mExtractor.getTrackCount();
+    }
+
+    /**
+     * Returns the track format of the specified index
+     *
+     * @param trackID Index of the track
+     * @return Format of the track
+     */
+    public MediaFormat getFormat(int trackID) { return mExtractor.getTrackFormat(trackID); }
+
+    /**
+     * Returns the extracted buffer for the input clip
+     */
+    public ByteBuffer getFrameBuffer() { return this.mFrameBuffer; }
+
+    /**
+     * Returns the information of buffer related to sample
+     */
+    public MediaCodec.BufferInfo getBufferInfo() { return this.mBufferInfo; }
+
+    /**
+     * Returns the duration of the sample
+     */
+    public long getClipDuration() { return this.mDurationUs; }
+
+    /**
+     * Retrieve the current sample and store it in the byte buffer
+     * Also, sets the information related to extracted sample and store it in buffer info
+     *
+     * @return Sample size of the extracted sample
+     */
+    public int getFrameSample() {
+        int sampleSize = mExtractor.readSampleData(mFrameBuffer, 0);
+        if (sampleSize < 0) {
+            mBufferInfo.flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+            mBufferInfo.size = 0;
+        } else {
+            mBufferInfo.size = sampleSize;
+            mBufferInfo.offset = 0;
+            mBufferInfo.flags = mExtractor.getSampleFlags();
+            mBufferInfo.presentationTimeUs = mExtractor.getSampleTime();
+            mExtractor.advance();
+        }
+        return sampleSize;
+    }
+
+    /**
+     * Setup the track format and get the duration of the sample
+     * Track is selected here for extraction
+     *
+     * @param trackId Track index to be selected
+     * @return 0 for valid track, otherwise -1
+     */
+    public int selectExtractorTrack(int trackId) {
+        MediaFormat trackFormat = mExtractor.getTrackFormat(trackId);
+        mDurationUs = trackFormat.getLong(MediaFormat.KEY_DURATION);
+        if (mDurationUs < 0) {
+            Log.e(TAG, "Invalid Clip");
+            return -1;
+        }
+        mExtractor.selectTrack(trackId);
+        return 0;
+    }
+
+    /**
+     * Unselect the track
+     *
+     * @param trackId Track Index to be unselected
+     */
+    public void unselectExtractorTrack(int trackId) { mExtractor.unselectTrack(trackId); }
+
+    /**
+     * Free up the resources
+     */
+    public void deinitExtractor() {
+        long sTime = mStats.getCurTime();
+        mExtractor.release();
+        long eTime = mStats.getCurTime();
+        long timeTaken = mStats.getTimeDiff(sTime, eTime);
+        mStats.setDeInitTime(timeTaken);
+    }
+
+    /**
+     * Performs extract operation
+     *
+     * @param currentTrack Track index to be extracted
+     * @return Status as 0 if extraction is successful, -1 otherwise
+     */
+    public int extractSample(int currentTrack) {
+        int status;
+        status = selectExtractorTrack(currentTrack);
+        if (status == -1) {
+            Log.e(TAG, "Failed to select track");
+            return -1;
+        }
+        mStats.setStartTime();
+        while (true) {
+            int readSampleSize = getFrameSample();
+            if (readSampleSize <= 0) {
+                break;
+            }
+            mStats.addOutputTime();
+            mStats.addFrameSize(readSampleSize);
+        }
+        unselectExtractorTrack(currentTrack);
+        return 0;
+    }
+
+    /**
+     * Write the benchmark logs for the given input file
+     *
+     * @param inputReference Name of the input file
+     */
+    public void dumpStatistics(String inputReference) {
+        String operation = "extract";
+        mStats.dumpStatistics(operation, inputReference, mDurationUs);
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
new file mode 100644
index 0000000..49eaa1c
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+public class Muxer {
+    private Stats mStats;
+    private MediaMuxer mMuxer;
+
+    /**
+     * Creates a Media Muxer for the specified path
+     *
+     * @param context      App context to specify the output file path
+     * @param outputFormat Format of the output media file
+     * @param trackFormat  Format of the current track
+     * @return Returns the track index of the newly added track, -1 otherwise
+     */
+    public int setUpMuxer(Context context, int outputFormat, MediaFormat trackFormat) {
+        try {
+            mStats = new Stats();
+            long sTime = mStats.getCurTime();
+            mMuxer = new MediaMuxer(context.getFilesDir().getPath() + "/mux.out.", outputFormat);
+            int trackIndex = mMuxer.addTrack(trackFormat);
+            mMuxer.start();
+            long eTime = mStats.getCurTime();
+            long timeTaken = mStats.getTimeDiff(sTime, eTime);
+            mStats.setInitTime(timeTaken);
+            return trackIndex;
+        } catch (IllegalArgumentException | IOException e) {
+            e.printStackTrace();
+            return -1;
+        }
+    }
+
+    /**
+     * Performs the Mux operation
+     *
+     * @param trackIndex           Track index of the sample
+     * @param inputExtractedBuffer Buffer containing encoded samples
+     * @param inputBufferInfo      Buffer information related to these samples
+     * @return Returns Status as 0 if write operation is successful, -1 otherwise
+     */
+    public int mux(int trackIndex, ArrayList<ByteBuffer> inputExtractedBuffer,
+                   ArrayList<MediaCodec.BufferInfo> inputBufferInfo) {
+        mStats.setStartTime();
+        for (int sampleCount = 0; sampleCount < inputExtractedBuffer.size(); sampleCount++) {
+            try {
+                mMuxer.writeSampleData(trackIndex, inputExtractedBuffer.get(sampleCount),
+                        inputBufferInfo.get(sampleCount));
+                mStats.addOutputTime();
+                mStats.addFrameSize(inputBufferInfo.get(sampleCount).size);
+            } catch (IllegalArgumentException | IllegalStateException e) {
+                e.printStackTrace();
+                return -1;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Stops the muxer and free up the resources
+     */
+    public void deInitMuxer() {
+        long sTime = mStats.getCurTime();
+        mMuxer.stop();
+        mMuxer.release();
+        long eTime = mStats.getCurTime();
+        long timeTaken = mStats.getTimeDiff(sTime, eTime);
+        mStats.setDeInitTime(timeTaken);
+    }
+
+    /**
+     * Resets the stats
+     */
+    public void resetMuxer() {
+        mStats.reset();
+    }
+
+    /**
+     * Write the benchmark logs for the given input file
+     *
+     * @param inputReference Name of the input file
+     * @param clipDuration   Duration of the given inputReference file
+     */
+    public void dumpStatistics(String inputReference, long clipDuration) {
+        String operation = "mux";
+        mStats.dumpStatistics(operation, inputReference, clipDuration);
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
new file mode 100644
index 0000000..18ab5be
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * Measures Performance.
+ */
+public class Stats {
+    private static final String TAG = "Stats";
+    private long mInitTimeNs;
+    private long mDeInitTimeNs;
+    private long mStartTimeNs;
+    private ArrayList<Integer> mFrameSizes;
+    private ArrayList<Long> mInputTimer;
+    private ArrayList<Long> mOutputTimer;
+
+    public Stats() {
+        mFrameSizes = new ArrayList<>();
+        mInputTimer = new ArrayList<>();
+        mOutputTimer = new ArrayList<>();
+        mInitTimeNs = 0;
+        mDeInitTimeNs = 0;
+    }
+
+    public long getCurTime() { return System.nanoTime(); }
+
+    public void setInitTime(long initTime) { mInitTimeNs = initTime; }
+
+    public void setDeInitTime(long deInitTime) { mDeInitTimeNs = deInitTime; }
+
+    public void setStartTime() { mStartTimeNs = System.nanoTime(); }
+
+    public void addFrameSize(int size) { mFrameSizes.add(size); }
+
+    public void addInputTime() { mInputTimer.add(System.nanoTime()); }
+
+    public void addOutputTime() { mOutputTimer.add(System.nanoTime()); }
+
+    public void reset() {
+        if (mFrameSizes.size() != 0) {
+            mFrameSizes.clear();
+        }
+
+        if (mInputTimer.size() != 0) {
+            mInputTimer.clear();
+        }
+
+        if (mOutputTimer.size() != 0) {
+            mOutputTimer.clear();
+        }
+    }
+
+    public long getInitTime() { return mInitTimeNs; }
+
+    public long getDeInitTime() { return mDeInitTimeNs; }
+
+    public long getTimeDiff(long sTime, long eTime) { return (eTime - sTime); }
+
+    private long getTotalTime() {
+        if (mOutputTimer.size() == 0) {
+            return -1;
+        }
+        long lastTime = mOutputTimer.get(mOutputTimer.size() - 1);
+        return lastTime - mStartTimeNs;
+    }
+
+    private long getTotalSize() {
+        long totalSize = 0;
+        for (long size : mFrameSizes) {
+            totalSize += size;
+        }
+        return totalSize;
+    }
+
+    /**
+     * Dumps the stats of the operation for a given input media.
+     * <p>
+     * \param operation      describes the operation performed on the input media
+     * (i.e. extract/mux/decode/encode)
+     * \param inputReference input media
+     * \param durationUs    is a duration of the input media in microseconds.
+     */
+    public void dumpStatistics(String operation, String inputReference, long durationUs) {
+        if (mOutputTimer.size() == 0) {
+            Log.e(TAG, "No output produced");
+            return;
+        }
+        long totalTimeTakenNs = getTotalTime();
+        long timeTakenPerSec = (totalTimeTakenNs * 1000000) / durationUs;
+        long timeToFirstFrameNs = mOutputTimer.get(0) - mStartTimeNs;
+        long size = getTotalSize();
+        // get min and max output intervals.
+        long intervalNs;
+        long minTimeTakenNs = Long.MAX_VALUE;
+        long maxTimeTakenNs = 0;
+        long prevIntervalNs = mStartTimeNs;
+        for (int idx = 0; idx < mOutputTimer.size() - 1; idx++) {
+            intervalNs = mOutputTimer.get(idx) - prevIntervalNs;
+            prevIntervalNs = mOutputTimer.get(idx);
+            if (minTimeTakenNs > intervalNs) {
+                minTimeTakenNs = intervalNs;
+            } else if (maxTimeTakenNs < intervalNs) {
+                maxTimeTakenNs = intervalNs;
+            }
+        }
+        // Print the Stats
+        Log.i(TAG, "Input Reference : " + inputReference);
+        Log.i(TAG, "Setup Time in nano sec : " + mInitTimeNs);
+        Log.i(TAG, "Average Time in nano sec : " + totalTimeTakenNs / mOutputTimer.size());
+        Log.i(TAG, "Time to first frame in nano sec : " + timeToFirstFrameNs);
+        Log.i(TAG, "Time taken (in nano sec) to " + operation + " 1 sec of content : " +
+                timeTakenPerSec);
+        Log.i(TAG, "Total bytes " + operation + "ed : " + size);
+        Log.i(TAG, "Number of bytes " + operation + "ed per second : " +
+                (size * 1000000000) / totalTimeTakenNs);
+        Log.i(TAG, "Minimum Time in nano sec : " + minTimeTakenNs);
+        Log.i(TAG, "Maximum Time in nano sec : " + maxTimeTakenNs);
+        Log.i(TAG, "Destroy Time in nano sec : " + mDeInitTimeNs);
+    }
+}
\ No newline at end of file
diff --git a/media/tests/benchmark/README.md b/media/tests/benchmark/README.md
index 8db3fd3..487ddb8 100644
--- a/media/tests/benchmark/README.md
+++ b/media/tests/benchmark/README.md
@@ -1,10 +1,19 @@
 # Benchmark tests
 
+Benchmark app analyses the time taken by MediaCodec, MediaExtractor and MediaMuxer for given set of inputs. It is used to benchmark these modules on android devices.
+Benchmark results are emitted to logcat.
+
+This page describes steps to run the NDK and SDK layer test.
+
 Run the following steps to build the test suite:
 ```
 mmm frameworks/av/media/tests/benchmark/
 ```
 
+# NDK
+
+To run the test suite for measuring performance of the native layer, follow the following steps:
+
 The binaries will be created in the following path : ${OUT}/data/nativetest64/
 
 adb push $(OUT)/data/nativetest64/* /data/local/tmp/
@@ -13,20 +22,25 @@
 
 To run the binary, follow the commands mentioned below under each module.
 
-The resource files for the tests are taken from [here](https://drive.google.com/open?id=1ghMr17BBJ7n0pqbm7oREiTN_MNemJUqy)
+The resource file for the tests is taken from [here](https://drive.google.com/open?id=1ghMr17BBJ7n0pqbm7oREiTN_MNemJUqy)
+
+Download the MediaBenchmark.zip file, unzip and push it to /data/local/tmp/ on the device.
+
+```
+unzip MediaBenchmark.zip
+adb push MediaBenchmark /data/local/tmp
+```
 
 ## Extractor
 
 The test extracts elementary stream and benchmarks the extractors available in NDK.
 
-Push the resource files to /sdcard/res on the device.
-
-You can use a different location, but you have to modify the rest of the instructions to replace /sdcard/res with wherever you chose to put the files.
+The resource files are assumed to be at /data/local/tmp/MediaBenchmark/res/. You can use a different location, but you have to modify the rest of the instructions to replace /data/local/tmp/MediaBenchmark/res/ with wherever you chose to put the files.
 
 The path to these files on the device is required to be given for the test.
 
 ```
-adb shell /data/local/tmp/extractorTest -P /sdcard/res/
+adb shell /data/local/tmp/extractorTest -P /data/local/tmp/MediaBenchmark/res/
 ```
 
 ## Decoder
@@ -36,7 +50,7 @@
 Setup steps are same as extractor.
 
 ```
-adb shell /data/local/tmp/decoderTest -P /sdcard/res/
+adb shell /data/local/tmp/decoderTest -P /data/local/tmp/MediaBenchmark/res/
 ```
 
 ## Muxer
@@ -46,7 +60,7 @@
 Setup steps are same as extractor.
 
 ```
-adb shell /data/local/tmp/muxerTest -P /sdcard/res/
+adb shell /data/local/tmp/muxerTest -P /data/local/tmp/MediaBenchmark/res/
 ```
 
 ## Encoder
@@ -56,5 +70,53 @@
 Setup steps are same as extractor.
 
 ```
-adb shell /data/local/tmp/encoderTest -P /sdcard/res/
+adb shell /data/local/tmp/encoderTest -P /data/local/tmp/MediaBenchmark/res/
+```
+
+# SDK
+
+To run the test suite for measuring performance of the SDK APIs, follow the following steps:
+
+The apk will be created at the following path:
+${OUT}/testcases/MediaBenchmarkApp/arm64/
+
+To get the resorce files for the test follow instructions given in [NDK](#NDK)
+
+For installing the apk, run the command:
+```
+adb install -f -r ${OUT}/testcases/MediaBenchmarkApp/arm64/MediaBenchmarkApp.apk
+```
+
+For running all the tests, run the command:
+```
+adb shell am instrument -w -r -e package com.android.media.benchmark.tests com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Extractor
+
+The test extracts elementary stream and benchmarks the extractors available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.ExtractorTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Decoder
+
+The test decodes input stream and benchmarks the decoders available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.DecoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Muxer
+
+The test muxes elementary stream and benchmarks different writers available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.MuxerTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Encoder
+
+The test encodes input stream and benchmarks the encoders available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.EncoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+
 ```
diff --git a/media/tests/benchmark/src/native/common/Android.bp b/media/tests/benchmark/src/native/common/Android.bp
index 527f588..1da0102 100644
--- a/media/tests/benchmark/src/native/common/Android.bp
+++ b/media/tests/benchmark/src/native/common/Android.bp
@@ -15,10 +15,10 @@
  */
 
 cc_library_static {
-    name: "libbenchmark_common",
+    name: "libmediabenchmark_common",
     defaults: [
-        "libbenchmark-defaults",
-        "libbenchmark_soft_sanitize_all-defaults",
+        "libmediabenchmark-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
     ],
 
     srcs: [
@@ -32,23 +32,19 @@
 }
 
 cc_defaults {
-    name: "libbenchmark_common-defaults",
+    name: "libmediabenchmark_common-defaults",
 
     defaults: [
-        "libbenchmark-defaults",
+        "libmediabenchmark-defaults",
     ],
 
     static_libs: [
-        "libbenchmark_common",
+        "libmediabenchmark_common",
     ],
 }
 
 cc_defaults {
-    name: "libbenchmark-defaults",
-
-    header_libs: [
-        "media_ndk_headers",
-    ],
+    name: "libmediabenchmark-defaults",
 
     shared_libs: [
         "libmediandk",
@@ -65,7 +61,7 @@
 // public dependency for native implementation
 // to be used by code under media/benchmark/* only
 cc_defaults {
-    name: "libbenchmark_soft_sanitize_all-defaults",
+    name: "libmediabenchmark_soft_sanitize_all-defaults",
 
     sanitize: {
         misc_undefined: [
@@ -73,6 +69,5 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        address: true,
     }
 }
diff --git a/media/tests/benchmark/src/native/decoder/Android.bp b/media/tests/benchmark/src/native/decoder/Android.bp
index f2d3db5..b6286d4 100644
--- a/media/tests/benchmark/src/native/decoder/Android.bp
+++ b/media/tests/benchmark/src/native/decoder/Android.bp
@@ -15,15 +15,15 @@
  */
 
 cc_library_static {
-    name: "libbenchmark_decoder",
+    name: "libmediabenchmark_decoder",
     defaults: [
-        "libbenchmark_common-defaults",
-        "libbenchmark_soft_sanitize_all-defaults",
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
     ],
 
     srcs: ["Decoder.cpp"],
 
-    static_libs: ["libbenchmark_extractor"],
+    static_libs: ["libmediabenchmark_extractor"],
 
     export_include_dirs: ["."],
 
diff --git a/media/tests/benchmark/src/native/encoder/Android.bp b/media/tests/benchmark/src/native/encoder/Android.bp
index c14c319..239f378 100644
--- a/media/tests/benchmark/src/native/encoder/Android.bp
+++ b/media/tests/benchmark/src/native/encoder/Android.bp
@@ -15,16 +15,16 @@
  */
 
 cc_library_static {
-    name: "libbenchmark_encoder",
+    name: "libmediabenchmark_encoder",
     defaults: [
-        "libbenchmark_common-defaults",
-        "libbenchmark_soft_sanitize_all-defaults",
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
     ],
 
     srcs: ["Encoder.cpp"],
 
-    static_libs: ["libbenchmark_extractor",
-                  "libbenchmark_decoder",
+    static_libs: ["libmediabenchmark_extractor",
+                  "libmediabenchmark_decoder",
     ],
 
     export_include_dirs: ["."],
diff --git a/media/tests/benchmark/src/native/extractor/Android.bp b/media/tests/benchmark/src/native/extractor/Android.bp
index 2fbe4e8..dfd0d49 100644
--- a/media/tests/benchmark/src/native/extractor/Android.bp
+++ b/media/tests/benchmark/src/native/extractor/Android.bp
@@ -15,10 +15,10 @@
  */
 
 cc_library_static {
-    name: "libbenchmark_extractor",
+    name: "libmediabenchmark_extractor",
     defaults: [
-        "libbenchmark_common-defaults",
-        "libbenchmark_soft_sanitize_all-defaults",
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
     ],
 
     srcs: ["Extractor.cpp"],
diff --git a/media/tests/benchmark/src/native/muxer/Android.bp b/media/tests/benchmark/src/native/muxer/Android.bp
index 6ef2a2e..f669d4a 100644
--- a/media/tests/benchmark/src/native/muxer/Android.bp
+++ b/media/tests/benchmark/src/native/muxer/Android.bp
@@ -15,15 +15,15 @@
  */
 
 cc_library_static {
-    name: "libbenchmark_muxer",
+    name: "libmediabenchmark_muxer",
     defaults: [
-        "libbenchmark_common-defaults",
-        "libbenchmark_soft_sanitize_all-defaults",
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
     ],
 
     srcs: ["Muxer.cpp"],
 
-    static_libs: ["libbenchmark_extractor"],
+    static_libs: ["libmediabenchmark_extractor"],
 
     export_include_dirs: ["."],
 
diff --git a/media/tests/benchmark/tests/Android.bp b/media/tests/benchmark/tests/Android.bp
index fc21ef7..24fd68c 100644
--- a/media/tests/benchmark/tests/Android.bp
+++ b/media/tests/benchmark/tests/Android.bp
@@ -18,28 +18,28 @@
     name: "extractorTest",
     gtest: true,
     defaults: [
-        "libbenchmark_common-defaults",
-        "libbenchmark_soft_sanitize_all-defaults",
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
     ],
 
     srcs: ["ExtractorTest.cpp"],
 
-    static_libs: ["libbenchmark_extractor"]
+    static_libs: ["libmediabenchmark_extractor"]
 }
 
 cc_test {
     name: "decoderTest",
     gtest: true,
     defaults: [
-        "libbenchmark_common-defaults",
-        "libbenchmark_soft_sanitize_all-defaults",
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
     ],
 
     srcs: ["DecoderTest.cpp"],
 
     static_libs: [
-        "libbenchmark_extractor",
-        "libbenchmark_decoder",
+        "libmediabenchmark_extractor",
+        "libmediabenchmark_decoder",
     ],
 }
 
@@ -47,15 +47,15 @@
     name: "muxerTest",
     gtest: true,
     defaults: [
-        "libbenchmark_common-defaults",
-        "libbenchmark_soft_sanitize_all-defaults",
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
     ],
 
     srcs: ["MuxerTest.cpp"],
 
     static_libs: [
-        "libbenchmark_extractor",
-        "libbenchmark_muxer",
+        "libmediabenchmark_extractor",
+        "libmediabenchmark_muxer",
     ],
 }
 
@@ -63,15 +63,15 @@
     name: "encoderTest",
     gtest: true,
     defaults: [
-        "libbenchmark_common-defaults",
-        "libbenchmark_soft_sanitize_all-defaults",
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
     ],
 
     srcs: ["EncoderTest.cpp"],
 
     static_libs: [
-        "libbenchmark_extractor",
-        "libbenchmark_decoder",
-        "libbenchmark_encoder",
+        "libmediabenchmark_extractor",
+        "libmediabenchmark_decoder",
+        "libmediabenchmark_encoder",
     ],
 }
diff --git a/media/tests/benchmark/tests/DecoderTest.cpp b/media/tests/benchmark/tests/DecoderTest.cpp
index 6cb42d6..242178f 100644
--- a/media/tests/benchmark/tests/DecoderTest.cpp
+++ b/media/tests/benchmark/tests/DecoderTest.cpp
@@ -72,24 +72,7 @@
         vector<AMediaCodecBufferInfo> frameInfo;
         AMediaCodecBufferInfo info;
         uint32_t inputBufferOffset = 0;
-        int32_t idx = 0;
 
-        // Get CSD data
-        while (1) {
-            void *csdBuffer = extractor->getCSDSample(info, idx);
-            if (!csdBuffer || !info.size) break;
-
-            // copy the meta data and buffer to be passed to decoder
-            if (inputBufferOffset + info.size > kMaxBufferSize) {
-                cout << "[   WARN   ] Test Skipped. Memory allocated not sufficient\n";
-                free(inputBuffer);
-                return;
-            }
-            memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
-            frameInfo.push_back(info);
-            inputBufferOffset += info.size;
-            idx++;
-        }
         // Get frame data
         while (1) {
             status = extractor->getFrameSample(info);
@@ -135,6 +118,7 @@
                           make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", false),
                           make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", false),
                           make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "", false),
+                          make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", false),
                           make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", false)));
 
 INSTANTIATE_TEST_SUITE_P(
@@ -144,6 +128,7 @@
                           make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", true),
                           make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", true),
                           make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "", true),
+                          make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", true),
                           make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", true)));
 
 INSTANTIATE_TEST_SUITE_P(VideDecoderSyncTest, DecoderTest,
diff --git a/media/tests/benchmark/tests/EncoderTest.cpp b/media/tests/benchmark/tests/EncoderTest.cpp
index 574083d..9f42c64 100644
--- a/media/tests/benchmark/tests/EncoderTest.cpp
+++ b/media/tests/benchmark/tests/EncoderTest.cpp
@@ -72,24 +72,6 @@
         vector<AMediaCodecBufferInfo> frameInfo;
         AMediaCodecBufferInfo info;
         uint32_t inputBufferOffset = 0;
-        int32_t idx = 0;
-
-        // Get CSD data
-        while (1) {
-            void *csdBuffer = extractor->getCSDSample(info, idx);
-            if (!csdBuffer || !info.size) break;
-
-            // copy the meta data and buffer to be passed to decoder
-            if (inputBufferOffset + info.size > kMaxBufferSize) {
-                cout << "[   WARN   ] Test Skipped. Memory allocated not sufficient\n";
-                free(inputBuffer);
-                return;
-            }
-            memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
-            frameInfo.push_back(info);
-            inputBufferOffset += info.size;
-            idx++;
-        }
 
         // Get frame data
         while (1) {
@@ -189,6 +171,7 @@
         ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", false),
                           make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", false),
                           make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", false),
+                          make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", false),
                           make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", false)));
 
 INSTANTIATE_TEST_SUITE_P(
@@ -196,6 +179,7 @@
         ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", true),
                           make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", true),
                           make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", true),
+                          make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", true),
                           make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", true)));
 
 INSTANTIATE_TEST_SUITE_P(VideEncoderSyncTest, EncoderTest,
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index 2dbc476..63437da 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -47,6 +47,7 @@
 
     header_libs: [
         "bionic_libc_platform_headers",
+        "libmedia_headers",
     ],
 
     local_include_dirs: ["include"],
diff --git a/media/utils/TimeCheck.cpp b/media/utils/TimeCheck.cpp
index 59cf4ef..265a232 100644
--- a/media/utils/TimeCheck.cpp
+++ b/media/utils/TimeCheck.cpp
@@ -16,8 +16,8 @@
 
 
 #include <utils/Log.h>
-#include <media/TimeCheck.h>
-#include <media/EventLog.h>
+#include <mediautils/TimeCheck.h>
+#include <mediautils/EventLog.h>
 
 namespace android {
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0b745ac..9b0872e 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -810,7 +810,33 @@
                     continue;
                 }
 
-                size_t frameCount = std::lcm(thread->frameCount(), secondaryThread->frameCount());
+                size_t sourceFrameCount = thread->frameCount() * output.sampleRate
+                                          / thread->sampleRate();
+                size_t sinkFrameCount = secondaryThread->frameCount() * output.sampleRate
+                                          / secondaryThread->sampleRate();
+                // If the secondary output has just been opened, the first secondaryThread write
+                // will not block as it will fill the empty startup buffer of the HAL,
+                // so a second sink buffer needs to be ready for the immediate next blocking write.
+                // Additionally, have a margin of one main thread buffer as the scheduling jitter
+                // can reorder the writes (eg if thread A&B have the same write intervale,
+                // the scheduler could schedule AB...BA)
+                size_t frameCountToBeReady = 2 * sinkFrameCount + sourceFrameCount;
+                // Total secondary output buffer must be at least as the read frames plus
+                // the margin of a few buffers on both sides in case the
+                // threads scheduling has some jitter.
+                // That value should not impact latency as the secondary track is started before
+                // its buffer is full, see frameCountToBeReady.
+                size_t frameCount = frameCountToBeReady + 2 * (sourceFrameCount + sinkFrameCount);
+                // The frameCount should also not be smaller than the secondary thread min frame
+                // count
+                size_t minFrameCount = AudioSystem::calculateMinFrameCount(
+                            [&] { Mutex::Autolock _l(secondaryThread->mLock);
+                                  return secondaryThread->latency_l(); }(),
+                            secondaryThread->mNormalFrameCount,
+                            secondaryThread->mSampleRate,
+                            output.sampleRate,
+                            input.speed);
+                frameCount = std::max(frameCount, minFrameCount);
 
                 using namespace std::chrono_literals;
                 auto inChannelMask = audio_channel_mask_out_to_in(input.config.channel_mask);
@@ -843,7 +869,8 @@
                                                                patchRecord->buffer(),
                                                                patchRecord->bufferSize(),
                                                                outputFlags,
-                                                               0ns /* timeout */);
+                                                               0ns /* timeout */,
+                                                               frameCountToBeReady);
                 status = patchTrack->initCheck();
                 if (status != NO_ERROR) {
                     ALOGE("Secondary output patchTrack init failed: %d", status);
@@ -1357,8 +1384,8 @@
         String8(AudioParameter::keyFrameCount),
         String8(AudioParameter::keyInputSource),
         String8(AudioParameter::keyMonoOutput),
-        String8(AudioParameter::keyStreamConnect),
-        String8(AudioParameter::keyStreamDisconnect),
+        String8(AudioParameter::keyDeviceConnect),
+        String8(AudioParameter::keyDeviceDisconnect),
         String8(AudioParameter::keyStreamSupportedFormats),
         String8(AudioParameter::keyStreamSupportedChannels),
         String8(AudioParameter::keyStreamSupportedSamplingRates),
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 72e669a..d639f26 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -547,6 +547,16 @@
         bool        mute;
     };
 
+    // Abstraction for the Audio Source for the RecordThread (HAL or PassthruPatchRecord).
+    struct Source
+    {
+        virtual ~Source() = default;
+        // The following methods have the same signatures as in StreamHalInterface.
+        virtual status_t read(void *buffer, size_t bytes, size_t *read) = 0;
+        virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0;
+        virtual status_t standby() = 0;
+    };
+
     // --- PlaybackThread ---
 #ifdef FLOAT_EFFECT_CHAIN
 #define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
@@ -749,7 +759,7 @@
     // For emphasis, we could also make all pointers to them be "const *",
     // but that would clutter the code unnecessarily.
 
-    struct AudioStreamIn {
+    struct AudioStreamIn : public Source {
         AudioHwDevice* const audioHwDev;
         sp<StreamInHalInterface> stream;
         audio_input_flags_t flags;
@@ -758,6 +768,13 @@
 
         AudioStreamIn(AudioHwDevice *dev, sp<StreamInHalInterface> in, audio_input_flags_t flags) :
             audioHwDev(dev), stream(in), flags(flags) {}
+        status_t read(void *buffer, size_t bytes, size_t *read) override {
+            return stream->read(buffer, bytes, read);
+        }
+        status_t getCapturePosition(int64_t *frames, int64_t *time) override {
+            return stream->getCapturePosition(frames, time);
+        }
+        status_t standby() override { return stream->standby(); }
     };
 
     struct TeePatch {
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 3c4fbba..13152d0 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -24,6 +24,7 @@
 #include "Configuration.h"
 #include <utils/Log.h>
 #include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_dynamicsprocessing.h>
 #include <system/audio_effects/effect_ns.h>
 #include <system/audio_effects/effect_visualizer.h>
 #include <audio_utils/channels.h>
@@ -2569,7 +2570,8 @@
     if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
         (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
          (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
-         (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
+         (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0) ||
+         (memcmp(&desc.type, SL_IID_DYNAMICSPROCESSING, sizeof(effect_uuid_t)) == 0))) {
         return false;
     }
     return true;
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index c5b9953..3eacc8c 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -105,13 +105,8 @@
     return mSQ.poll();
 }
 
-void FastMixer::setNBLogWriter(NBLog::Writer *logWriter)
+void FastMixer::setNBLogWriter(NBLog::Writer *logWriter __unused)
 {
-    // FIXME If mMixer is set or changed prior to this, we don't inform correctly.
-    //       Should cache logWriter and re-apply it at the assignment to mMixer.
-    if (mMixer != NULL) {
-        mMixer->setNBLogWriter(logWriter);
-    }
 }
 
 void FastMixer::onIdle()
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/FastThread.cpp
index 04b32c2..8b7a124 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/FastThread.cpp
@@ -124,7 +124,7 @@
             mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
             tlNBLogWriter = next->mNBLogWriter != NULL ?
                     next->mNBLogWriter : mDummyNBLogWriter.get();
-            setNBLogWriter(tlNBLogWriter); // FastMixer informs its AudioMixer, FastCapture ignores
+            setNBLogWriter(tlNBLogWriter); // This is used for debugging only
 
             // We want to always have a valid reference to the previous (non-idle) state.
             // However, the state queue only guarantees access to current and previous states.
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index edb331d..18cb53b 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -483,19 +483,6 @@
         // Fast mode is not available in this case.
         inputFlags = (audio_input_flags_t) (inputFlags & ~AUDIO_INPUT_FLAG_FAST);
     }
-    sp<RecordThread::PatchRecord> tempRecordTrack = new (std::nothrow) RecordThread::PatchRecord(
-                                             mRecord.thread().get(),
-                                             sampleRate,
-                                             inChannelMask,
-                                             format,
-                                             frameCount,
-                                             NULL,
-                                             (size_t)0 /* bufferSize */,
-                                             inputFlags);
-    status = mRecord.checkTrack(tempRecordTrack.get());
-    if (status != NO_ERROR) {
-        return status;
-    }
 
     audio_output_flags_t outputFlags = mAudioPatch.sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ?
             mAudioPatch.sinks[0].flags.output : AUDIO_OUTPUT_FLAG_NONE;
@@ -512,9 +499,34 @@
         outputFlags = (audio_output_flags_t) (outputFlags & ~AUDIO_OUTPUT_FLAG_FAST);
     }
 
+    sp<RecordThread::PatchRecord> tempRecordTrack;
+    if ((inputFlags & AUDIO_INPUT_FLAG_DIRECT) && (outputFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
+        tempRecordTrack = new RecordThread::PassthruPatchRecord(
+                                                 mRecord.thread().get(),
+                                                 sampleRate,
+                                                 inChannelMask,
+                                                 format,
+                                                 frameCount,
+                                                 inputFlags);
+    } else {
+        tempRecordTrack = new RecordThread::PatchRecord(
+                                                 mRecord.thread().get(),
+                                                 sampleRate,
+                                                 inChannelMask,
+                                                 format,
+                                                 frameCount,
+                                                 nullptr,
+                                                 (size_t)0 /* bufferSize */,
+                                                 inputFlags);
+    }
+    status = mRecord.checkTrack(tempRecordTrack.get());
+    if (status != NO_ERROR) {
+        return status;
+    }
+
     // create a special playback track to render to playback thread.
     // this track is given the same buffer as the PatchRecord buffer
-    sp<PlaybackThread::PatchTrack> tempPatchTrack = new (std::nothrow) PlaybackThread::PatchTrack(
+    sp<PlaybackThread::PatchTrack> tempPatchTrack = new PlaybackThread::PatchTrack(
                                            mPlayback.thread().get(),
                                            streamType,
                                            sampleRate,
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index a093893..1ff03c4 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -74,7 +74,10 @@
                                 uid_t uid,
                                 audio_output_flags_t flags,
                                 track_type type,
-                                audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+                                audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+                                /** default behaviour is to start when there are as many frames
+                                  * ready as possible (aka. Buffer is full). */
+                                size_t frameCountToBeReady = SIZE_MAX);
     virtual             ~Track();
     virtual status_t    initCheck() const;
 
@@ -263,11 +266,11 @@
     };
     sp<AudioVibrationController> mAudioVibrationController;
     sp<os::ExternalVibration>    mExternalVibration;
+    /** How many frames should be in the buffer before the track is considered ready */
+    const size_t        mFrameCountToBeReady;
 
 private:
     void                interceptBuffer(const AudioBufferProvider::Buffer& buffer);
-    /** Write the source data in the buffer provider. @return written frame count. */
-    size_t              writeFrames(AudioBufferProvider* dest, const void* src, size_t frameCount);
     template <class F>
     void                forEachTeePatchTrack(F f) {
         for (auto& tp : mTeePatches) { f(tp.patchTrack); }
@@ -384,9 +387,15 @@
                                    void *buffer,
                                    size_t bufferSize,
                                    audio_output_flags_t flags,
-                                   const Timeout& timeout = {});
+                                   const Timeout& timeout = {},
+                                   size_t frameCountToBeReady = 1 /** Default behaviour is to start
+                                                                    *  as soon as possible to have
+                                                                    *  the lowest possible latency
+                                                                    *  even if it might glitch. */);
     virtual             ~PatchTrack();
 
+            size_t      framesReady() const override;
+
     virtual status_t    start(AudioSystem::sync_event_t event =
                                     AudioSystem::SYNC_EVENT_NONE,
                              audio_session_t triggerSession = AUDIO_SESSION_NONE);
@@ -402,5 +411,4 @@
 
 private:
             void restartIfDisabled();
-
 };  // end of PatchTrack
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 08660dd..da05dac 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -128,6 +128,8 @@
                 const Timeout& timeout = {});
     virtual             ~PatchRecord();
 
+    virtual Source* getSource() { return nullptr; }
+
     // AudioBufferProvider interface
     virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
     virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
@@ -136,4 +138,71 @@
     virtual status_t    obtainBuffer(Proxy::Buffer *buffer,
                                      const struct timespec *timeOut = NULL);
     virtual void        releaseBuffer(Proxy::Buffer *buffer);
+
+    size_t writeFrames(const void* src, size_t frameCount, size_t frameSize) {
+        return writeFrames(this, src, frameCount, frameSize);
+    }
+
+protected:
+    /** Write the source data into the buffer provider. @return written frame count. */
+    static size_t writeFrames(AudioBufferProvider* dest, const void* src,
+            size_t frameCount, size_t frameSize);
+
 };  // end of PatchRecord
+
+class PassthruPatchRecord : public PatchRecord, public Source {
+public:
+    PassthruPatchRecord(RecordThread *recordThread,
+                        uint32_t sampleRate,
+                        audio_channel_mask_t channelMask,
+                        audio_format_t format,
+                        size_t frameCount,
+                        audio_input_flags_t flags);
+
+    Source* getSource() override { return static_cast<Source*>(this); }
+
+    // Source interface
+    status_t read(void *buffer, size_t bytes, size_t *read) override;
+    status_t getCapturePosition(int64_t *frames, int64_t *time) override;
+    status_t standby() override;
+
+    // AudioBufferProvider interface
+    // This interface is used by RecordThread to pass the data obtained
+    // from HAL or other source to the client. PassthruPatchRecord receives
+    // the data in 'obtainBuffer' so these calls are stubbed out.
+    status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
+    void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;
+
+    // PatchProxyBufferProvider interface
+    // This interface is used from DirectOutputThread to acquire data from HAL.
+    bool producesBufferOnDemand() const override { return true; }
+    status_t obtainBuffer(Proxy::Buffer *buffer, const struct timespec *timeOut = nullptr) override;
+    void releaseBuffer(Proxy::Buffer *buffer) override;
+
+private:
+    // This is to use with PatchRecord::writeFrames
+    struct PatchRecordAudioBufferProvider : public AudioBufferProvider {
+        explicit PatchRecordAudioBufferProvider(PassthruPatchRecord& passthru) :
+                mPassthru(passthru) {}
+        status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override {
+            return mPassthru.PatchRecord::getNextBuffer(buffer);
+        }
+        void releaseBuffer(AudioBufferProvider::Buffer* buffer) override {
+            return mPassthru.PatchRecord::releaseBuffer(buffer);
+        }
+    private:
+        PassthruPatchRecord& mPassthru;
+    };
+
+    sp<StreamInHalInterface> obtainStream(sp<ThreadBase>* thread);
+
+    PatchRecordAudioBufferProvider mPatchRecordAudioBufferProvider;
+    std::unique_ptr<void, decltype(free)*> mSinkBuffer;  // frame size aligned continuous buffer
+    std::unique_ptr<void, decltype(free)*> mStubBuffer;  // buffer used for AudioBufferProvider
+    size_t mUnconsumedFrames = 0;
+    std::mutex mReadLock;
+    std::condition_variable mReadCV;
+    size_t mReadBytes = 0; // GUARDED_BY(mReadLock)
+    status_t mReadError = NO_ERROR; // GUARDED_BY(mReadLock)
+    int64_t mLastReadFrames = 0;  // accessed on RecordThread only
+};
diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp
index a44ab2a..c7aba79 100644
--- a/services/audioflinger/SpdifStreamOut.cpp
+++ b/services/audioflinger/SpdifStreamOut.cpp
@@ -59,6 +59,7 @@
     // TODO Move this into the audio_utils as a static method.
     switch(config->format) {
         case AUDIO_FORMAT_E_AC3:
+        case AUDIO_FORMAT_E_AC3_JOC:
             mRateMultiplier = 4;
             break;
         case AUDIO_FORMAT_AC3:
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 2e6037b0..73292d3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2953,9 +2953,11 @@
             ALOG_ASSERT(mCallbackThread != 0);
             mCallbackThread->setWriteBlocked(mWriteAckSequence);
         }
+        ATRACE_BEGIN("write");
         // FIXME We should have an implementation of timestamps for direct output threads.
         // They are used e.g for multichannel PCM playback over HDMI.
         bytesWritten = mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining);
+        ATRACE_END();
 
         if (mUseAsyncWrite &&
                 ((bytesWritten < 0) || (bytesWritten == (ssize_t)mBytesRemaining))) {
@@ -3956,6 +3958,32 @@
     return INVALID_OPERATION;
 }
 
+// For dedicated VoIP outputs, let the HAL apply the stream volume. Track volume is
+// still applied by the mixer.
+// All tracks attached to a mixer with flag VOIP_RX are tied to the same
+// stream type STREAM_VOICE_CALL so this will only change the HAL volume once even
+// if more than one track are active
+status_t AudioFlinger::PlaybackThread::handleVoipVolume_l(float *volume)
+{
+    status_t result = NO_ERROR;
+    if ((mOutput->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) != 0) {
+        if (*volume != mLeftVolFloat) {
+            result = mOutput->stream->setVolume(*volume, *volume);
+            ALOGE_IF(result != OK,
+                     "Error when setting output stream volume: %d", result);
+            if (result == NO_ERROR) {
+                mLeftVolFloat = *volume;
+            }
+        }
+        // if stream volume was successfully sent to the HAL, mLeftVolFloat == v here and we
+        // remove stream volume contribution from software volume.
+        if (mLeftVolFloat == *volume) {
+            *volume = 1.0f;
+        }
+    }
+    return result;
+}
+
 status_t AudioFlinger::MixerThread::createAudioPatch_l(const struct audio_patch *patch,
                                                           audio_patch_handle_t *handle)
 {
@@ -4758,22 +4786,25 @@
                     // no acknowledgement required for newly active tracks
                 }
                 sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
+                float volume;
+                if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute) {
+                    volume = 0.f;
+                } else {
+                    volume = masterVolume * mStreamTypes[track->streamType()].volume;
+                }
+
+                handleVoipVolume_l(&volume);
+
                 // cache the combined master volume and stream type volume for fast mixer; this
                 // lacks any synchronization or barrier so VolumeProvider may read a stale value
                 const float vh = track->getVolumeHandler()->getVolume(
-                        proxy->framesReleased()).first;
-                float volume;
-                if (track->isPlaybackRestricted()) {
-                    volume = 0.f;
-                } else {
-                    volume = masterVolume
-                        * mStreamTypes[track->streamType()].volume
-                        * vh;
-                }
+                    proxy->framesReleased()).first;
+                volume *= vh;
                 track->mCachedVolume = volume;
                 gain_minifloat_packed_t vlr = proxy->getVolumeLR();
                 float vlf = volume * float_from_gain(gain_minifloat_unpack_left(vlr));
                 float vrf = volume * float_from_gain(gain_minifloat_unpack_right(vlr));
+
                 track->setFinalVolume((vlf + vrf) / 2.f);
                 ++fastTracks;
             } else {
@@ -4916,20 +4947,22 @@
             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;
+            float v = masterVolume * mStreamTypes[track->streamType()].volume;
             // Always fetch volumeshaper volume to ensure state is updated.
             const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
             const float vh = track->getVolumeHandler()->getVolume(
                     track->mAudioTrackServerProxy->framesReleased()).first;
 
-            if (track->isPausing() || mStreamTypes[track->streamType()].mute
-                    || track->isPlaybackRestricted()) {
+            if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
+                v = 0;
+            }
+
+            handleVoipVolume_l(&v);
+
+            if (track->isPausing()) {
                 vl = vr = 0;
                 vlf = vrf = vaf = 0.;
-                if (track->isPausing()) {
-                    track->setPaused();
-                }
+                track->setPaused();
             } else {
                 gain_minifloat_packed_t vlr = proxy->getVolumeLR();
                 vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
@@ -4981,25 +5014,6 @@
                 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(trackId, track);
             mAudioMixer->enable(trackId);
@@ -5289,11 +5303,11 @@
         return false;
     }
     // Check validity as we don't call AudioMixer::create() here.
-    if (!AudioMixer::isValidFormat(format)) {
+    if (!mAudioMixer->isValidFormat(format)) {
         ALOGW("%s: invalid format: %#x", __func__, format);
         return false;
     }
-    if (!AudioMixer::isValidChannelMask(channelMask)) {
+    if (!mAudioMixer->isValidChannelMask(channelMask)) {
         ALOGW("%s: invalid channelMask: %#x", __func__, channelMask);
         return false;
     }
@@ -5646,10 +5660,17 @@
             minFrames = 1;
         }
 
-        if ((track->framesReady() >= minFrames) && track->isReady() && !track->isPaused() &&
+        const size_t framesReady = track->framesReady();
+        const int trackId = track->id();
+        if (ATRACE_ENABLED()) {
+            std::string traceName("nRdy");
+            traceName += std::to_string(trackId);
+            ATRACE_INT(traceName.c_str(), framesReady);
+        }
+        if ((framesReady >= minFrames) && track->isReady() && !track->isPaused() &&
                 !track->isStopping_2() && !track->isStopped())
         {
-            ALOGVV("track(%d) s=%08x [OK]", track->id(), cblk->mServer);
+            ALOGVV("track(%d) s=%08x [OK]", trackId, cblk->mServer);
 
             if (track->mFillingUpStatus == Track::FS_FILLED) {
                 track->mFillingUpStatus = Track::FS_ACTIVE;
@@ -5726,7 +5747,7 @@
                 // fill a buffer, then remove it from active list.
                 // Only consider last track started for mixer state control
                 if (--(track->mRetryCount) <= 0) {
-                    ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", track->id());
+                    ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", trackId);
                     tracksToRemove->add(track);
                     // indicate to client process that the track was disabled because of underrun;
                     // it will then automatically call start() when data is available
@@ -5734,7 +5755,7 @@
                 } else if (last) {
                     ALOGW("pause because of UNDERRUN, framesReady = %zu,"
                             "minFrames = %u, mFormat = %#x",
-                            track->framesReady(), minFrames, mFormat);
+                            framesReady, minFrames, mFormat);
                     mixerStatus = MIXER_TRACKS_ENABLED;
                     if (mHwSupportsPause && !mHwPaused && !mStandby) {
                         doHwPause = true;
@@ -6658,6 +6679,7 @@
                                          ) :
     ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady),
     mInput(input),
+    mSource(mInput),
     mActiveTracks(&this->mLocalLog),
     mRsmpInBuffer(NULL),
     // mRsmpInFrames, mRsmpInFramesP2, and mRsmpInFramesOA are set by readInputParameters_l()
@@ -7110,7 +7132,7 @@
         } else {
             ATRACE_BEGIN("read");
             size_t bytesRead;
-            status_t result = mInput->stream->read(
+            status_t result = mSource->read(
                     (uint8_t*)mRsmpInBuffer + rear * mFrameSize, mBufferSize, &bytesRead);
             ATRACE_END();
             if (result < 0) {
@@ -7132,7 +7154,7 @@
             int64_t position, time;
             if (mStandby) {
                 mTimestampVerifier.discontinuity();
-            } else if (mInput->stream->getCapturePosition(&position, &time) == NO_ERROR
+            } else if (mSource->getCapturePosition(&position, &time) == NO_ERROR
                     && time > mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]) {
 
                 mTimestampVerifier.add(position, time, mSampleRate);
@@ -7413,7 +7435,7 @@
             sq->end(false /*didModify*/);
         }
     }
-    status_t result = mInput->stream->standby();
+    status_t result = mSource->standby();
     ALOGE_IF(result != OK, "Error when putting input stream into standby: %d", result);
 
     // If going into standby, flush the pipe source.
@@ -8398,11 +8420,17 @@
 {
     Mutex::Autolock _l(mLock);
     mTracks.add(record);
+    if (record->getSource()) {
+        mSource = record->getSource();
+    }
 }
 
 void AudioFlinger::RecordThread::deletePatchTrack(const sp<PatchRecord>& record)
 {
     Mutex::Autolock _l(mLock);
+    if (mSource == record->getSource()) {
+        mSource = mInput;
+    }
     destroyTrack_l(record);
 }
 
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 336c2b4..acb1370 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -747,6 +747,7 @@
                 // is safe to do so. That will drop the final ref count and destroy the tracks.
     virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove) = 0;
                 void        removeTracks_l(const Vector< sp<Track> >& tracksToRemove);
+                status_t    handleVoipVolume_l(float *volume);
 
     // StreamOutHalInterfaceCallback implementation
     virtual     void        onWriteReady();
@@ -1645,6 +1646,7 @@
             void    checkBtNrec_l();
 
             AudioStreamIn                       *mInput;
+            Source                              *mSource;
             SortedVector < sp<RecordTrack> >    mTracks;
             // mActiveTracks has dual roles:  it indicates the current active track(s), and
             // is used together with mStartStopCond to indicate start()/stop() progress
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 8f720b5..7a3bb0d 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -325,6 +325,7 @@
 
     virtual ~PatchProxyBufferProvider() {}
 
+    virtual bool        producesBufferOnDemand() const = 0;
     virtual status_t    obtainBuffer(Proxy::Buffer* buffer,
                                      const struct timespec *requested = NULL) = 0;
     virtual void        releaseBuffer(Proxy::Buffer* buffer) = 0;
@@ -347,6 +348,8 @@
                             mPeerProxy = nullptr;
                         }
 
+            bool        producesBufferOnDemand() const override { return false; }
+
 protected:
     const sp<ClientProxy>       mProxy;
     sp<RefBase>                 mPeerReferenceHold;   // keeps mPeerProxy alive during access.
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 78db80c..16a8a84 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -18,12 +18,14 @@
 
 #define LOG_TAG "AudioFlinger"
 //#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_AUDIO
 
 #include "Configuration.h"
 #include <linux/futex.h>
 #include <math.h>
 #include <sys/syscall.h>
 #include <utils/Log.h>
+#include <utils/Trace.h>
 
 #include <private/media/AudioTrackShared.h>
 
@@ -511,7 +513,8 @@
             uid_t uid,
             audio_output_flags_t flags,
             track_type type,
-            audio_port_handle_t portId)
+            audio_port_handle_t portId,
+            size_t frameCountToBeReady)
     :   TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
                   (sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
                   (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
@@ -530,6 +533,7 @@
     mVolumeHandler(new media::VolumeHandler(sampleRate)),
     mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(uid, attr, id(), streamType)),
     // mSinkTimestamp
+    mFrameCountToBeReady(frameCountToBeReady),
     mFastIndex(-1),
     mCachedVolume(1.0),
     /* The track might not play immediately after being active, similarly as if its volume was 0.
@@ -820,16 +824,9 @@
     }
     for (auto& teePatch : mTeePatches) {
         RecordThread::PatchRecord* patchRecord = teePatch.patchRecord.get();
-
-        size_t framesWritten = writeFrames(patchRecord, sourceBuffer.i8, frameCount);
-        // On buffer wrap, the buffer frame count will be less than requested,
-        // when this happens a second buffer needs to be used to write the leftover audio
-        size_t framesLeft = frameCount - framesWritten;
-        if (framesWritten != 0 && framesLeft != 0) {
-            framesWritten +=
-                writeFrames(patchRecord, sourceBuffer.i8 + framesWritten * mFrameSize, framesLeft);
-            framesLeft = frameCount - framesWritten;
-        }
+        const size_t framesWritten = patchRecord->writeFrames(
+                sourceBuffer.i8, frameCount, mFrameSize);
+        const size_t framesLeft = frameCount - framesWritten;
         ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
                  "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->mId,
                  framesWritten, frameCount, framesLeft);
@@ -837,30 +834,10 @@
     auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
     using namespace std::chrono_literals;
     // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
-    ALOGD_IF(spent > 200us, "%s: took %lldus to intercept %zu tracks", __func__,
+    ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
              spent.count(), mTeePatches.size());
 }
 
-size_t AudioFlinger::PlaybackThread::Track::writeFrames(AudioBufferProvider* dest,
-                                                        const void* src,
-                                                        size_t frameCount) {
-    AudioBufferProvider::Buffer patchBuffer;
-    patchBuffer.frameCount = frameCount;
-    auto status = dest->getNextBuffer(&patchBuffer);
-    if (status != NO_ERROR) {
-       ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
-             __func__, status, strerror(-status));
-       return 0;
-    }
-    ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
-    memcpy(patchBuffer.raw, src, patchBuffer.frameCount * mFrameSize);
-    auto framesWritten = patchBuffer.frameCount;
-    dest->releaseBuffer(&patchBuffer);
-    return framesWritten;
-}
-
-// releaseBuffer() is not overridden
-
 // ExtendedAudioBufferProvider interface
 
 // framesReady() may return an approximation of the number of frames if called
@@ -910,8 +887,12 @@
         return true;
     }
 
-    if (framesReady() >= mServerProxy->getBufferSizeInFrames() ||
-            (mCblk->mFlags & CBLK_FORCEREADY)) {
+    size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
+    size_t framesToBeReady = std::min(mFrameCountToBeReady, bufferSizeInFrames);
+
+    if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
+        ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
+              __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
         mFillingUpStatus = FS_FILLED;
         android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
         return true;
@@ -1413,6 +1394,7 @@
 
 void AudioFlinger::PlaybackThread::Track::disable()
 {
+    // TODO(b/142394888): the filling status should also be reset to filling
     signalClientFlag(CBLK_DISABLED);
 }
 
@@ -1790,12 +1772,14 @@
                                                      void *buffer,
                                                      size_t bufferSize,
                                                      audio_output_flags_t flags,
-                                                     const Timeout& timeout)
+                                                     const Timeout& timeout,
+                                                     size_t frameCountToBeReady)
     :   Track(playbackThread, NULL, streamType,
               audio_attributes_t{} /* currently unused for patch track */,
               sampleRate, format, channelMask, frameCount,
               buffer, bufferSize, nullptr /* sharedBuffer */,
-              AUDIO_SESSION_NONE, getpid(), AID_AUDIOSERVER, flags, TYPE_PATCH),
+              AUDIO_SESSION_NONE, getpid(), AID_AUDIOSERVER, flags, TYPE_PATCH,
+              AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
         PatchTrackBase(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true),
                        *playbackThread, timeout)
 {
@@ -1810,6 +1794,15 @@
     ALOGV("%s(%d)", __func__, mId);
 }
 
+size_t AudioFlinger::PlaybackThread::PatchTrack::framesReady() const
+{
+    if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
+        return std::numeric_limits<size_t>::max();
+    } else {
+        return Track::framesReady();
+    }
+}
+
 status_t AudioFlinger::PlaybackThread::PatchTrack::start(AudioSystem::sync_event_t event,
                                                          audio_session_t triggerSession)
 {
@@ -1828,9 +1821,19 @@
     ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
     Proxy::Buffer buf;
     buf.mFrameCount = buffer->frameCount;
+    if (ATRACE_ENABLED()) {
+        std::string traceName("PTnReq");
+        traceName += std::to_string(id());
+        ATRACE_INT(traceName.c_str(), buf.mFrameCount);
+    }
     status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
     ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
     buffer->frameCount = buf.mFrameCount;
+    if (ATRACE_ENABLED()) {
+        std::string traceName("PTnObt");
+        traceName += std::to_string(id());
+        ATRACE_INT(traceName.c_str(), buf.mFrameCount);
+    }
     if (buf.mFrameCount == 0) {
         return WOULD_BLOCK;
     }
@@ -1869,7 +1872,6 @@
 {
     mProxy->releaseBuffer(buffer);
     restartIfDisabled();
-    android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
 }
 
 void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()
@@ -2283,6 +2285,39 @@
     ALOGV("%s(%d)", __func__, mId);
 }
 
+static size_t writeFramesHelper(
+        AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
+{
+    AudioBufferProvider::Buffer patchBuffer;
+    patchBuffer.frameCount = frameCount;
+    auto status = dest->getNextBuffer(&patchBuffer);
+    if (status != NO_ERROR) {
+       ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
+             __func__, status, strerror(-status));
+       return 0;
+    }
+    ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
+    memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
+    size_t framesWritten = patchBuffer.frameCount;
+    dest->releaseBuffer(&patchBuffer);
+    return framesWritten;
+}
+
+// static
+size_t AudioFlinger::RecordThread::PatchRecord::writeFrames(
+        AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
+{
+    size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
+    // On buffer wrap, the buffer frame count will be less than requested,
+    // when this happens a second buffer needs to be used to write the leftover audio
+    const size_t framesLeft = frameCount - framesWritten;
+    if (framesWritten != 0 && framesLeft != 0) {
+        framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
+                        framesLeft, frameSize);
+    }
+    return framesWritten;
+}
+
 // AudioBufferProvider interface
 status_t AudioFlinger::RecordThread::PatchRecord::getNextBuffer(
                                                   AudioBufferProvider::Buffer* buffer)
@@ -2294,6 +2329,11 @@
     ALOGV_IF(status != NO_ERROR,
              "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
     buffer->frameCount = buf.mFrameCount;
+    if (ATRACE_ENABLED()) {
+        std::string traceName("PRnObt");
+        traceName += std::to_string(id());
+        ATRACE_INT(traceName.c_str(), buf.mFrameCount);
+    }
     if (buf.mFrameCount == 0) {
         return WOULD_BLOCK;
     }
@@ -2322,6 +2362,180 @@
     mProxy->releaseBuffer(buffer);
 }
 
+#undef LOG_TAG
+#define LOG_TAG "AF::PthrPatchRecord"
+
+static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
+{
+    void *ptr = nullptr;
+    (void)posix_memalign(&ptr, alignment, size);
+    return std::unique_ptr<void, decltype(free)*>(ptr, free);
+}
+
+AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord(
+        RecordThread *recordThread,
+        uint32_t sampleRate,
+        audio_channel_mask_t channelMask,
+        audio_format_t format,
+        size_t frameCount,
+        audio_input_flags_t flags)
+        : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
+                nullptr /*buffer*/, 0 /*bufferSize*/, flags),
+          mPatchRecordAudioBufferProvider(*this),
+          mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
+          mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
+{
+    memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
+}
+
+sp<StreamInHalInterface> AudioFlinger::RecordThread::PassthruPatchRecord::obtainStream(
+        sp<ThreadBase>* thread)
+{
+    *thread = mThread.promote();
+    if (!*thread) return nullptr;
+    RecordThread *recordThread = static_cast<RecordThread*>((*thread).get());
+    Mutex::Autolock _l(recordThread->mLock);
+    return recordThread->mInput ? recordThread->mInput->stream : nullptr;
+}
+
+// PatchProxyBufferProvider methods are called on DirectOutputThread
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::obtainBuffer(
+        Proxy::Buffer* buffer, const struct timespec* timeOut)
+{
+    if (mUnconsumedFrames) {
+        buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
+        // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
+        return PatchRecord::obtainBuffer(buffer, timeOut);
+    }
+
+    // Otherwise, execute a read from HAL and write into the buffer.
+    nsecs_t startTimeNs = 0;
+    if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
+        // Will need to correct timeOut by elapsed time.
+        startTimeNs = systemTime();
+    }
+    const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
+    buffer->mFrameCount = 0;
+    buffer->mRaw = nullptr;
+    sp<ThreadBase> thread;
+    sp<StreamInHalInterface> stream = obtainStream(&thread);
+    if (!stream) return NO_INIT;  // If there is no stream, RecordThread is not reading.
+
+    status_t result = NO_ERROR;
+    size_t bytesRead = 0;
+    {
+        ATRACE_NAME("read");
+        result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
+        if (result != NO_ERROR) goto stream_error;
+        if (bytesRead == 0) return NO_ERROR;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mReadLock);
+        mReadBytes += bytesRead;
+        mReadError = NO_ERROR;
+    }
+    mReadCV.notify_one();
+    // writeFrames handles wraparound and should write all the provided frames.
+    // If it couldn't, there is something wrong with the client/server buffer of the software patch.
+    buffer->mFrameCount = writeFrames(
+            &mPatchRecordAudioBufferProvider,
+            mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
+    ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
+            "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
+    mUnconsumedFrames = buffer->mFrameCount;
+    struct timespec newTimeOut;
+    if (startTimeNs) {
+        // Correct the timeout by elapsed time.
+        nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
+        if (newTimeOutNs < 0) newTimeOutNs = 0;
+        newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
+        newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
+        timeOut = &newTimeOut;
+    }
+    return PatchRecord::obtainBuffer(buffer, timeOut);
+
+stream_error:
+    stream->standby();
+    {
+        std::lock_guard<std::mutex> lock(mReadLock);
+        mReadError = result;
+    }
+    mReadCV.notify_one();
+    return result;
+}
+
+void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
+{
+    if (buffer->mFrameCount <= mUnconsumedFrames) {
+        mUnconsumedFrames -= buffer->mFrameCount;
+    } else {
+        ALOGW("Write side has consumed more frames than we had: %zu > %zu",
+                buffer->mFrameCount, mUnconsumedFrames);
+        mUnconsumedFrames = 0;
+    }
+    PatchRecord::releaseBuffer(buffer);
+}
+
+// AudioBufferProvider and Source methods are called on RecordThread
+// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
+// and 'releaseBuffer' are stubbed out and ignore their input.
+// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
+// until we copy it.
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::read(
+        void* buffer, size_t bytes, size_t* read)
+{
+    bytes = std::min(bytes, mFrameCount * mFrameSize);
+    {
+        std::unique_lock<std::mutex> lock(mReadLock);
+        mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
+        if (mReadError != NO_ERROR) {
+            mLastReadFrames = 0;
+            return mReadError;
+        }
+        *read = std::min(bytes, mReadBytes);
+        mReadBytes -= *read;
+    }
+    mLastReadFrames = *read / mFrameSize;
+    memset(buffer, 0, *read);
+    return 0;
+}
+
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::getCapturePosition(
+        int64_t* frames, int64_t* time)
+{
+    sp<ThreadBase> thread;
+    sp<StreamInHalInterface> stream = obtainStream(&thread);
+    return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
+}
+
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::standby()
+{
+    // RecordThread issues 'standby' command in two major cases:
+    // 1. Error on read--this case is handled in 'obtainBuffer'.
+    // 2. Track is stopping--as PassthruPatchRecord assumes continuous
+    //    output, this can only happen when the software patch
+    //    is being torn down. In this case, the RecordThread
+    //    will terminate and close the HAL stream.
+    return 0;
+}
+
+// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::getNextBuffer(
+        AudioBufferProvider::Buffer* buffer)
+{
+    buffer->frameCount = mLastReadFrames;
+    buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
+    return NO_ERROR;
+}
+
+void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(
+        AudioBufferProvider::Buffer* buffer)
+{
+    buffer->frameCount = 0;
+    buffer->raw = nullptr;
+}
+
 // ----------------------------------------------------------------------------
 #undef LOG_TAG
 #define LOG_TAG "AF::MmapTrack"
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 2264d8f..0776a8d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -40,7 +40,8 @@
                       DeviceVector &availableOutputDevices,
                       DeviceVector &availableInputDevices,
                       sp<DeviceDescriptor> &defaultOutputDevice)
-        : mHwModules(hwModules),
+        : mEngineLibraryNameSuffix(kDefaultEngineLibraryNameSuffix),
+          mHwModules(hwModules),
           mAvailableOutputDevices(availableOutputDevices),
           mAvailableInputDevices(availableInputDevices),
           mDefaultOutputDevice(defaultOutputDevice),
@@ -55,6 +56,14 @@
         mSource = file;
     }
 
+    const std::string& getEngineLibraryNameSuffix() const {
+        return mEngineLibraryNameSuffix;
+    }
+
+    void setEngineLibraryNameSuffix(const std::string& suffix) {
+        mEngineLibraryNameSuffix = suffix;
+    }
+
     void setHwModules(const HwModuleCollection &hwModules)
     {
         mHwModules = hwModules;
@@ -108,6 +117,7 @@
     void setDefault(void)
     {
         mSource = "AudioPolicyConfig::setDefault";
+        mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
         mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
         mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic());
         sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
@@ -167,7 +177,10 @@
     }
 
 private:
+    static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
+
     std::string mSource;
+    std::string mEngineLibraryNameSuffix;
     HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
     DeviceVector &mAvailableOutputDevices;
     DeviceVector &mAvailableInputDevices;
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 96a8337..1f9b725 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -333,9 +333,10 @@
             if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
                 moduleDevice->setEncodedFormat(encodedFormat);
             }
-            moduleDevice->setAddress(devAddress);
             if (allowToCreate) {
                 moduleDevice->attach(hwModule);
+                moduleDevice->setAddress(devAddress);
+                moduleDevice->setName(String8(name));
             }
             return moduleDevice;
         }
diff --git a/services/audiopolicy/config/Android.bp b/services/audiopolicy/config/Android.bp
new file mode 100644
index 0000000..4b5e788
--- /dev/null
+++ b/services/audiopolicy/config/Android.bp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+soong_namespace {
+}
+
+prebuilt_etc {
+    name: "a2dp_in_audio_policy_configuration.xml",
+    vendor: true,
+    src: ":a2dp_in_audio_policy_configuration",
+}
+prebuilt_etc {
+    name: "a2dp_audio_policy_configuration.xml",
+    vendor: true,
+    src: ":a2dp_audio_policy_configuration",
+}
+prebuilt_etc {
+    name: "audio_policy_configuration.xml",
+    vendor: true,
+    src: ":audio_policy_configuration_generic",
+}
+prebuilt_etc {
+    name: "r_submix_audio_policy_configuration.xml",
+    vendor: true,
+    src: ":r_submix_audio_policy_configuration",
+}
+prebuilt_etc {
+    name: "audio_policy_volumes.xml",
+    vendor: true,
+    src: ":audio_policy_volumes",
+}
+prebuilt_etc {
+    name: "default_volume_tables.xml",
+    vendor: true,
+    src: ":default_volume_tables",
+}
+prebuilt_etc {
+    name: "surround_sound_configuration_5_0.xml",
+    vendor: true,
+    src: ":surround_sound_configuration_5_0",
+}
+prebuilt_etc {
+    name: "usb_audio_policy_configuration.xml",
+    vendor: true,
+    src: ":usb_audio_policy_configuration",
+}
+prebuilt_etc {
+    name: "primary_audio_policy_configuration.xml",
+    src: ":primary_audio_policy_configuration",
+    vendor: true,
+}
+
+filegroup {
+    name: "a2dp_in_audio_policy_configuration",
+    srcs: ["a2dp_in_audio_policy_configuration.xml"],
+}
+filegroup {
+    name: "a2dp_audio_policy_configuration",
+    srcs: ["a2dp_audio_policy_configuration.xml"],
+}
+filegroup {
+    name: "primary_audio_policy_configuration",
+    srcs: ["primary_audio_policy_configuration.xml"],
+}
+filegroup {
+    name: "surround_sound_configuration_5_0",
+    srcs: ["surround_sound_configuration_5_0.xml"],
+}
+filegroup {
+    name: "default_volume_tables",
+    srcs: ["default_volume_tables.xml"],
+}
+filegroup {
+    name: "audio_policy_volumes",
+    srcs: ["audio_policy_volumes.xml"],
+}
+filegroup {
+    name: "audio_policy_configuration_generic",
+    srcs: ["audio_policy_configuration_generic.xml"],
+}
+filegroup {
+    name: "usb_audio_policy_configuration",
+    srcs: ["usb_audio_policy_configuration.xml"],
+}
+filegroup {
+    name: "r_submix_audio_policy_configuration",
+    srcs: ["r_submix_audio_policy_configuration.xml"],
+}
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index cedc78f..fca9a60 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -17,18 +17,18 @@
 #pragma once
 
 #include <EngineConfig.h>
-#include <AudioPolicyManagerInterface.h>
+#include <EngineInterface.h>
 #include <ProductStrategy.h>
 #include <VolumeGroup.h>
 
 namespace android {
 namespace audio_policy {
 
-class EngineBase : public AudioPolicyManagerInterface
+class EngineBase : public EngineInterface
 {
 public:
     ///
-    /// from AudioPolicyManagerInterface
+    /// from EngineInterface
     ///
     android::status_t initCheck() override;
 
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 1a2a198..c538f52 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -19,7 +19,6 @@
 #include "VolumeGroup.h"
 
 #include <system/audio.h>
-#include <AudioPolicyManagerInterface.h>
 #include <utils/RefBase.h>
 #include <HandleGenerator.h>
 #include <string>
@@ -27,6 +26,7 @@
 #include <map>
 #include <utils/Errors.h>
 #include <utils/String8.h>
+#include <media/AudioAttributes.h>
 
 namespace android {
 
diff --git a/services/audiopolicy/engine/common/include/VolumeCurve.h b/services/audiopolicy/engine/common/include/VolumeCurve.h
index 54314e3..d3d0904 100644
--- a/services/audiopolicy/engine/common/include/VolumeCurve.h
+++ b/services/audiopolicy/engine/common/include/VolumeCurve.h
@@ -18,7 +18,6 @@
 
 #include "IVolumeCurves.h"
 #include <policy.h>
-#include <AudioPolicyManagerInterface.h>
 #include <utils/RefBase.h>
 #include <HandleGenerator.h>
 #include <utils/String8.h>
diff --git a/services/audiopolicy/engine/common/include/VolumeGroup.h b/services/audiopolicy/engine/common/include/VolumeGroup.h
index c34b406..5378f64 100644
--- a/services/audiopolicy/engine/common/include/VolumeGroup.h
+++ b/services/audiopolicy/engine/common/include/VolumeGroup.h
@@ -16,7 +16,6 @@
 
 #pragma once
 
-#include <AudioPolicyManagerInterface.h>
 #include <VolumeCurve.h>
 #include <system/audio.h>
 #include <utils/RefBase.h>
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 07a7e65..840eb34 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -39,7 +39,7 @@
 {
     ALOGV("setPhoneState() state %d", state);
 
-    if (state < 0 || state >= AUDIO_MODE_CNT) {
+    if (state < 0 || uint32_t(state) >= AUDIO_MODE_CNT) {
         ALOGW("setPhoneState() invalid state %d", state);
         return BAD_VALUE;
     }
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index f74f190..ac3e462 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -19,6 +19,7 @@
 
 #include "ProductStrategy.h"
 
+#include <media/AudioProductStrategy.h>
 #include <media/TypeConverter.h>
 #include <utils/String8.h>
 #include <cstdint>
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 1ad7739..d47fbd2 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -32,9 +32,9 @@
 #include <istream>
 
 #include <cstdint>
+#include <stdarg.h>
 #include <string>
 
-
 namespace android {
 
 using utilities::convertTo;
@@ -603,7 +603,39 @@
     return NO_ERROR;
 }
 
+namespace {
+
+class XmlErrorHandler {
+public:
+    XmlErrorHandler() {
+        xmlSetGenericErrorFunc(this, &xmlErrorHandler);
+    }
+    XmlErrorHandler(const XmlErrorHandler&) = delete;
+    XmlErrorHandler(XmlErrorHandler&&) = delete;
+    XmlErrorHandler& operator=(const XmlErrorHandler&) = delete;
+    XmlErrorHandler& operator=(XmlErrorHandler&&) = delete;
+    ~XmlErrorHandler() {
+        xmlSetGenericErrorFunc(NULL, NULL);
+        if (!mErrorMessage.empty()) {
+            ALOG(LOG_ERROR, "libxml2", "%s", mErrorMessage.c_str());
+        }
+    }
+    static void xmlErrorHandler(void* ctx, const char* msg, ...) {
+        char buffer[256];
+        va_list args;
+        va_start(args, msg);
+        vsnprintf(buffer, sizeof(buffer), msg, args);
+        va_end(args);
+        static_cast<XmlErrorHandler*>(ctx)->mErrorMessage += buffer;
+    }
+private:
+    std::string mErrorMessage;
+};
+
+}  // namespace
+
 ParsingResult parse(const char* path) {
+    XmlErrorHandler errorHandler;
     xmlDocPtr doc;
     doc = xmlParseFile(path);
     if (doc == NULL) {
@@ -641,6 +673,7 @@
 }
 
 android::status_t parseLegacyVolumeFile(const char* path, VolumeGroups &volumeGroups) {
+    XmlErrorHandler errorHandler;
     xmlDocPtr doc;
     doc = xmlParseFile(path);
     if (doc == NULL) {
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
similarity index 97%
rename from services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
rename to services/audiopolicy/engine/interface/EngineInterface.h
index b7fd031..0c58a7c 100644
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -38,7 +38,7 @@
 /**
  * This interface is dedicated to the policy manager that a Policy Engine shall implement.
  */
-class AudioPolicyManagerInterface
+class EngineInterface
 {
 public:
     /**
@@ -295,7 +295,13 @@
     virtual void dump(String8 *dst) const = 0;
 
 protected:
-    virtual ~AudioPolicyManagerInterface() {}
+    virtual ~EngineInterface() {}
 };
 
+__attribute__((visibility("default")))
+extern "C" EngineInterface* createEngineInstance();
+
+__attribute__((visibility("default")))
+extern "C" void destroyEngineInstance(EngineInterface *engine);
+
 } // namespace android
diff --git a/services/audiopolicy/engineconfigurable/config/Android.bp b/services/audiopolicy/engineconfigurable/config/Android.bp
new file mode 100644
index 0000000..fe3eae0
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Root soong_namespace for common components
+
+prebuilt_etc {
+    name: "audio_policy_engine_criteria.xml",
+    vendor: true,
+    src: ":audio_policy_engine_criteria",
+}
+filegroup {
+    name: "audio_policy_engine_criterion_types_template",
+    srcs: ["example/common/audio_policy_engine_criterion_types.xml.in"],
+}
+filegroup {
+    name: "audio_policy_engine_criteria",
+    srcs: ["example/common/audio_policy_engine_criteria.xml"],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/Android.mk b/services/audiopolicy/engineconfigurable/config/example/Android.mk
deleted file mode 100644
index a0f1a90..0000000
--- a/services/audiopolicy/engineconfigurable/config/example/Android.mk
+++ /dev/null
@@ -1,151 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-ifdef BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-PROVISION_CRITERION_TYPES := $(TOOLS)/provision_criterion_types_from_android_headers.mk
-
-##################################################################
-# CONFIGURATION TOP FILE
-##################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_configuration.xml
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-
-LOCAL_REQUIRED_MODULES := \
-    audio_policy_engine_product_strategies.xml  \
-    audio_policy_engine_stream_volumes.xml \
-    audio_policy_engine_default_stream_volumes.xml \
-    audio_policy_engine_criteria.xml \
-    audio_policy_engine_criterion_types.xml
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_stream_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_default_stream_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
-
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),automotive_configurable caremu_configurable))
-
-##################################################################
-# AUTOMOTIVE CONFIGURATION TOP FILE
-##################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_configuration.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
-
-LOCAL_REQUIRED_MODULES := \
-    audio_policy_engine_product_strategies.xml \
-    audio_policy_engine_criteria.xml \
-    audio_policy_engine_criterion_types.xml \
-    audio_policy_engine_volumes.xml
-
-include $(BUILD_PREBUILT)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),automotive_configurable caremu_configurable))
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := caremu/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := caremu/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_criteria.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := common/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_criterion_types.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_VENDOR_ETC)/primary_audio_policy_configuration.xml
-ANDROID_AUDIO_BASE_HEADER_FILE := system/media/audio/include/system/audio-base.h
-AUDIO_POLICY_CONFIGURATION_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
-CRITERION_TYPES_FILE := $(LOCAL_PATH)/common/$(LOCAL_MODULE).in
-
-include $(PROVISION_CRITERION_TYPES)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
-
-endif #ifdef BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp b/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp
new file mode 100644
index 0000000..f913a14
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Automotive configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "audio_policy_engine_configuration.xml",
+    vendor: true,
+    src: ":audio_policy_engine_configuration",
+    required: [
+        ":audio_policy_engine_criterion_types.xml",
+        ":audio_policy_engine_criteria.xml",
+        ":audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes.xml",
+    ],
+}
+prebuilt_etc {
+    name: "audio_policy_engine_product_strategies.xml",
+    vendor: true,
+    src: "audio_policy_engine_product_strategies.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_volumes.xml",
+    vendor: true,
+    src: ":audio_policy_engine_volumes",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_criterion_types.xml",
+    vendor: true,
+    src: ":audio_policy_engine_criterion_types",
+}
+
+//
+// Generate audio_policy_engine criterion type file => provides device addresses criterion type
+//
+genrule {
+    name: "audio_policy_engine_criterion_types",
+    defaults: ["buildpolicycriteriontypesrule"],
+    srcs: [
+        ":audio_policy_configuration_top_file",
+        ":audio_policy_configuration_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_configuration_files",
+    srcs: [
+        ":r_submix_audio_policy_configuration",
+        ":default_volume_tables",
+        ":audio_policy_volumes",
+        ":surround_sound_configuration_5_0",
+        ":primary_audio_policy_configuration",
+    ],
+}
+filegroup {
+    name : "audio_policy_configuration_top_file",
+    srcs: [":audio_policy_configuration_generic"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration",
+    srcs: ["audio_policy_engine_configuration.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_volumes",
+    srcs: ["audio_policy_engine_volumes.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration_files",
+    srcs: [
+        ":audio_policy_engine_configuration",
+        "audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes",
+        ":audio_policy_engine_criterion_types",
+        ":audio_policy_engine_criteria",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp b/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp
new file mode 100644
index 0000000..fae6b7b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Car Emulator configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/automotive",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "audio_policy_engine_configuration.xml",
+    vendor: true,
+    src: ":audio_policy_engine_configuration",
+    required: [
+        "audio_policy_engine_criterion_types.xml",
+        "audio_policy_engine_criteria.xml",
+        "audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes.xml",
+    ],
+}
+prebuilt_etc {
+    name: "audio_policy_engine_product_strategies.xml",
+    vendor: true,
+    src: "audio_policy_engine_product_strategies.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_criterion_types.xml",
+    vendor: true,
+    src: ":audio_policy_engine_criterion_types",
+}
+
+//
+// Generate audio_policy_engine criterion type file => provides device addresses criterion type
+//
+genrule {
+    name: "audio_policy_engine_criterion_types",
+    defaults: ["buildpolicycriteriontypesrule"],
+    srcs: [
+        ":audio_policy_configuration_top_file",
+        ":audio_policy_configuration_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_configuration_files",
+    srcs: [
+        ":r_submix_audio_policy_configuration",
+        ":default_volume_tables",
+        ":audio_policy_volumes",
+        ":surround_sound_configuration_5_0",
+        ":primary_audio_policy_configuration",
+    ],
+}
+filegroup {
+    name : "audio_policy_configuration_top_file",
+    srcs: [":audio_policy_configuration_generic"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration_files",
+    srcs: [
+        ":audio_policy_engine_configuration",
+        "audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes",
+        ":audio_policy_engine_criterion_types",
+        ":audio_policy_engine_criteria",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp b/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp
new file mode 100644
index 0000000..94d33bd
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Phone configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "audio_policy_engine_configuration.xml",
+    vendor: true,
+    src: ":audio_policy_engine_configuration",
+    required: [
+        ":audio_policy_engine_criterion_types.xml",
+        ":audio_policy_engine_criteria.xml",
+        ":audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes.xml",
+    ],
+}
+prebuilt_etc {
+    name: "audio_policy_engine_product_strategies.xml",
+    vendor: true,
+    src: "audio_policy_engine_product_strategies.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_stream_volumes.xml",
+    vendor: true,
+    src: ":audio_policy_engine_stream_volumes",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_default_stream_volumes.xml",
+    vendor: true,
+    src: ":audio_policy_engine_default_stream_volumes",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_criterion_types.xml",
+    vendor: true,
+    src: ":audio_policy_engine_criterion_types",
+}
+
+//
+// Generate audio_policy_engine criterion type file => provides device addresses criterion type
+//
+genrule {
+    name: "audio_policy_engine_criterion_types",
+    defaults: ["buildpolicycriteriontypesrule"],
+    srcs: [
+        ":audio_policy_configuration_top_file",
+        ":audio_policy_configuration_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_configuration_files",
+    srcs: [
+        ":r_submix_audio_policy_configuration",
+        ":default_volume_tables",
+        ":audio_policy_volumes",
+        ":surround_sound_configuration_5_0",
+        ":primary_audio_policy_configuration",
+    ],
+}
+filegroup {
+    name : "audio_policy_configuration_top_file",
+    srcs: [":audio_policy_configuration_generic"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration",
+    srcs: ["audio_policy_engine_configuration.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_stream_volumes",
+    srcs: ["audio_policy_engine_stream_volumes.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_default_stream_volumes",
+    srcs: ["audio_policy_engine_default_stream_volumes.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration_files",
+    srcs: [
+        ":audio_policy_engine_configuration",
+        "audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_stream_volumes",
+        ":audio_policy_engine_default_stream_volumes",
+        ":audio_policy_engine_criterion_types",
+        ":audio_policy_engine_criteria",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
index efc69da..f52de21 100644
--- a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
+++ b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-class AudioPolicyManagerInterface;
+class EngineInterface;
 class AudioPolicyPluginInterface;
 
 namespace android {
@@ -69,7 +69,7 @@
  * Compile time error will claim if invalid interface is requested.
  */
 template <>
-AudioPolicyManagerInterface *EngineInstance::queryInterface() const;
+EngineInterface *EngineInstance::queryInterface() const;
 
 template <>
 AudioPolicyPluginInterface *EngineInstance::queryInterface() const;
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
new file mode 100644
index 0000000..a0b874a
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Root soong_namespace for common components
+
+prebuilt_etc {
+    name: "PolicyClass.xml",
+    vendor: true,
+    src: ":PolicyClass",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+prebuilt_etc {
+    name: "PolicySubsystem.xml",
+    vendor: true,
+    src: ":PolicySubsystem",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+prebuilt_etc {
+    name: "PolicySubsystem-CommonTypes.xml",
+    vendor: true,
+    src: ":PolicySubsystem-CommonTypes",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+
+filegroup {
+    name: "product_strategies_structure_template",
+    srcs: ["examples/common/Structure/ProductStrategies.xml.in"],
+}
+filegroup {
+    name: "PolicySubsystem",
+    srcs: ["examples/common/Structure/PolicySubsystem.xml"],
+}
+filegroup {
+    name: "PolicySubsystem-no-strategy",
+    srcs: ["examples/common/Structure/PolicySubsystem-no-strategy.xml"],
+}
+filegroup {
+    name: "PolicySubsystem-CommonTypes",
+    srcs: ["examples/common/Structure/PolicySubsystem-CommonTypes.xml"],
+}
+filegroup {
+    name: "PolicyClass",
+    srcs: ["examples/common/Structure/PolicyClass.xml"],
+}
+filegroup {
+    name: "volumes.pfw",
+    srcs: ["examples/Settings/volumes.pfw"],
+}
+filegroup {
+    name: "device_for_input_source.pfw",
+    srcs: ["examples/Settings/device_for_input_source.pfw"],
+}
+filegroup {
+    name: "ParameterFrameworkConfigurationPolicy.userdebug.xml",
+    srcs: ["examples/ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "ParameterFrameworkConfigurationPolicy.user.xml",
+    srcs: ["examples/ParameterFrameworkConfigurationPolicy.user.xml"],
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
deleted file mode 100644
index 19f93b3..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
+++ /dev/null
@@ -1,187 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Engine configurable example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-LOCAL_PATH := $(call my-dir)
-
-ifdef BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable no-output_configurable no-input_configurable))
-
-PFW_CORE := external/parameter-framework
-#@TODO: upstream new domain generator
-#BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
-PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
-
-PROVISION_STRATEGIES_STRUCTURE := $(TOOLS)/provision_strategies_structure.mk
-
-endif
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-######### Policy PFW top level file #########
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ParameterFrameworkConfigurationPolicy.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework
-LOCAL_SRC_FILES := $(LOCAL_MODULE).in
-LOCAL_REQUIRED_MODULES := \
-    PolicySubsystem.xml \
-    PolicyClass.xml
-
-# external/parameter-framework prevents from using debug interface
-AUDIO_PATTERN = @TUNING_ALLOWED@
-ifeq ($(TARGET_BUILD_VARIANT),user)
-AUDIO_VALUE = false
-else
-AUDIO_VALUE = true
-endif
-
-LOCAL_POST_INSTALL_CMD := $(hide) sed -i -e 's|$(AUDIO_PATTERN)|$(AUDIO_VALUE)|g' $(TARGET_OUT_VENDOR_ETC)/$(LOCAL_MODULE_RELATIVE_PATH)/$(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
-
-########## Policy PFW Common Structures #########
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_REQUIRED_MODULES := \
-    PolicySubsystem-CommonTypes.xml \
-    ProductStrategies.xml
-
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem-CommonTypes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicyClass.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ProductStrategies.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-
-AUDIO_POLICY_ENGINE_CONFIGURATION_FILE := \
-    $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_configuration.xml
-STRATEGIES_STRUCTURE_FILE := $(LOCAL_PATH)/common/Structure/$(LOCAL_MODULE).in
-
-include $(PROVISION_STRATEGIES_STRUCTURE)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
-
-########## Policy PFW Example Structures #########
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable no-input_configurable))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_REQUIRED_MODULES := PolicySubsystem-CommonTypes.xml
-
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ParameterFrameworkConfigurationPolicy-no-strategy.xml
-LOCAL_MODULE_STEM := ParameterFrameworkConfigurationPolicy.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework
-LOCAL_SRC_FILES := $(LOCAL_MODULE).in
-LOCAL_REQUIRED_MODULES := \
-    PolicySubsystem.xml \
-    PolicyClass.xml
-AUDIO_VALUE = false
-LOCAL_POST_INSTALL_CMD := $(hide) sed -i -e 's|$(AUDIO_PATTERN)|$(AUDIO_VALUE)|g' $(TARGET_OUT_VENDOR_ETC)/$(LOCAL_MODULE_RELATIVE_PATH)/$(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
-
-endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable no-input_configurable))
-
-######### Policy PFW Settings - No Output #########
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoOutputDevice.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_EDD_FILES := \
-        $(LOCAL_PATH)/SettingsNoOutput/device_for_strategies.pfw \
-        $(LOCAL_PATH)/Settings/device_for_input_source.pfw \
-        $(LOCAL_PATH)/Settings/volumes.pfw        
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-include $(BUILD_PFW_SETTINGS)
-
-endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable)
-######### Policy PFW Settings - No Input #########
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-input_configurable)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoInputDevice.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_EDD_FILES := \
-        $(LOCAL_PATH)/SettingsNoInput/device_for_input_source.pfw \
-        $(LOCAL_PATH)/Settings/volumes.pfw
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-include $(BUILD_PFW_SETTINGS)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-input_configurable)
-#######################################################################
-# Recursive call sub-folder Android.mk
-#######################################################################
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
-endif #ifdef BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION
-
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
new file mode 100644
index 0000000..5078268
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Automotive configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/automotive",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Product Strategies Structure file from template
+//
+prebuilt_etc {
+    name: "ProductStrategies.xml",
+    vendor: true,
+    src: ":buildstrategiesstructure_gen",
+    sub_dir: "parameter-framework/Structure/Policy",
+    required: ["libpolicy-subsystem"],
+}
+genrule {
+    name: "buildstrategiesstructure_gen",
+    defaults: ["buildstrategiesstructurerule"],
+    srcs: [
+        ":audio_policy_engine_configuration_files",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Configurable Domains
+//
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "ProductStrategies.xml",
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        ":device_for_input_source.pfw",
+        ":volumes.pfw",
+        "Settings/device_for_product_strategies.pfw",
+    ],
+}
+// This is for Settings generation, must use socket port, so userdebug version is required
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":PolicySubsystem-CommonTypes",
+        ":buildstrategiesstructure_gen",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk
deleted file mode 100644
index 7304ec2..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Engine configurable example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
-LOCAL_PATH := $(call my-dir)
-
-PFW_CORE := external/parameter-framework
-PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
-
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-
-########## Policy PFW Structures #########
-######### Policy PFW Settings #########
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-
-PFW_EDD_FILES := \
-    $(LOCAL_PATH)/Settings/device_for_product_strategies.pfw \
-    $(LOCAL_PATH)/../Settings/device_for_input_source.pfw \
-    $(LOCAL_PATH)/../Settings/volumes.pfw
-
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-include $(BUILD_PFW_SETTINGS)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
new file mode 100644
index 0000000..0917440
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Car Emulator configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/caremu",
+        "frameworks/av/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Product Strategies Structure file from template
+//
+prebuilt_etc {
+    name: "ProductStrategies.xml",
+    vendor: true,
+    src: ":buildstrategiesstructure_gen",
+    sub_dir: "parameter-framework/Structure/Policy",
+    required: ["libpolicy-subsystem"],
+}
+genrule {
+    name: "buildstrategiesstructure_gen",
+    defaults: ["buildstrategiesstructurerule"],
+    srcs: [
+        ":audio_policy_engine_configuration_files",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Configurable Domains
+//
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "ProductStrategies.xml",
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        ":device_for_input_source.pfw",
+        ":volumes.pfw",
+        "Settings/device_for_product_strategies.pfw",
+    ],
+}
+// This is for Settings generation, must use socket port, so userdebug version is required
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":PolicySubsystem-CommonTypes",
+        ":buildstrategiesstructure_gen",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.mk
deleted file mode 100644
index f5eb7d1..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.mk
+++ /dev/null
@@ -1,46 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Engine configurable example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
-LOCAL_PATH := $(call my-dir)
-
-PFW_CORE := external/parameter-framework
-PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
-
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-
-########## Policy PFW Structures #########
-######### Policy PFW Settings #########
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-
-PFW_EDD_FILES := \
-    $(LOCAL_PATH)/Settings/device_for_product_strategies.pfw \
-    $(LOCAL_PATH)/../Settings/device_for_input_source.pfw \
-    $(LOCAL_PATH)/../Settings/volumes.pfw
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-include $(BUILD_PFW_SETTINGS)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.user.xml
similarity index 81%
copy from services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
copy to services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.user.xml
index 1be67dd..c5960cb 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.user.xml
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    SystemClassName="Policy" ServerPort="unix:///dev/socket/audioserver/policy_debug"
-    TuningAllowed="@TUNING_ALLOWED@">
+    SystemClassName="Policy" TuningAllowed="false">
 
     <SubsystemPlugins>
         <Location Folder="">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.userdebug.xml
similarity index 93%
rename from services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
rename to services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.userdebug.xml
index 1be67dd..1b7d7d8 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.userdebug.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     SystemClassName="Policy" ServerPort="unix:///dev/socket/audioserver/policy_debug"
-    TuningAllowed="@TUNING_ALLOWED@">
+    TuningAllowed="true">
 
     <SubsystemPlugins>
         <Location Folder="">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
new file mode 100644
index 0000000..11e220b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Phone configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/phone",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Product Strategies Structure file from template
+//
+prebuilt_etc {
+    name: "ProductStrategies.xml",
+    vendor: true,
+    src: ":buildstrategiesstructure_gen",
+    sub_dir: "parameter-framework/Structure/Policy",
+    required: ["libpolicy-subsystem"],
+}
+genrule {
+    name: "buildstrategiesstructure_gen",
+    defaults: ["buildstrategiesstructurerule"],
+    srcs: [
+        ":audio_policy_engine_configuration_files",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Configurable Domains
+//
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "ProductStrategies.xml",
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        ":device_for_input_source.pfw",
+        ":volumes.pfw",
+        "Settings/device_for_product_strategy_media.pfw",
+        "Settings/device_for_product_strategy_accessibility.pfw",
+        "Settings/device_for_product_strategy_dtmf.pfw",
+        "Settings/device_for_product_strategy_enforced_audible.pfw",
+        "Settings/device_for_product_strategy_phone.pfw",
+        "Settings/device_for_product_strategy_sonification.pfw",
+        "Settings/device_for_product_strategy_sonification_respectful.pfw",
+        "Settings/device_for_product_strategy_transmitted_through_speaker.pfw",
+        "Settings/device_for_product_strategy_rerouting.pfw",
+        "Settings/device_for_product_strategy_patch.pfw",
+    ],
+}
+// This is for Settings generation, must use socket port, so userdebug version is required
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":PolicySubsystem-CommonTypes",
+        ":buildstrategiesstructure_gen",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk
deleted file mode 100644
index 0b20781..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Engine configurable example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
-
-LOCAL_PATH := $(call my-dir)
-
-PFW_CORE := external/parameter-framework
-PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-########## Policy PFW Structures #########
-######### Policy PFW Settings #########
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-
-PFW_EDD_FILES := \
-        $(LOCAL_PATH)/../Settings/device_for_input_source.pfw \
-        $(LOCAL_PATH)/../Settings/volumes.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_media.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_accessibility.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_dtmf.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_enforced_audible.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_phone.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_sonification.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_sonification_respectful.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_transmitted_through_speaker.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_rerouting.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_patch.pfw
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-include $(BUILD_PFW_SETTINGS)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/device_for_input_source.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/device_for_input_source.pfw
index a990879..9e0957c 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/device_for_input_source.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/device_for_input_source.pfw
@@ -18,7 +18,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/mic/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -36,7 +35,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_downlink/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -58,7 +56,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_call/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -80,7 +77,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_uplink/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -102,7 +98,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -123,7 +118,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_recognition/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -142,7 +136,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_communication/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -160,7 +153,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/remote_submix/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -182,7 +174,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/hotword/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -201,7 +192,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/unprocessed/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -220,7 +210,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/fm_tuner/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -242,7 +231,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 
 	domain: DefaultAndMic
 		conf: A2dp
@@ -255,12 +243,14 @@
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 1
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 
 		conf: Sco
 			AvailableInputDevices Includes BluetoothScoHeadset
@@ -273,12 +263,14 @@
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 1
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 1
+					stub = 0
 
 		conf: WiredHeadset
 			AvailableInputDevices Includes WiredHeadset
@@ -290,12 +282,14 @@
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 1
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 
 		conf: UsbDevice
 			AvailableInputDevices Includes UsbDevice
@@ -307,12 +301,14 @@
 					usb_device = 1
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 0
 					usb_device = 1
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 
 		conf: BuiltinMic
 			AvailableInputDevices Includes BuiltinMic
@@ -324,12 +320,33 @@
 					usb_device = 0
 					builtin_mic = 1
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 1
 					bluetooth_sco_headset = 0
+					stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources
+				component: default/applicable_input_device/mask/
+					bluetooth_a2dp = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					bluetooth_sco_headset = 0
+					stub = 1
+				component: mic/applicable_input_device/mask/
+					bluetooth_a2dp = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					bluetooth_sco_headset = 0
+					stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources
@@ -339,12 +356,14 @@
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 
 	domain: VoiceUplinkAndVoiceDownlinkAndVoiceCall
 		conf: VoiceCall
@@ -354,12 +373,29 @@
 				voice_downlink/applicable_input_device/mask/telephony_rx = 1
 				voice_call/applicable_input_device/mask/telephony_rx = 1
 				voice_uplink/applicable_input_device/mask/telephony_rx = 1
+				voice_downlink/applicable_input_device/mask/stub = 0
+				voice_call/applicable_input_device/mask/stub = 0
+				voice_uplink/applicable_input_device/mask/stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources
+				voice_downlink/applicable_input_device/mask/telephony_rx = 0
+				voice_call/applicable_input_device/mask/telephony_rx = 0
+				voice_uplink/applicable_input_device/mask/telephony_rx = 0
+				voice_downlink/applicable_input_device/mask/stub = 1
+				voice_call/applicable_input_device/mask/stub = 1
+				voice_uplink/applicable_input_device/mask/stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources
 				voice_downlink/applicable_input_device/mask/telephony_rx = 0
 				voice_call/applicable_input_device/mask/telephony_rx = 0
 				voice_uplink/applicable_input_device/mask/telephony_rx = 0
+				voice_downlink/applicable_input_device/mask/stub = 0
+				voice_call/applicable_input_device/mask/stub = 0
+				voice_uplink/applicable_input_device/mask/stub = 0
 
 	domain: Camcorder
 		conf: BackMic
@@ -368,6 +404,7 @@
 			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
 				back_mic = 1
 				builtin_mic = 0
+				stub = 0
 
 		conf: BuiltinMic
 			AvailableInputDevices Includes BuiltinMic
@@ -375,11 +412,21 @@
 			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
 				back_mic = 0
 				builtin_mic = 1
+				stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
+				back_mic = 0
+				builtin_mic = 0
+				stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
 				back_mic = 0
 				builtin_mic = 0
+				stub = 0
 
 	domain: VoiceRecognitionAndUnprocessedAndHotword
 		conf: ScoHeadset
@@ -392,16 +439,19 @@
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 1
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 1
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 
 		conf: WiredHeadset
 			AvailableInputDevices Includes WiredHeadset
@@ -411,17 +461,20 @@
 					bluetooth_sco_headset = 0
 					wired_headset = 1
 					usb_device = 0
+					stub = 0
 					builtin_mic = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 1
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 1
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 
 		conf: UsbDevice
 			AvailableInputDevices Includes UsbDevice
@@ -432,16 +485,19 @@
 					wired_headset = 0
 					usb_device = 1
 					builtin_mic = 0
+					stub = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 1
 					builtin_mic = 0
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 1
 					builtin_mic = 0
+					stub = 0
 
 		conf: BuiltinMic
 			AvailableInputDevices Includes BuiltinMic
@@ -452,17 +508,42 @@
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 1
+					stub = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 1
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 1
+					stub = 0
 
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources
+				component: voice_recognition/applicable_input_device/mask
+					bluetooth_sco_headset = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					stub = 1
+				component: unprocessed/applicable_input_device/mask
+					bluetooth_sco_headset = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					stub = 1
+				component: hotword/applicable_input_device/mask
+					bluetooth_sco_headset = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					stub = 1
 		conf: Default
 			component: /Policy/policy/input_sources
 				component: voice_recognition/applicable_input_device/mask
@@ -470,16 +551,19 @@
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 
 	domain: VoiceCommunication
 		conf: ScoHeadset
@@ -495,6 +579,7 @@
 				usb_device = 0
 				builtin_mic = 0
 				back_mic = 0
+				stub = 0
 
 		conf: WiredHeadset
 			ForceUseForCommunication Is ForceNone
@@ -506,6 +591,7 @@
 				usb_device = 0
 				builtin_mic = 0
 				back_mic = 0
+				stub = 0
 
 		conf: UsbDevice
 			ForceUseForCommunication Is ForceNone
@@ -517,6 +603,7 @@
 				usb_device = 1
 				builtin_mic = 0
 				back_mic = 0
+				stub = 0
 
 		conf: BuiltinMic
 			AvailableInputDevices Includes BuiltinMic
@@ -532,6 +619,7 @@
 				usb_device = 0
 				builtin_mic = 1
 				back_mic = 0
+				stub = 0
 
 		conf: BackMic
 			ForceUseForCommunication Is ForceSpeaker
@@ -543,6 +631,7 @@
 				usb_device = 0
 				builtin_mic = 0
 				back_mic = 1
+				stub = 0
 
 		conf: Default
 			#
@@ -554,6 +643,7 @@
 				usb_device = 0
 				builtin_mic = 1
 				back_mic = 0
+				stub = 0
 
 	domain: RemoteSubmix
 		conf: RemoteSubmix
@@ -561,10 +651,19 @@
 
 			component: /Policy/policy/input_sources/remote_submix/applicable_input_device/mask
 				remote_submix = 1
+				stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources/remote_submix/applicable_input_device/mask
+				remote_submix = 0
+				stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources/remote_submix/applicable_input_device/mask
 				remote_submix = 0
+				stub = 0
 
 	domain: FmTuner
 		conf: FmTuner
@@ -572,8 +671,29 @@
 
 			component: /Policy/policy/input_sources/fm_tuner/applicable_input_device/mask
 				fm_tuner = 1
+				stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources/fm_tuner/applicable_input_device/mask
+				fm_tuner = 0
+				stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources/fm_tuner/applicable_input_device/mask
 				fm_tuner = 0
+				stub = 0
+
+	domain: Voice
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			/Policy/policy/input_sources/echo_reference/applicable_input_device/mask/stub = 1
+			/Policy/policy/input_sources/voice_performance/applicable_input_device/mask/stub = 1
+
+		conf: Default
+			/Policy/policy/input_sources/echo_reference/applicable_input_device/mask/stub = 0
+			/Policy/policy/input_sources/voice_performance/applicable_input_device/mask/stub = 0
+
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
new file mode 100644
index 0000000..ffd494e
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP No Input configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/phone",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":PolicySubsystem-CommonTypes",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        "device_for_input_source.pfw",
+        ":volumes.pfw",
+    ],
+}
+prebuilt_etc {
+    name: "PolicySubsystem.xml",
+    vendor: true,
+    src: ":PolicySubsystem-no-strategy",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
new file mode 100644
index 0000000..6fca048
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP No output configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/phone",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":PolicySubsystem-CommonTypes",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        "device_for_strategies.pfw",
+        ":volumes.pfw",
+        ":device_for_input_source.pfw",
+    ],
+}
+prebuilt_etc {
+    name: "PolicySubsystem.xml",
+    vendor: true,
+    src: ":PolicySubsystem-no-strategy",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml
index b55ce2c..585ce87 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml
@@ -73,10 +73,13 @@
                                             Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
             <Component Name="unprocessed" Type="InputSource"
                                             Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
+            <Component Name="voice_performance" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_VOICE_PERFORMANCE"/>
+            <Component Name="echo_reference" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_ECHO_REFERENCE"/>
             <Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
             <Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
         </ComponentType>
-
         <!--#################### INPUT SOURCE END ####################-->
     </ComponentLibrary>
 
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index cb45fcf..3987294 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -33,6 +33,8 @@
 #include <AudioIODescriptorInterface.h>
 #include <ParameterManagerWrapper.h>
 
+#include <media/TypeConverter.h>
+
 using std::string;
 using std::map;
 
@@ -244,9 +246,9 @@
     }
     if (devices == AUDIO_DEVICE_NONE ||
             (devices & availableOutputDevicesType) == AUDIO_DEVICE_NONE) {
-        devices = getApmObserver()->getDefaultOutputDevice()->type();
-        ALOGE_IF(devices == AUDIO_DEVICE_NONE, "%s: no valid default device defined", __FUNCTION__);
-        return DeviceVector(getApmObserver()->getDefaultOutputDevice());
+        auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
+        ALOG_ASSERT(defaultDevice != nullptr, "no valid default device defined");
+        return DeviceVector(defaultDevice);
     }
     if (/*device_distinguishes_on_address(devices)*/ devices == AUDIO_DEVICE_OUT_BUS) {
         // We do expect only one device for these types of devices
@@ -254,6 +256,14 @@
         // If this criterion is not wished, need to ensure this device is available
         const String8 address(productStrategies.getDeviceAddressForProductStrategy(ps).c_str());
         ALOGV("%s:device 0x%x %s %d", __FUNCTION__, devices, address.c_str(), ps);
+        auto busDevice = availableOutputDevices.getDevice(devices, address, AUDIO_FORMAT_DEFAULT);
+        if (busDevice == nullptr) {
+            ALOGE("%s:unavailable device 0x%x %s, fallback on default", __func__, devices,
+                  address.c_str());
+            auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
+            ALOG_ASSERT(defaultDevice != nullptr, "Default Output Device NOT available");
+            return DeviceVector(defaultDevice);
+        }
         return DeviceVector(availableOutputDevices.getDevice(devices,
                                                              address,
                                                              AUDIO_FORMAT_DEFAULT));
@@ -361,7 +371,7 @@
 }
 
 template <>
-AudioPolicyManagerInterface *Engine::queryInterface()
+EngineInterface *Engine::queryInterface()
 {
     return this;
 }
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 4662e7e..3b371d8 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -17,7 +17,7 @@
 #pragma once
 
 #include "EngineBase.h"
-#include <AudioPolicyManagerInterface.h>
+#include <EngineInterface.h>
 #include <AudioPolicyPluginInterface.h>
 #include "Collection.h"
 
diff --git a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
index 2442590..b127796 100644
--- a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
+++ b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <AudioPolicyManagerInterface.h>
+#include <EngineInterface.h>
 #include <AudioPolicyPluginInterface.h>
 #include "AudioPolicyEngineInstance.h"
 #include "Engine.h"
@@ -45,9 +45,9 @@
 }
 
 template <>
-AudioPolicyManagerInterface *EngineInstance::queryInterface() const
+EngineInterface *EngineInstance::queryInterface() const
 {
-    return getEngine()->queryInterface<AudioPolicyManagerInterface>();
+    return getEngine()->queryInterface<EngineInterface>();
 }
 
 template <>
@@ -57,5 +57,16 @@
 }
 
 } // namespace audio_policy
+
+extern "C" EngineInterface* createEngineInstance()
+{
+    return audio_policy::EngineInstance::getInstance()->queryInterface<EngineInterface>();
+}
+
+extern "C" void destroyEngineInstance(EngineInterface*)
+{
+    // The engine is a singleton.
+}
+
 } // namespace android
 
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index 8c16972..d9e97af 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -16,14 +16,17 @@
     name: "tools_default",
     version: {
         py2: {
-            enabled: true,
+            enabled: false,
         },
         py3: {
-            enabled: false,
+            enabled: true,
         },
     },
 }
 
+//##################################################################################################
+// Tools for audio policy engine criterion type configuration file
+//
 python_binary_host {
     name: "buildPolicyCriterionTypes.py",
     main: "buildPolicyCriterionTypes.py",
@@ -33,6 +36,30 @@
     defaults: ["tools_default"],
 }
 
+genrule_defaults {
+    name: "buildpolicycriteriontypesrule",
+    tools: ["buildPolicyCriterionTypes.py"],
+    cmd: "cp $(locations :audio_policy_configuration_files) $(genDir)/. && " +
+         "cp $(location :audio_policy_configuration_top_file) $(genDir)/audio_policy_configuration.xml && " +
+         "$(location buildPolicyCriterionTypes.py) " +
+         // @todo update if 1428659 is merged "--androidaudiobaseheader $(location :android_audio_base_header_file) " +
+         " --androidaudiobaseheader system/media/audio/include/system/audio-base.h " +
+         "--audiopolicyconfigurationfile $(genDir)/audio_policy_configuration.xml " +
+         "--criteriontypes $(location :audio_policy_engine_criterion_types_template) " +
+         "--outputfile $(out)",
+    srcs: [
+        // The commented inputs must be provided to use this genrule_defaults
+        // @todo uncomment if 1428659 is merged":android_audio_base_header_file",
+        ":audio_policy_engine_criterion_types_template",
+        // ":audio_policy_configuration_top_file",
+        // ":audio_policy_configuration_files",
+    ],
+    out: ["audio_policy_engine_criterion_types.xml"],
+}
+
+//##################################################################################################
+// Tools for audio policy engine parameter framework configurable domains
+//
 python_binary_host {
     name: "domainGeneratorPolicy.py",
     main: "domainGeneratorPolicy.py",
@@ -50,6 +77,38 @@
     ],
 }
 
+genrule_defaults {
+    name: "domaingeneratorpolicyrule",
+    tools: [
+        "domainGeneratorPolicy.py",
+        "domainGeneratorConnector",
+    ],
+    cmd: "mkdir -p $(genDir)/Structure/Policy && " +
+         "cp $(locations :audio_policy_pfw_structure_files) $(genDir)/Structure/Policy && " +
+         "cp $(location :audio_policy_pfw_toplevel) $(genDir)/top_level && " +
+         "$(location domainGeneratorPolicy.py) " +
+         "--validate " +
+         "--domain-generator-tool $(location domainGeneratorConnector) " +
+         "--toplevel-config $(genDir)/top_level " +
+         "--criteria $(location :audio_policy_engine_criteria) " +
+         "--criteriontypes $(location :audio_policy_engine_criterion_types) " +
+         "--add-edds $(locations :edd_files) " +
+         "--schemas-dir external/parameter-framework/upstream/schemas " +
+         " > $(out)",
+    srcs: [
+        // The commented inputs must be provided to use this genrule_defaults
+        // ":audio_policy_pfw_toplevel",
+        // ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criteria",
+        // ":audio_policy_engine_criterion_types",
+        // ":edd_files",
+    ],
+    out: ["PolicyConfigurableDomains.xml"],
+}
+
+//##################################################################################################
+// Tools for policy parameter-framework product strategies structure file generation
+//
 python_binary_host {
     name: "buildStrategiesStructureFile.py",
     main: "buildStrategiesStructureFile.py",
@@ -58,3 +117,19 @@
     ],
     defaults: ["tools_default"],
 }
+
+genrule_defaults {
+    name: "buildstrategiesstructurerule",
+    tools: ["buildStrategiesStructureFile.py"],
+    cmd: "cp $(locations :audio_policy_engine_configuration_files) $(genDir) && ls -l $(genDir) &&"+
+         "$(location buildStrategiesStructureFile.py) " +
+         "--audiopolicyengineconfigurationfile $(genDir)/audio_policy_engine_configuration.xml "+
+         "--productstrategiesstructurefile $(location :product_strategies_structure_template) " +
+         "--outputfile $(out)",
+    srcs: [
+        // The commented inputs must be provided to use this genrule_defaults
+        // ":audio_policy_engine_configuration_files",
+        ":product_strategies_structure_template",
+    ],
+    out: ["ProductStrategies.xml"],
+}
diff --git a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
index a63c858..b8b60c1 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 #
 # Copyright 2018, The Android Open Source Project
@@ -19,10 +19,8 @@
 import argparse
 import re
 import sys
-import tempfile
 import os
 import logging
-import subprocess
 import xml.etree.ElementTree as ET
 import xml.etree.ElementInclude as EI
 import xml.dom.minidom as MINIDOM
@@ -49,33 +47,35 @@
 
 def parseArgs():
     argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
-        audio criterion type file generator.\n\
-        Exit with the number of (recoverable or not) error that occured.")
+                                        audio criterion type file generator.\n\
+                                        Exit with the number of (recoverable or not) \
+                                        error that occured.")
     argparser.add_argument('--androidaudiobaseheader',
-            help="Android Audio Base C header file, Mandatory.",
-            metavar="ANDROID_AUDIO_BASE_HEADER",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Android Audio Base C header file, Mandatory.",
+                           metavar="ANDROID_AUDIO_BASE_HEADER",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--audiopolicyconfigurationfile',
-            help="Android Audio Policy Configuration file, Mandatory.",
-            metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Android Audio Policy Configuration file, Mandatory.",
+                           metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--criteriontypes',
-            help="Criterion types XML base file, in \
-            '<criterion_types> \
-                <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/>' \
-        format. Mandatory.",
-            metavar="CRITERION_TYPE_FILE",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Criterion types XML base file, in \
+                           '<criterion_types> \
+                               <criterion_type name="" type=<inclusive|exclusive> \
+                               values=<value1,value2,...>/>' \
+                           format. Mandatory.",
+                           metavar="CRITERION_TYPE_FILE",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--outputfile',
-            help="Criterion types outputfile file. Mandatory.",
-            metavar="CRITERION_TYPE_OUTPUT_FILE",
-            type=argparse.FileType('w'),
-            required=True)
+                           help="Criterion types outputfile file. Mandatory.",
+                           metavar="CRITERION_TYPE_OUTPUT_FILE",
+                           type=argparse.FileType('w'),
+                           required=True)
     argparser.add_argument('--verbose',
-            action='store_true')
+                           action='store_true')
 
     return argparser.parse_args()
 
@@ -120,7 +120,7 @@
     reparsed = MINIDOM.parseString(xmlstr)
     prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
     prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
-    outputFile.write(prettyXmlStr.encode('utf-8'))
+    outputFile.write(prettyXmlStr)
 
 def capitalizeLine(line):
     return ' '.join((w.capitalize() for w in line.split(' ')))
@@ -137,30 +137,30 @@
     #
     address_criteria_mapping_table = {
         'sink' : "OutputDevicesAddressesType",
-        'source' : "InputDevicesAddressesType" }
+        'source' : "InputDevicesAddressesType"}
 
     address_criteria = {
         'OutputDevicesAddressesType' : [],
-        'InputDevicesAddressesType' : [] }
+        'InputDevicesAddressesType' : []}
 
-    oldWorkingDir = os.getcwd()
-    print "Current working directory %s" % oldWorkingDir
+    old_working_dir = os.getcwd()
+    print("Current working directory %s" % old_working_dir)
 
-    newDir = os.path.join(oldWorkingDir , audiopolicyconfigurationfile.name)
+    new_dir = os.path.join(old_working_dir, audiopolicyconfigurationfile.name)
 
     policy_in_tree = ET.parse(audiopolicyconfigurationfile)
-    os.chdir(os.path.dirname(os.path.normpath(newDir)))
+    os.chdir(os.path.dirname(os.path.normpath(new_dir)))
 
-    print "new working directory %s" % os.getcwd()
+    print("new working directory %s" % os.getcwd())
 
     policy_root = policy_in_tree.getroot()
     EI.include(policy_root)
 
-    os.chdir(oldWorkingDir)
+    os.chdir(old_working_dir)
 
     for device in policy_root.iter('devicePort'):
         for key in address_criteria_mapping_table.keys():
-            if device.get('role') == key and device.get('address') :
+            if device.get('role') == key and device.get('address'):
                 logging.info("{}: <{}>".format(key, device.get('address')))
                 address_criteria[address_criteria_mapping_table[key]].append(device.get('address'))
 
@@ -188,15 +188,15 @@
     all_criteria = {
         'AndroidModeType' : {},
         'OutputDevicesMaskType' : {},
-        'InputDevicesMaskType' : {} }
+        'InputDevicesMaskType' : {}}
 
     #
     # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
     #
-    ignored_values = [ 'CNT', 'MAX', 'ALL', 'NONE' ]
+    ignored_values = ['CNT', 'MAX', 'ALL', 'NONE']
 
     criteria_pattern = re.compile(
-        r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))\_" \
+        r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
         r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
         r"(?P<values>(?:0[xX])?[0-9a-fA-F]+)")
 
@@ -221,7 +221,7 @@
                 logging.info("criterion {} duplicated values:".format(criterion_name))
                 logging.info("{}:{}".format(numerical_value, literal))
                 logging.info("KEEPING LATEST")
-                for key in all_criteria[criterion_name].keys():
+                for key in list(all_criteria[criterion_name]):
                     if all_criteria[criterion_name][key] == int(numerical_value, 0):
                         del all_criteria[criterion_name][key]
 
diff --git a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
index af40602..f69d346 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 #
 # Copyright 2019, The Android Open Source Project
@@ -17,16 +17,12 @@
 #
 
 import argparse
-import re
 import sys
-import tempfile
 import os
 import logging
-import subprocess
 import xml.etree.ElementTree as ET
 import xml.etree.ElementInclude as EI
 import xml.dom.minidom as MINIDOM
-from collections import OrderedDict
 
 #
 # Helper script that helps to feed at build time the XML Product Strategies Structure file file used
@@ -46,33 +42,34 @@
 
 def parseArgs():
     argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
-        product strategies structure file generator.\n\
-        Exit with the number of (recoverable or not) error that occured.")
+                                        product strategies structure file generator.\n\
+                                        Exit with the number of (recoverable or not) \
+                                        error that occured.")
     argparser.add_argument('--audiopolicyengineconfigurationfile',
-            help="Android Audio Policy Engine Configuration file, Mandatory.",
-            metavar="(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Android Audio Policy Engine Configuration file, Mandatory.",
+                           metavar="(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--productstrategiesstructurefile',
-            help="Product Strategies Structure XML base file, Mandatory.",
-            metavar="STRATEGIES_STRUCTURE_FILE",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Product Strategies Structure XML base file, Mandatory.",
+                           metavar="STRATEGIES_STRUCTURE_FILE",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--outputfile',
-            help="Product Strategies Structure output file, Mandatory.",
-            metavar="STRATEGIES_STRUCTURE_OUTPUT_FILE",
-            type=argparse.FileType('w'),
-            required=True)
+                           help="Product Strategies Structure output file, Mandatory.",
+                           metavar="STRATEGIES_STRUCTURE_OUTPUT_FILE",
+                           type=argparse.FileType('w'),
+                           required=True)
     argparser.add_argument('--verbose',
-            action='store_true')
+                           action='store_true')
 
     return argparser.parse_args()
 
 
-def generateXmlStructureFile(strategies, strategyStructureInFile, outputFile):
+def generateXmlStructureFile(strategies, strategy_structure_in_file, output_file):
 
-    logging.info("Importing strategyStructureInFile {}".format(strategyStructureInFile))
-    strategies_in_tree = ET.parse(strategyStructureInFile)
+    logging.info("Importing strategy_structure_in_file {}".format(strategy_structure_in_file))
+    strategies_in_tree = ET.parse(strategy_structure_in_file)
 
     strategies_root = strategies_in_tree.getroot()
     strategy_components = strategies_root.find('ComponentType')
@@ -80,13 +77,15 @@
     for strategy_name in strategies:
         context_mapping = "".join(map(str, ["Name:", strategy_name]))
         strategy_pfw_name = strategy_name.replace('STRATEGY_', '').lower()
-        strategy_component_node = ET.SubElement(strategy_components, "Component", Name=strategy_pfw_name, Type="ProductStrategy", Mapping=context_mapping)
+        ET.SubElement(strategy_components, "Component",
+                      Name=strategy_pfw_name, Type="ProductStrategy",
+                      Mapping=context_mapping)
 
     xmlstr = ET.tostring(strategies_root, encoding='utf8', method='xml')
     reparsed = MINIDOM.parseString(xmlstr)
     prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
     prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
-    outputFile.write(prettyXmlStr.encode('utf-8'))
+    output_file.write(prettyXmlStr)
 
 def capitalizeLine(line):
     return ' '.join((w.capitalize() for w in line.split(' ')))
@@ -97,26 +96,27 @@
 #
 def parseAndroidAudioPolicyEngineConfigurationFile(audiopolicyengineconfigurationfile):
 
-    logging.info("Checking Audio Policy Engine Configuration file {}".format(audiopolicyengineconfigurationfile))
+    logging.info("Checking Audio Policy Engine Configuration file {}".format(
+        audiopolicyengineconfigurationfile))
     #
     # extract all product strategies name from audio policy engine configuration file
     #
     strategy_names = []
 
-    oldWorkingDir = os.getcwd()
-    print "Current working directory %s" % oldWorkingDir
+    old_working_dir = os.getcwd()
+    print("Current working directory %s" % old_working_dir)
 
-    newDir = os.path.join(oldWorkingDir , audiopolicyengineconfigurationfile.name)
+    new_dir = os.path.join(old_working_dir, audiopolicyengineconfigurationfile.name)
 
     policy_engine_in_tree = ET.parse(audiopolicyengineconfigurationfile)
-    os.chdir(os.path.dirname(os.path.normpath(newDir)))
+    os.chdir(os.path.dirname(os.path.normpath(new_dir)))
 
-    print "new working directory %s" % os.getcwd()
+    print("new working directory %s" % os.getcwd())
 
     policy_engine_root = policy_engine_in_tree.getroot()
     EI.include(policy_engine_root)
 
-    os.chdir(oldWorkingDir)
+    os.chdir(old_working_dir)
 
     for strategy in policy_engine_root.iter('ProductStrategy'):
         strategy_names.append(strategy.get('name'))
@@ -128,7 +128,8 @@
     logging.root.setLevel(logging.INFO)
     args = parseArgs()
 
-    strategies = parseAndroidAudioPolicyEngineConfigurationFile(args.audiopolicyengineconfigurationfile)
+    strategies = parseAndroidAudioPolicyEngineConfigurationFile(
+        args.audiopolicyengineconfigurationfile)
 
     product_strategies_structure = args.productstrategiesstructurefile
 
diff --git a/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
deleted file mode 100644
index ac60ef7..0000000
--- a/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES += \
-    $(HOST_OUT_EXECUTABLES)/domainGeneratorPolicy.py \
-    $(PFW_TOPLEVEL_FILE) $(PFW_CRITERIA_FILE) $(PFW_CRITERION_TYPES_FILE)
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
-$(LOCAL_BUILT_MODULE): MY_TOOL := $(HOST_OUT_EXECUTABLES)/domainGeneratorPolicy.py
-$(LOCAL_BUILT_MODULE): MY_TOPLEVEL_FILE := $(PFW_TOPLEVEL_FILE)
-$(LOCAL_BUILT_MODULE): MY_CRITERIA_FILE := $(PFW_CRITERIA_FILE)
-$(LOCAL_BUILT_MODULE): MY_TUNING_FILE := $(PFW_TUNING_FILE)
-$(LOCAL_BUILT_MODULE): MY_EDD_FILES := $(PFW_EDD_FILES)
-$(LOCAL_BUILT_MODULE): MY_DOMAIN_FILES := $(PFW_DOMAIN_FILES)
-$(LOCAL_BUILT_MODULE): MY_SCHEMAS_DIR := $(PFW_SCHEMAS_DIR)
-$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
-
-	"$(MY_TOOL)" --validate \
-		--toplevel-config "$(MY_TOPLEVEL_FILE)" \
-		--criteria "$(MY_CRITERIA_FILE)" \
-		--criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
-		--initial-settings $(MY_TUNING_FILE) \
-		--add-edds $(MY_EDD_FILES) \
-		--add-domains $(MY_DOMAIN_FILES) \
-		--schemas-dir $(MY_SCHEMAS_DIR) > "$@"
-
-
-# Clear variables for further use
-PFW_TOPLEVEL_FILE :=
-PFW_STRUCTURE_FILES :=
-PFW_CRITERIA_FILE :=
-PFW_CRITERION_TYPES_FILE :=
-PFW_TUNING_FILE :=
-PFW_EDD_FILES :=
-PFW_DOMAIN_FILES :=
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
diff --git a/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
index 4dec9a2..b0c4b66 100755
--- a/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
+++ b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 #
 # Copyright 2018, The Android Open Source Project
@@ -16,12 +16,7 @@
 # limitations under the License.
 #
 
-import EddParser
-from PFWScriptGenerator import PfwScriptTranslator
-import hostConfig
-
 import argparse
-import re
 import sys
 import tempfile
 import os
@@ -29,6 +24,10 @@
 import subprocess
 import xml.etree.ElementTree as ET
 
+import EddParser
+from PFWScriptGenerator import PfwScriptTranslator
+import hostConfig
+
 #
 # In order to build the XML Settings file at build time, an instance of the parameter-framework
 # shall be started and fed with all the criterion types/criteria that will be used by
@@ -39,61 +38,67 @@
 
 def parseArgs():
     argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
-        Settings file generator.\n\
-        Exit with the number of (recoverable or not) error that occured.")
+                                        Settings file generator.\n\
+                                        Exit with the number of (recoverable or not) \
+                                        error that occured.")
+    argparser.add_argument('--domain-generator-tool',
+                           help="ParameterFramework domain generator tool. Mandatory.",
+                           metavar="PFW_DOMAIN_GENERATOR_TOOL",
+                           required=True)
     argparser.add_argument('--toplevel-config',
-            help="Top-level parameter-framework configuration file. Mandatory.",
-            metavar="TOPLEVEL_CONFIG_FILE",
-            required=True)
+                           help="Top-level parameter-framework configuration file. Mandatory.",
+                           metavar="TOPLEVEL_CONFIG_FILE",
+                           required=True)
     argparser.add_argument('--criteria',
-            help="Criteria file, in XML format: \
-                  in '<criteria> \
-                          <criterion name="" type=""/> \
-                      </criteria>' \
-        format. Mandatory.",
-            metavar="CRITERIA_FILE",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Criteria file, in XML format: \
+                                 in '<criteria> \
+                                         <criterion name="" type=""/> \
+                                     </criteria>' \
+                           format. Mandatory.",
+                           metavar="CRITERIA_FILE",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--criteriontypes',
-            help="Criterion types XML file, in \
-            '<criterion_types> \
-                <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/> \
-             </criterion_types>' \
-        format. Mandatory.",
-            metavar="CRITERION_TYPE_FILE",
-            type=argparse.FileType('r'),
-            required=False)
+                           help="Criterion types XML file, in \
+                           '<criterion_types> \
+                               <criterion_type name="" type=<inclusive|exclusive> \
+                                               values=<value1,value2,...>/> \
+                            </criterion_types>' \
+                           format. Mandatory.",
+                           metavar="CRITERION_TYPE_FILE",
+                           type=argparse.FileType('r'),
+                           required=False)
     argparser.add_argument('--initial-settings',
-            help="Initial XML settings file (containing a \
-        <ConfigurableDomains>  tag",
-            nargs='?',
-            default=None,
-            metavar="XML_SETTINGS_FILE")
+                           help="Initial XML settings file (containing a \
+                           <ConfigurableDomains>  tag",
+                           nargs='?',
+                           default=None,
+                           metavar="XML_SETTINGS_FILE")
     argparser.add_argument('--add-domains',
-            help="List of single domain files (each containing a single \
-        <ConfigurableDomain> tag",
-            metavar="XML_DOMAIN_FILE",
-            nargs='*',
-            dest='xml_domain_files',
-            default=[])
+                           help="List of single domain files (each containing a single \
+                           <ConfigurableDomain> tag",
+                           metavar="XML_DOMAIN_FILE",
+                           nargs='*',
+                           dest='xml_domain_files',
+                           default=[])
     argparser.add_argument('--add-edds',
-            help="List of files in EDD syntax (aka \".pfw\" files)",
-            metavar="EDD_FILE",
-            type=argparse.FileType('r'),
-            nargs='*',
-            default=[],
-            dest='edd_files')
+                           help="List of files in EDD syntax (aka \".pfw\" files)",
+                           metavar="EDD_FILE",
+                           type=argparse.FileType('r'),
+                           nargs='*',
+                           default=[],
+                           dest='edd_files')
     argparser.add_argument('--schemas-dir',
-            help="Directory of parameter-framework XML Schemas for generation \
-        validation",
-            default=None)
+                           help="Directory of parameter-framework XML Schemas for generation \
+                           validation",
+                           default=None)
     argparser.add_argument('--target-schemas-dir',
-            help="Ignored. Kept for retro-compatibility")
+                           help="Ignored. Kept for retro-compatibility")
     argparser.add_argument('--validate',
-            help="Validate the settings against XML schemas",
-            action='store_true')
+                           help="Validate the settings against XML schemas",
+                           action='store_true')
     argparser.add_argument('--verbose',
-            action='store_true')
+                           action='store_true')
 
     return argparser.parse_args()
 
@@ -112,7 +117,6 @@
     logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
 
     criteria_root = criteria_tree.getroot()
-    criterion_types_root = criterion_types_tree.getroot()
 
     all_criteria = []
     for criterion in criteria_root.findall('criterion'):
@@ -165,7 +169,7 @@
 
         try:
             root.propagate()
-        except EddParser.MyPropagationError, ex :
+        except EddParser.MyPropagationError as ex:
             logging.critical(str(ex))
             logging.info("EXIT ON FAILURE")
             exit(1)
@@ -179,32 +183,32 @@
 # It takes as input the collection of criteria, the domains and the simplified settings read from
 # pfw.
 #
-def generateDomainCommands(logging, all_criteria, initial_settings, xml_domain_files, parsed_edds):
-        # create and inject all the criteria
-        logging.info("Creating all criteria")
-        for criterion in all_criteria:
-            yield ["createSelectionCriterion", criterion['inclusive'],
-                   criterion['name']] + criterion['values']
+def generateDomainCommands(logger, all_criteria, initial_settings, xml_domain_files, parsed_edds):
+    # create and inject all the criteria
+    logger.info("Creating all criteria")
+    for criterion in all_criteria:
+        yield ["createSelectionCriterion", criterion['inclusive'],
+               criterion['name']] + criterion['values']
 
-        yield ["start"]
+    yield ["start"]
 
-        # Import initial settings file
-        if initial_settings:
-            logging.info("Importing initial settings file {}".format(initial_settings))
-            yield ["importDomainsWithSettingsXML", initial_settings]
+    # Import initial settings file
+    if initial_settings:
+        logger.info("Importing initial settings file {}".format(initial_settings))
+        yield ["importDomainsWithSettingsXML", initial_settings]
 
-        # Import each standalone domain files
-        for domain_file in xml_domain_files:
-            logging.info("Importing single domain file {}".format(domain_file))
-            yield ["importDomainWithSettingsXML", domain_file]
+    # Import each standalone domain files
+    for domain_file in xml_domain_files:
+        logger.info("Importing single domain file {}".format(domain_file))
+        yield ["importDomainWithSettingsXML", domain_file]
 
-        # Generate the script for each EDD file
-        for filename, parsed_edd in parsed_edds:
-            logging.info("Translating and injecting EDD file {}".format(filename))
-            translator = PfwScriptTranslator()
-            parsed_edd.translate(translator)
-            for command in translator.getScript():
-                yield command
+    # Generate the script for each EDD file
+    for filename, parsed_edd in parsed_edds:
+        logger.info("Translating and injecting EDD file {}".format(filename))
+        translator = PfwScriptTranslator()
+        parsed_edd.translate(translator)
+        for command in translator.getScript():
+            yield command
 
 #
 # Entry point of the domain generator.
@@ -232,30 +236,29 @@
                                                        prefix="TMPdomainGeneratorPFConfig_")
 
     install_path = os.path.dirname(os.path.realpath(args.toplevel_config))
-    hostConfig.configure(
-            infile=args.toplevel_config,
-            outfile=fake_toplevel_config,
-            structPath=install_path)
+    hostConfig.configure(infile=args.toplevel_config,
+                         outfile=fake_toplevel_config,
+                         structPath=install_path)
     fake_toplevel_config.close()
 
     # Create the connector. Pipe its input to us in order to write commands;
     # connect its output to stdout in order to have it dump the domains
     # there; connect its error output to stderr.
-    connector = subprocess.Popen(["domainGeneratorConnector",
-                            fake_toplevel_config.name,
-                            'verbose' if args.verbose else 'no-verbose',
-                            'validate' if args.validate else 'no-validate',
-                            args.schemas_dir],
-                           stdout=sys.stdout, stdin=subprocess.PIPE, stderr=sys.stderr)
+    connector = subprocess.Popen([args.domain_generator_tool,
+                                  fake_toplevel_config.name,
+                                  'verbose' if args.verbose else 'no-verbose',
+                                  'validate' if args.validate else 'no-validate',
+                                  args.schemas_dir],
+                                 stdout=sys.stdout, stdin=subprocess.PIPE, stderr=sys.stderr)
 
     initial_settings = None
     if args.initial_settings:
         initial_settings = os.path.realpath(args.initial_settings)
 
     for command in generateDomainCommands(logging, all_criteria, initial_settings,
-                                       args.xml_domain_files, parsed_edds):
-        connector.stdin.write('\0'.join(command))
-        connector.stdin.write("\n")
+                                          args.xml_domain_files, parsed_edds):
+        connector.stdin.write('\0'.join(command).encode('utf-8'))
+        connector.stdin.write("\n".encode('utf-8'))
 
     # Closing the connector's input triggers the domain generation
     connector.stdin.close()
diff --git a/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk b/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
deleted file mode 100644
index dab5a0f..0000000
--- a/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES += \
-    $(HOST_OUT_EXECUTABLES)/buildPolicyCriterionTypes.py \
-    $(CRITERION_TYPES_FILE) $(AUDIO_POLICY_CONFIGURATION_FILE) \
-    $(ANDROID_AUDIO_BASE_HEADER_FILE)
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(CRITERION_TYPES_FILE)
-$(LOCAL_BUILT_MODULE): MY_ANDROID_AUDIO_BASE_HEADER_FILE := $(ANDROID_AUDIO_BASE_HEADER_FILE)
-$(LOCAL_BUILT_MODULE): MY_AUDIO_POLICY_CONFIGURATION_FILE := $(AUDIO_POLICY_CONFIGURATION_FILE)
-$(LOCAL_BUILT_MODULE): MY_CRITERION_TOOL := $(HOST_OUT_EXECUTABLES)/buildPolicyCriterionTypes.py
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
-
-	"$(MY_CRITERION_TOOL)" \
-		--androidaudiobaseheader "$(MY_ANDROID_AUDIO_BASE_HEADER_FILE)" \
-		--audiopolicyconfigurationfile "$(MY_AUDIO_POLICY_CONFIGURATION_FILE)" \
-		--criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
-		--outputfile "$(@)"
-
-# Clear variables for further use
-CRITERION_TYPES_FILE :=
-ANDROID_AUDIO_BASE_HEADER_FILE :=
-AUDIO_POLICY_CONFIGURATION_FILE :=
diff --git a/services/audiopolicy/engineconfigurable/tools/provision_strategies_structure.mk b/services/audiopolicy/engineconfigurable/tools/provision_strategies_structure.mk
deleted file mode 100644
index f2b1a19..0000000
--- a/services/audiopolicy/engineconfigurable/tools/provision_strategies_structure.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES += \
-    $(HOST_OUT_EXECUTABLES)/buildStrategiesStructureFile.py \
-    $(STRATEGIES_STRUCTURE_FILE) $(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): MY_STRATEGIES_STRUCTURE_FILE := $(STRATEGIES_STRUCTURE_FILE)
-$(LOCAL_BUILT_MODULE): MY_AUDIO_POLICY_ENGINE_CONFIGURATION_FILE := $(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)
-$(LOCAL_BUILT_MODULE): MY_PROVISION_TOOL := $(HOST_OUT_EXECUTABLES)/buildStrategiesStructureFile.py
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
-
-	"$(MY_PROVISION_TOOL)" \
-		--audiopolicyengineconfigurationfile "$(MY_AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)" \
-		--productstrategiesstructurefile "$(MY_STRATEGIES_STRUCTURE_FILE)" \
-		--outputfile "$(@)"
-
-# Clear variables for further use
-STRATEGIES_STRUCTURE_FILE :=
-AUDIO_POLICY_ENGINE_CONFIGURATION_FILE :=
diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp
index 7b42c6a..2b9cf09 100644
--- a/services/audiopolicy/enginedefault/Android.bp
+++ b/services/audiopolicy/enginedefault/Android.bp
@@ -1,16 +1,15 @@
 cc_library_shared {
     name: "libaudiopolicyenginedefault",
-    export_include_dirs: ["include"],
     srcs: [
         "src/Engine.cpp",
         "src/EngineInstance.cpp",
     ],
     cflags: [
+        "-fvisibility=hidden",
         "-Wall",
         "-Werror",
         "-Wextra",
     ],
-    local_include_dirs: ["include"],
     header_libs: [
         "libbase_headers",
         "libaudiopolicycommon",
diff --git a/services/audiopolicy/enginedefault/config/example/Android.bp b/services/audiopolicy/enginedefault/config/example/Android.bp
new file mode 100644
index 0000000..0bfcaa1
--- /dev/null
+++ b/services/audiopolicy/enginedefault/config/example/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Phone with Default Engine configuration example
+
+soong_namespace {
+}
+
+prebuilt_etc {
+    name: "audio_policy_engine_configuration.xml",
+    vendor: true,
+    src: "phone/audio_policy_engine_configuration.xml",
+    required: [
+        ":audio_policy_engine_stream_volumes.xml",
+        ":audio_policy_engine_default_stream_volumes.xml",
+        ":audio_policy_engine_product_strategies.xml",
+    ],
+}
+prebuilt_etc {
+    name: "audio_policy_engine_product_strategies.xml",
+    vendor: true,
+    src: "phone/audio_policy_engine_product_strategies.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_stream_volumes.xml",
+    vendor: true,
+    src: "phone/audio_policy_engine_stream_volumes.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_default_stream_volumes.xml",
+    vendor: true,
+    src: "phone/audio_policy_engine_default_stream_volumes.xml",
+}
diff --git a/services/audiopolicy/enginedefault/config/example/Android.mk b/services/audiopolicy/enginedefault/config/example/Android.mk
deleted file mode 100644
index 0badac8..0000000
--- a/services/audiopolicy/enginedefault/config/example/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-##################################################################
-# CONFIGURATION TOP FILE
-##################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_default)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_configuration.xml
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-
-LOCAL_REQUIRED_MODULES := \
-    audio_policy_engine_product_strategies.xml \
-    audio_policy_engine_stream_volumes.xml \
-    audio_policy_engine_default_stream_volumes.xml
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_stream_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_default_stream_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_default)
diff --git a/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h b/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h
deleted file mode 100644
index 1e329f0..0000000
--- a/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h
+++ /dev/null
@@ -1,76 +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.
- */
-
-#pragma once
-
-class AudioPolicyManagerInterface;
-
-namespace android
-{
-namespace audio_policy
-{
-
-class Engine;
-
-class EngineInstance
-{
-protected:
-    EngineInstance();
-
-public:
-    virtual ~EngineInstance();
-
-    /**
-     * Get Audio Policy Engine instance.
-     *
-     * @return pointer to Route Manager Instance object.
-     */
-    static EngineInstance *getInstance();
-
-    /**
-     * Interface query.
-     * The first client of an interface of the policy engine will start the singleton.
-     *
-     * @tparam RequestedInterface: interface that the client is wishing to retrieve.
-     *
-     * @return interface handle.
-     */
-    template <class RequestedInterface>
-    RequestedInterface *queryInterface() const;
-
-protected:
-    /**
-     * Get Audio Policy Engine instance.
-     *
-     * @return Audio Policy Engine singleton.
-     */
-    Engine *getEngine() const;
-
-private:
-    /* Copy facilities are put private to disable copy. */
-    EngineInstance(const EngineInstance &object);
-    EngineInstance &operator=(const EngineInstance &object);
-};
-
-/**
- * Limit template instantation to supported type interfaces.
- * Compile time error will claim if invalid interface is requested.
- */
-template <>
-AudioPolicyManagerInterface *EngineInstance::queryInterface() const;
-
-} // namespace audio_policy
-} // namespace android
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 04170ac..c602f3a 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -762,12 +762,6 @@
                                            AUDIO_FORMAT_DEFAULT);
 }
 
-template <>
-AudioPolicyManagerInterface *Engine::queryInterface()
-{
-    return this;
-}
-
 } // namespace audio_policy
 } // namespace android
 
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index d5dfacc..62938cf 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -17,7 +17,7 @@
 #pragma once
 
 #include "EngineBase.h"
-#include "AudioPolicyManagerInterface.h"
+#include "EngineInterface.h"
 #include <AudioGain.h>
 #include <policy.h>
 
@@ -48,12 +48,9 @@
     Engine();
     virtual ~Engine() = default;
 
-    template <class RequestedInterface>
-    RequestedInterface *queryInterface();
-
 private:
     ///
-    /// from EngineBase, so from AudioPolicyManagerInterface
+    /// from EngineBase, so from EngineInterface
     ///
     status_t setForceUse(audio_policy_force_use_t usage,
                          audio_policy_forced_cfg_t config) override;
diff --git a/services/audiopolicy/enginedefault/src/EngineInstance.cpp b/services/audiopolicy/enginedefault/src/EngineInstance.cpp
index 17e9832..eeb3758 100644
--- a/services/audiopolicy/enginedefault/src/EngineInstance.cpp
+++ b/services/audiopolicy/enginedefault/src/EngineInstance.cpp
@@ -14,41 +14,21 @@
  * limitations under the License.
  */
 
-#include <AudioPolicyManagerInterface.h>
-#include "AudioPolicyEngineInstance.h"
+#include <EngineInterface.h>
 #include "Engine.h"
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
-EngineInstance::EngineInstance()
+extern "C" EngineInterface* createEngineInstance()
 {
+    return new (std::nothrow) Engine();
 }
 
-EngineInstance *EngineInstance::getInstance()
+extern "C" void destroyEngineInstance(EngineInterface *engine)
 {
-    static EngineInstance instance;
-    return &instance;
-}
-
-EngineInstance::~EngineInstance()
-{
-}
-
-Engine *EngineInstance::getEngine() const
-{
-    static Engine engine;
-    return &engine;
-}
-
-template <>
-AudioPolicyManagerInterface *EngineInstance::queryInterface() const
-{
-    return getEngine()->queryInterface<AudioPolicyManagerInterface>();
+    delete static_cast<Engine*>(engine);
 }
 
 } // namespace audio_policy
 } // namespace android
-
diff --git a/services/audiopolicy/manager/AudioPolicyFactory.cpp b/services/audiopolicy/manager/AudioPolicyFactory.cpp
index 7aff6a9..476a1ec 100644
--- a/services/audiopolicy/manager/AudioPolicyFactory.cpp
+++ b/services/audiopolicy/manager/AudioPolicyFactory.cpp
@@ -21,7 +21,13 @@
 extern "C" AudioPolicyInterface* createAudioPolicyManager(
         AudioPolicyClientInterface *clientInterface)
 {
-    return new AudioPolicyManager(clientInterface);
+    AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);
+    status_t status = apm->initialize();
+    if (status != NO_ERROR) {
+        delete apm;
+        apm = nullptr;
+    }
+    return apm;
 }
 
 extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
new file mode 100644
index 0000000..8fbeff9
--- /dev/null
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -0,0 +1,43 @@
+cc_library_shared {
+    name: "libaudiopolicymanagerdefault",
+
+    srcs: [
+        "AudioPolicyManager.cpp",
+        "EngineLibrary.cpp",
+    ],
+
+    export_include_dirs: ["."],
+
+    shared_libs: [
+        "libcutils",
+        "libdl",
+        "libutils",
+        "liblog",
+        "libaudiopolicy",
+        "libsoundtrigger",
+        "libmedia_helper",
+        "libmediametrics",
+        "libbinder",
+        "libhidlbase",
+        "libxml2",
+        // The default audio policy engine is always present in the system image.
+        // libaudiopolicyengineconfigurable can be built in addition by specifying
+        // a dependency on it in the device makefile. There will be no build time
+        // conflict with libaudiopolicyenginedefault.
+        "libaudiopolicyenginedefault",
+    ],
+
+    header_libs: [
+        "libaudiopolicycommon",
+        "libaudiopolicyengine_interface_headers",
+        "libaudiopolicymanager_interface_headers",
+    ],
+
+    static_libs: ["libaudiopolicycomponents"],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+}
diff --git a/services/audiopolicy/managerdefault/Android.mk b/services/audiopolicy/managerdefault/Android.mk
deleted file mode 100644
index c5921c3..0000000
--- a/services/audiopolicy/managerdefault/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= AudioPolicyManager.cpp
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libutils \
-    liblog \
-    libaudiopolicy \
-    libsoundtrigger
-
-ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
-
-LOCAL_SHARED_LIBRARIES += libaudiopolicyengineconfigurable
-
-else
-
-LOCAL_SHARED_LIBRARIES += libaudiopolicyenginedefault
-
-endif # ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
-
-LOCAL_C_INCLUDES += \
-    $(call include-path-for, audio-utils)
-
-LOCAL_HEADER_LIBRARIES := \
-    libaudiopolicycommon \
-    libaudiopolicyengine_interface_headers \
-    libaudiopolicymanager_interface_headers
-
-LOCAL_STATIC_LIBRARIES := \
-    libaudiopolicycomponents
-
-LOCAL_SHARED_LIBRARIES += libmedia_helper
-LOCAL_SHARED_LIBRARIES += libmediametrics
-
-LOCAL_SHARED_LIBRARIES += libbinder libhidlbase libxml2
-
-LOCAL_CFLAGS += -Wall -Werror
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_MODULE:= libaudiopolicymanagerdefault
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a8fd9cd..83ae35e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -42,8 +42,6 @@
 #include <set>
 #include <unordered_set>
 #include <vector>
-#include <AudioPolicyManagerInterface.h>
-#include <AudioPolicyEngineInstance.h>
 #include <cutils/properties.h>
 #include <utils/Log.h>
 #include <media/AudioParameter.h>
@@ -96,7 +94,7 @@
 {
     AudioParameter param(device->address());
     const String8 key(state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE ?
-                AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect);
+                AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect);
     param.addInt(key, device->type());
     mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
 }
@@ -474,6 +472,10 @@
     std::unordered_set<audio_format_t> formatSet;
     sp<HwModule> primaryModule =
             mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY);
+    if (primaryModule == nullptr) {
+        ALOGE("%s() unable to get primary module", __func__);
+        return NO_INIT;
+    }
     DeviceVector declaredDevices = primaryModule->getDeclaredDevices().getDevicesFromTypeMask(
             AUDIO_DEVICE_OUT_ALL_A2DP);
     for (const auto& device : declaredDevices) {
@@ -838,7 +840,7 @@
         // if explicitly requested
         static const uint32_t kRelevantFlags =
                 (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
-                 AUDIO_OUTPUT_FLAG_VOIP_RX);
+                 AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ);
         flags =
             (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT);
     }
@@ -2238,16 +2240,22 @@
         return status;
     }
 
-  // increment activity count before calling getNewInputDevice() below as only active sessions
+    // increment activity count before calling getNewInputDevice() below as only active sessions
     // are considered for device selection
     inputDesc->setClientActive(client, true);
 
     // indicate active capture to sound trigger service if starting capture from a mic on
     // primary HW module
     sp<DeviceDescriptor> device = getNewInputDevice(inputDesc);
-    setInputDevice(input, device, true /* force */);
+    if (device != nullptr) {
+        status = setInputDevice(input, device, true /* force */);
+    } else {
+        ALOGW("%s no new input device can be found for descriptor %d",
+                __FUNCTION__, inputDesc->getId());
+        status = BAD_VALUE;
+    }
 
-    if (inputDesc->activeCount()  == 1) {
+    if (status == NO_ERROR && inputDesc->activeCount() == 1) {
         sp<AudioPolicyMix> policyMix = inputDesc->mPolicyMix.promote();
         // if input maps to a dynamic policy with an activity listener, notify of state change
         if ((policyMix != NULL)
@@ -2278,11 +2286,16 @@
                         address, "remote-submix", AUDIO_FORMAT_DEFAULT);
             }
         }
+    } else if (status != NO_ERROR) {
+        // Restore client activity state.
+        inputDesc->setClientActive(client, false);
+        inputDesc->stop();
     }
 
-    ALOGV("%s input %d source = %d exit", __FUNCTION__, input, client->source());
+    ALOGV("%s input %d source = %d status = %d exit",
+            __FUNCTION__, input, client->source(), status);
 
-    return NO_ERROR;
+    return status;
 }
 
 status_t AudioPolicyManager::stopInput(audio_port_handle_t portId)
@@ -4293,7 +4306,6 @@
         : AudioPolicyManager(clientInterface, false /*forTesting*/)
 {
     loadConfig();
-    initialize();
 }
 
 void AudioPolicyManager::loadConfig() {
@@ -4304,17 +4316,18 @@
 }
 
 status_t AudioPolicyManager::initialize() {
-    // Once policy config has been parsed, retrieve an instance of the engine and initialize it.
-    audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
-    if (!engineInstance) {
-        ALOGE("%s:  Could not get an instance of policy engine", __FUNCTION__);
-        return NO_INIT;
-    }
-    // Retrieve the Policy Manager Interface
-    mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
-    if (mEngine == NULL) {
-        ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
-        return NO_INIT;
+    {
+        auto engLib = EngineLibrary::load(
+                        "libaudiopolicyengine" + getConfig().getEngineLibraryNameSuffix() + ".so");
+        if (!engLib) {
+            ALOGE("%s: Failed to load the engine library", __FUNCTION__);
+            return NO_INIT;
+        }
+        mEngine = engLib->createEngine();
+        if (mEngine == nullptr) {
+            ALOGE("%s: Failed to instantiate the APM engine", __FUNCTION__);
+            return NO_INIT;
+        }
     }
     mEngine->setObserver(this);
     status_t status = mEngine->initCheck();
@@ -5681,8 +5694,9 @@
     const auto ringVolumeSrc = toVolumeSource(AUDIO_STREAM_RING);
     const auto musicVolumeSrc = toVolumeSource(AUDIO_STREAM_MUSIC);
     const auto alarmVolumeSrc = toVolumeSource(AUDIO_STREAM_ALARM);
+    const auto a11yVolumeSrc = toVolumeSource(AUDIO_STREAM_ACCESSIBILITY);
 
-    if (volumeSource == toVolumeSource(AUDIO_STREAM_ACCESSIBILITY)
+    if (volumeSource == a11yVolumeSrc
             && (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
             mOutputs.isActive(ringVolumeSrc, 0)) {
         auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
@@ -5699,7 +5713,7 @@
              volumeSource == toVolumeSource(AUDIO_STREAM_NOTIFICATION) ||
              volumeSource == toVolumeSource(AUDIO_STREAM_ENFORCED_AUDIBLE) ||
              volumeSource == toVolumeSource(AUDIO_STREAM_DTMF) ||
-             volumeSource == toVolumeSource(AUDIO_STREAM_ACCESSIBILITY))) {
+             volumeSource == a11yVolumeSrc)) {
         auto &voiceCurves = getVolumeCurves(callVolumeSrc);
         int voiceVolumeIndex = voiceCurves.getVolumeIndex(device);
         const float maxVoiceVolDb =
@@ -5711,7 +5725,9 @@
         // VOICE_CALL stream has minVolumeIndex > 0 : Users cannot set the volume of voice calls to
         // 0. We don't want to cap volume when the system has programmatically muted the voice call
         // stream. See setVolumeCurveIndex() for more information.
-        bool exemptFromCapping = (volumeSource == ringVolumeSrc) && (voiceVolumeIndex == 0);
+        bool exemptFromCapping =
+                ((volumeSource == ringVolumeSrc) || (volumeSource == a11yVolumeSrc))
+                && (voiceVolumeIndex == 0);
         ALOGV_IF(exemptFromCapping, "%s volume source %d at vol=%f not capped", __func__,
                  volumeSource, volumeDb);
         if ((volumeDb > maxVoiceVolDb) && !exemptFromCapping) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 612bd8f..5f651cc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -34,7 +34,6 @@
 #include <media/PatchBuilder.h>
 #include "AudioPolicyInterface.h"
 
-#include <AudioPolicyManagerInterface.h>
 #include <AudioPolicyManagerObserver.h>
 #include <AudioGain.h>
 #include <AudioPolicyConfig.h>
@@ -49,6 +48,7 @@
 #include <AudioPolicyMix.h>
 #include <EffectDescriptor.h>
 #include <SoundTriggerSession.h>
+#include "EngineLibrary.h"
 #include "TypeConverter.h"
 
 namespace android {
@@ -307,6 +307,8 @@
             return volumeGroup != VOLUME_GROUP_NONE ? NO_ERROR : BAD_VALUE;
         }
 
+        status_t initialize();
+
 protected:
         // A constructor that allows more fine-grained control over initialization process,
         // used in automatic tests.
@@ -321,7 +323,6 @@
         //   - initialize.
         AudioPolicyConfig& getConfig() { return mConfig; }
         void loadConfig();
-        status_t initialize();
 
         // From AudioPolicyManagerObserver
         virtual const AudioPatchCollection &getAudioPatches() const
@@ -752,7 +753,7 @@
         uint32_t nextAudioPortGeneration();
 
         // Audio Policy Engine Interface.
-        AudioPolicyManagerInterface *mEngine;
+        EngineInstance mEngine;
 
         // Surround formats that are enabled manually. Taken into account when
         // "encoded surround" is forced into "manual" mode.
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp
new file mode 100644
index 0000000..ef699aa
--- /dev/null
+++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019 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 "APM_EngineLoader"
+
+#include <dlfcn.h>
+#include <utils/Log.h>
+
+#include "EngineLibrary.h"
+
+namespace android {
+
+// static
+std::shared_ptr<EngineLibrary> EngineLibrary::load(std::string libraryPath)
+{
+    std::shared_ptr<EngineLibrary> engLib(new EngineLibrary());
+    return engLib->init(std::move(libraryPath)) ? engLib : nullptr;
+}
+
+EngineLibrary::~EngineLibrary()
+{
+    close();
+}
+
+bool EngineLibrary::init(std::string libraryPath)
+{
+    mLibraryHandle = dlopen(libraryPath.c_str(), 0);
+    if (mLibraryHandle == nullptr) {
+        ALOGE("Could not dlopen %s: %s", libraryPath.c_str(), dlerror());
+        return false;
+    }
+    mCreateEngineInstance = (EngineInterface* (*)())dlsym(mLibraryHandle, "createEngineInstance");
+    mDestroyEngineInstance = (void (*)(EngineInterface*))dlsym(
+            mLibraryHandle, "destroyEngineInstance");
+    if (mCreateEngineInstance == nullptr || mDestroyEngineInstance == nullptr) {
+        ALOGE("Could not find engine interface functions in %s", libraryPath.c_str());
+        close();
+        return false;
+    }
+    ALOGD("Loaded engine from %s", libraryPath.c_str());
+    return true;
+}
+
+EngineInstance EngineLibrary::createEngine()
+{
+    if (mCreateEngineInstance == nullptr || mDestroyEngineInstance == nullptr) {
+        return EngineInstance();
+    }
+    return EngineInstance(mCreateEngineInstance(),
+            [lib = shared_from_this(), destroy = mDestroyEngineInstance] (EngineInterface* e) {
+                destroy(e);
+            });
+}
+
+void EngineLibrary::close()
+{
+    if (mLibraryHandle != nullptr) {
+        dlclose(mLibraryHandle);
+    }
+    mLibraryHandle = nullptr;
+    mCreateEngineInstance = nullptr;
+    mDestroyEngineInstance = nullptr;
+}
+
+}  // namespace android
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.h b/services/audiopolicy/managerdefault/EngineLibrary.h
new file mode 100644
index 0000000..f143916
--- /dev/null
+++ b/services/audiopolicy/managerdefault/EngineLibrary.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <EngineInterface.h>
+
+namespace android {
+
+using EngineInstance = std::unique_ptr<EngineInterface, std::function<void (EngineInterface*)>>;
+
+class EngineLibrary : public std::enable_shared_from_this<EngineLibrary> {
+public:
+    static std::shared_ptr<EngineLibrary> load(std::string libraryPath);
+    ~EngineLibrary();
+
+    EngineLibrary(const EngineLibrary&) = delete;
+    EngineLibrary(EngineLibrary&&) = delete;
+    EngineLibrary& operator=(const EngineLibrary&) = delete;
+    EngineLibrary& operator=(EngineLibrary&&) = delete;
+
+    EngineInstance createEngine();
+
+private:
+    EngineLibrary() = default;
+    bool init(std::string libraryPath);
+    void close();
+
+    void *mLibraryHandle = nullptr;
+    EngineInterface* (*mCreateEngineInstance)() = nullptr;
+    void (*mDestroyEngineInstance)(EngineInterface*) = nullptr;
+};
+
+}  // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 85ea94f..d1b59c1 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -409,12 +409,17 @@
 //    Another client in the same UID has already been allowed to capture
 //    OR The client is the assistant
 //        AND an accessibility service is on TOP or a RTT call is active
-//               AND the source is VOICE_RECOGNITION or HOTWORD
-//        OR uses VOICE_RECOGNITION AND is on TOP
-//               OR uses HOTWORD
+//                AND the source is VOICE_RECOGNITION or HOTWORD
+//            OR uses VOICE_RECOGNITION AND is on TOP
+//                OR uses HOTWORD
 //            AND there is no active privacy sensitive capture or call
 //                OR client has CAPTURE_AUDIO_OUTPUT privileged permission
 //    OR The client is an accessibility service
+//        AND Is on TOP
+//                AND the source is VOICE_RECOGNITION or HOTWORD
+//            OR The assistant is not on TOP
+//                AND there is no active privacy sensitive capture or call
+//                    OR client has CAPTURE_AUDIO_OUTPUT privileged permission
 //        AND is on TOP
 //        AND the source is VOICE_RECOGNITION or HOTWORD
 //    OR the client source is virtual (remote submix, call audio TX or RX...)
@@ -422,7 +427,7 @@
 //        AND The assistant is not on TOP
 //        AND is on TOP or latest started
 //        AND there is no active privacy sensitive capture or call
-//                OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//            OR client has CAPTURE_AUDIO_OUTPUT privileged permission
 
     sp<AudioRecordClient> topActive;
     sp<AudioRecordClient> latestActive;
@@ -458,16 +463,24 @@
             continue;
         }
 
-        if (appState == APP_STATE_TOP) {
+        bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
+        bool isAccessibility = mUidPolicy->isA11yUid(current->uid);
+        if (appState == APP_STATE_TOP && !isAccessibility) {
             if (current->startTimeNs > topStartNs) {
                 topActive = current;
                 topStartNs = current->startTimeNs;
             }
-            if (mUidPolicy->isAssistantUid(current->uid)) {
+            if (isAssistant) {
                 isAssistantOnTop = true;
             }
         }
-        if (current->startTimeNs > latestStartNs) {
+        // Assistant capturing for HOTWORD or Accessibility services not considered
+        // for latest active to avoid masking regular clients started before
+        if (current->startTimeNs > latestStartNs
+                && !((current->attributes.source == AUDIO_SOURCE_HOTWORD
+                        || isA11yOnTop || rttCallActive)
+                    && isAssistant)
+                && !isAccessibility) {
             latestActive = current;
             latestStartNs = current->startTimeNs;
         }
@@ -540,10 +553,20 @@
         } else if (mUidPolicy->isA11yUid(current->uid)) {
             // For accessibility service allow capture if:
             //     Is on TOP
-            //     AND the source is VOICE_RECOGNITION or HOTWORD
-            if (isA11yOnTop &&
-                    (source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD)) {
-                allowCapture = true;
+            //          AND the source is VOICE_RECOGNITION or HOTWORD
+            //     Or
+            //          The assistant is not on TOP
+            //          AND there is no active privacy sensitive capture or call
+            //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+            if (isA11yOnTop) {
+                if (source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD) {
+                    allowCapture = true;
+                }
+            } else {
+                if (!isAssistantOnTop
+                        && (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+                    allowCapture = true;
+                }
             }
         }
         setAppState_l(current->uid,
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index de5670c..e10a716 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -30,7 +30,16 @@
 
 using namespace android;
 
-TEST(AudioPolicyManagerTestInit, Failure) {
+TEST(AudioPolicyManagerTestInit, EngineFailure) {
+    AudioPolicyTestClient client;
+    AudioPolicyTestManager manager(&client);
+    manager.getConfig().setDefault();
+    manager.getConfig().setEngineLibraryNameSuffix("non-existent");
+    ASSERT_EQ(NO_INIT, manager.initialize());
+    ASSERT_EQ(NO_INIT, manager.initCheck());
+}
+
+TEST(AudioPolicyManagerTestInit, ClientFailure) {
     AudioPolicyTestClient client;
     AudioPolicyTestManager manager(&client);
     manager.getConfig().setDefault();
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index b26398e..c50a3c6 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -69,6 +69,10 @@
         "utils/LatencyHistogram.cpp",
     ],
 
+    header_libs: [
+        "libmediadrm_headers"
+    ],
+
     shared_libs: [
         "libbase",
         "libdl",
@@ -88,6 +92,7 @@
         "libhardware",
         "libhidlbase",
         "libjpeg",
+        "libmedia_codeclist",
         "libmedia_omx",
         "libmemunreachable",
         "libsensorprivacy",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index e663485..c70513c 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -253,6 +253,15 @@
     enumerateProviders();
 }
 
+bool CameraService::isPublicallyHiddenSecureCamera(const String8& cameraId) {
+    auto state = getCameraState(cameraId);
+    if (state != nullptr) {
+        return state->isPublicallyHiddenSecureCamera();
+    }
+    // Hidden physical camera ids won't have CameraState
+    return mCameraProviderManager->isPublicallyHiddenSecureCamera(cameraId.c_str());
+}
+
 void CameraService::updateCameraNumAndIds() {
     Mutex::Autolock l(mServiceLock);
     mNumberOfCameras = mCameraProviderManager->getCameraCount();
@@ -268,6 +277,8 @@
         ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
         return;
     }
+    bool isPublicallyHiddenSecureCamera =
+            mCameraProviderManager->isPublicallyHiddenSecureCamera(id.string());
     std::set<String8> conflicting;
     for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
         conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
@@ -276,7 +287,8 @@
     {
         Mutex::Autolock lock(mCameraStatesLock);
         mCameraStates.emplace(id, std::make_shared<CameraState>(id, cost.resourceCost,
-                                                                conflicting));
+                                                                conflicting,
+                                                                isPublicallyHiddenSecureCamera));
     }
 
     if (mFlashlight->hasFlashUnit(id)) {
@@ -514,8 +526,16 @@
                 "Camera subsystem is not available");;
     }
 
-    Status ret{};
+    if (shouldRejectHiddenCameraConnection(String8(cameraId))) {
+        ALOGW("Attempting to retrieve characteristics for system-only camera id %s, rejected",
+              String8(cameraId).string());
+        return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
+                                "No camera device with ID \"%s\" currently available",
+                                String8(cameraId).string());
 
+    }
+
+    Status ret{};
     status_t res = mCameraProviderManager->getCameraCharacteristics(
             String8(cameraId).string(), cameraInfo);
     if (res != OK) {
@@ -1149,6 +1169,8 @@
                 clientPid,
                 states[states.size() - 1]);
 
+        resource_policy::ClientPriority clientPriority = clientDescriptor->getPriority();
+
         // Find clients that would be evicted
         auto evicted = mActiveClientManager.wouldEvict(clientDescriptor);
 
@@ -1166,8 +1188,7 @@
             String8 msg = String8::format("%s : DENIED connect device %s client for package %s "
                     "(PID %d, score %d state %d) due to eviction policy", curTime.string(),
                     cameraId.string(), packageName.string(), clientPid,
-                    priorityScores[priorityScores.size() - 1],
-                    states[states.size() - 1]);
+                    clientPriority.getScore(), clientPriority.getState());
 
             for (auto& i : incompatibleClients) {
                 msg.appendFormat("\n   - Blocked by existing device %s client for package %s"
@@ -1212,9 +1233,8 @@
                     i->getKey().string(), String8{clientSp->getPackageName()}.string(),
                     i->getOwnerId(), i->getPriority().getScore(),
                     i->getPriority().getState(), cameraId.string(),
-                    packageName.string(), clientPid,
-                    priorityScores[priorityScores.size() - 1],
-                    states[states.size() - 1]));
+                    packageName.string(), clientPid, clientPriority.getScore(),
+                    clientPriority.getState()));
 
             // Notify the client of disconnection
             clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
@@ -1330,7 +1350,7 @@
     // publically hidden, we should reject the connection.
     if (!hardware::IPCThreadState::self()->isServingCall() &&
             CameraThreadState::getCallingPid() != getpid() &&
-            mCameraProviderManager->isPublicallyHiddenSecureCamera(cameraId.c_str())) {
+            isPublicallyHiddenSecureCamera(cameraId)) {
         return true;
     }
     return false;
@@ -1348,14 +1368,19 @@
     Status ret = Status::ok();
     String8 id = String8(cameraId);
     sp<CameraDeviceClient> client = nullptr;
-
+    String16 clientPackageNameAdj = clientPackageName;
+    if (hardware::IPCThreadState::self()->isServingCall()) {
+        std::string vendorClient =
+                StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
+        clientPackageNameAdj = String16(vendorClient.c_str());
+    }
     ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
             /*api1CameraId*/-1,
-            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
+            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageNameAdj,
             clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, /*out*/client);
 
     if(!ret.isOk()) {
-        logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
+        logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageNameAdj),
                 ret.toString8());
         return ret;
     }
@@ -1799,16 +1824,25 @@
     {
         Mutex::Autolock lock(mCameraStatesLock);
         for (auto& i : mCameraStates) {
-            if (!isVendorListener &&
-                mCameraProviderManager->isPublicallyHiddenSecureCamera(i.first.c_str())) {
-                ALOGV("Cannot add public listener for hidden system-only %s for pid %d",
-                      i.first.c_str(), CameraThreadState::getCallingPid());
-                continue;
-            }
             cameraStatuses->emplace_back(i.first, mapToInterface(i.second->getStatus()));
         }
     }
 
+    // Remove the camera statuses that should be hidden from the client, we do
+    // this after collecting the states in order to avoid holding
+    // mCameraStatesLock and mInterfaceLock (held in
+    // isPublicallyHiddenSecureCamera()) at the same time.
+    cameraStatuses->erase(std::remove_if(cameraStatuses->begin(), cameraStatuses->end(),
+                [this, &isVendorListener](const hardware::CameraStatus& s) {
+                    bool ret = !isVendorListener && isPublicallyHiddenSecureCamera(s.cameraId);
+                    if (ret) {
+                        ALOGV("Cannot add public listener for hidden system-only %s for pid %d",
+                                s.cameraId.c_str(), CameraThreadState::getCallingPid());
+                    }
+                    return ret;
+                }),
+                cameraStatuses->end());
+
     /*
      * Immediately signal current torch status to this listener only
      * This may be a subset of all the devices, so don't include it in the response directly
@@ -2368,11 +2402,7 @@
         }
         mClientPackageName = packages[0];
     }
-    if (hardware::IPCThreadState::self()->isServingCall()) {
-        std::string vendorClient =
-                StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
-        mClientPackageName = String16(vendorClient.c_str());
-    } else {
+    if (!hardware::IPCThreadState::self()->isServingCall()) {
         mAppOpsManager = std::make_unique<AppOpsManager>();
     }
 }
@@ -2870,8 +2900,9 @@
 // ----------------------------------------------------------------------------
 
 CameraService::CameraState::CameraState(const String8& id, int cost,
-        const std::set<String8>& conflicting) : mId(id),
-        mStatus(StatusInternal::NOT_PRESENT), mCost(cost), mConflicting(conflicting) {}
+        const std::set<String8>& conflicting, bool isHidden) : mId(id),
+        mStatus(StatusInternal::NOT_PRESENT), mCost(cost), mConflicting(conflicting),
+        mIsPublicallyHiddenSecureCamera(isHidden) {}
 
 CameraService::CameraState::~CameraState() {}
 
@@ -2900,6 +2931,10 @@
     return mId;
 }
 
+bool CameraService::CameraState::isPublicallyHiddenSecureCamera() const {
+    return mIsPublicallyHiddenSecureCamera;
+}
+
 // ----------------------------------------------------------------------------
 //                  ClientEventListener
 // ----------------------------------------------------------------------------
@@ -3235,10 +3270,10 @@
                 cameraId.string());
         return;
     }
-
+    bool isHidden = isPublicallyHiddenSecureCamera(cameraId);
     // Update the status for this camera state, then send the onStatusChangedCallbacks to each
     // of the listeners with both the mStatusStatus and mStatusListenerLock held
-    state->updateStatus(status, cameraId, rejectSourceStates, [this]
+    state->updateStatus(status, cameraId, rejectSourceStates, [this,&isHidden]
             (const String8& cameraId, StatusInternal status) {
 
             if (status != StatusInternal::ENUMERATING) {
@@ -3260,8 +3295,7 @@
             Mutex::Autolock lock(mStatusListenerLock);
 
             for (auto& listener : mListenerList) {
-                if (!listener.first &&
-                    mCameraProviderManager->isPublicallyHiddenSecureCamera(cameraId.c_str())) {
+                if (!listener.first &&  isHidden) {
                     ALOGV("Skipping camera discovery callback for system-only camera %s",
                           cameraId.c_str());
                     continue;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index cf93a41..8bb78cd 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -471,7 +471,8 @@
          * Make a new CameraState and set the ID, cost, and conflicting devices using the values
          * returned in the HAL's camera_info struct for each device.
          */
-        CameraState(const String8& id, int cost, const std::set<String8>& conflicting);
+        CameraState(const String8& id, int cost, const std::set<String8>& conflicting,
+                bool isHidden);
         virtual ~CameraState();
 
         /**
@@ -523,6 +524,11 @@
          */
         String8 getId() const;
 
+        /**
+         * Return if the camera device is a publically hidden secure camera
+         */
+        bool isPublicallyHiddenSecureCamera() const;
+
     private:
         const String8 mId;
         StatusInternal mStatus; // protected by mStatusLock
@@ -530,6 +536,7 @@
         std::set<String8> mConflicting;
         mutable Mutex mStatusLock;
         CameraParameters mShimParams;
+        const bool mIsPublicallyHiddenSecureCamera;
     }; // class CameraState
 
     // Observer for UID lifecycle enforcing that UIDs in idle
@@ -635,7 +642,9 @@
 
     // Should an operation attempt on a cameraId be rejected, if the camera id is
     // advertised as a publically hidden secure camera, by the camera HAL ?
-    bool shouldRejectHiddenCameraConnection(const String8 & cameraId);
+    bool shouldRejectHiddenCameraConnection(const String8& cameraId);
+
+    bool isPublicallyHiddenSecureCamera(const String8& cameraId);
 
     // Single implementation shared between the various connect calls
     template<class CALLBACK, class CLIENT>
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 5a87134..3d1235e 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -28,7 +28,7 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 09638d0..cb2c324 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -97,7 +97,13 @@
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     int count = 0;
     for (auto& provider : mProviders) {
-        count += provider->mUniqueCameraIds.size();
+        for (auto& id : provider->mUniqueCameraIds) {
+            // Hidden secure camera ids are not to be exposed to camera1 api.
+            if (isPublicallyHiddenSecureCameraLocked(id)) {
+                continue;
+            }
+            count++;
+        }
     }
     return count;
 }
@@ -123,7 +129,11 @@
         // for each camera facing, only take the first id advertised by HAL in
         // all [logical, physical1, physical2, ...] id combos, and filter out the rest.
         filterLogicalCameraIdsLocked(providerDeviceIds);
-
+        // Hidden secure camera ids are not to be exposed to camera1 api.
+        providerDeviceIds.erase(std::remove_if(providerDeviceIds.begin(), providerDeviceIds.end(),
+                [this](const std::string& s) {
+                    return this->isPublicallyHiddenSecureCameraLocked(s);}),
+                providerDeviceIds.end());
         deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end());
     }
 
@@ -1035,23 +1045,42 @@
     return deviceInfo->mIsLogicalCamera;
 }
 
-bool CameraProviderManager::isPublicallyHiddenSecureCamera(const std::string& id) {
+bool CameraProviderManager::isPublicallyHiddenSecureCamera(const std::string& id) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
-
-    auto deviceInfo = findDeviceInfoLocked(id);
-    if (deviceInfo == nullptr) {
-        return false;
-    }
-    return deviceInfo->mIsPublicallyHiddenSecureCamera;
+    return isPublicallyHiddenSecureCameraLocked(id);
 }
 
-bool CameraProviderManager::isHiddenPhysicalCamera(const std::string& cameraId) {
+bool CameraProviderManager::isPublicallyHiddenSecureCameraLocked(const std::string& id) const {
+    auto deviceInfo = findDeviceInfoLocked(id);
+    if (deviceInfo != nullptr) {
+        return deviceInfo->mIsPublicallyHiddenSecureCamera;
+    }
+    // If this is a hidden physical camera, we should return what kind of
+    // camera the enclosing logical camera is.
+    auto isHiddenAndParent = isHiddenPhysicalCameraInternal(id);
+    if (isHiddenAndParent.first) {
+        LOG_ALWAYS_FATAL_IF(id == isHiddenAndParent.second->mId,
+                "%s: hidden physical camera id %s and enclosing logical camera id %s are the same",
+                __FUNCTION__, id.c_str(), isHiddenAndParent.second->mId.c_str());
+        return isPublicallyHiddenSecureCameraLocked(isHiddenAndParent.second->mId);
+    }
+    // Invalid camera id
+    return true;
+}
+
+bool CameraProviderManager::isHiddenPhysicalCamera(const std::string& cameraId) const {
+    return isHiddenPhysicalCameraInternal(cameraId).first;
+}
+
+std::pair<bool, CameraProviderManager::ProviderInfo::DeviceInfo *>
+CameraProviderManager::isHiddenPhysicalCameraInternal(const std::string& cameraId) const {
+    auto falseRet = std::make_pair(false, nullptr);
     for (auto& provider : mProviders) {
         for (auto& deviceInfo : provider->mDevices) {
             if (deviceInfo->mId == cameraId) {
                 // cameraId is found in public camera IDs advertised by the
                 // provider.
-                return false;
+                return falseRet;
             }
         }
     }
@@ -1063,7 +1092,7 @@
             if (res != OK) {
                 ALOGE("%s: Failed to getCameraCharacteristics for id %s", __FUNCTION__,
                         deviceInfo->mId.c_str());
-                return false;
+                return falseRet;
             }
 
             std::vector<std::string> physicalIds;
@@ -1075,16 +1104,16 @@
                     if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_5) {
                         ALOGE("%s: Wrong deviceVersion %x for hiddenPhysicalCameraId %s",
                                 __FUNCTION__, deviceVersion, cameraId.c_str());
-                        return false;
+                        return falseRet;
                     } else {
-                        return true;
+                        return std::make_pair(true, deviceInfo.get());
                     }
                 }
             }
         }
     }
 
-    return false;
+    return falseRet;
 }
 
 status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
@@ -2058,6 +2087,13 @@
     return OK;
 }
 bool CameraProviderManager::ProviderInfo::DeviceInfo3::isAPI1Compatible() const {
+    // Do not advertise NIR cameras to API1 camera app.
+    camera_metadata_ro_entry cfa = mCameraCharacteristics.find(
+            ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+    if (cfa.count == 1 && cfa.data.u8[0] == ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR) {
+        return false;
+    }
+
     bool isBackwardCompatible = false;
     camera_metadata_ro_entry_t caps = mCameraCharacteristics.find(
             ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index a42fb4d..cd283b3 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -269,8 +269,8 @@
      */
     bool isLogicalCamera(const std::string& id, std::vector<std::string>* physicalCameraIds);
 
-    bool isPublicallyHiddenSecureCamera(const std::string& id);
-    bool isHiddenPhysicalCamera(const std::string& cameraId);
+    bool isPublicallyHiddenSecureCamera(const std::string& id) const;
+    bool isHiddenPhysicalCamera(const std::string& cameraId) const;
 
     static const float kDepthARTolerance;
 private:
@@ -591,7 +591,15 @@
 
     status_t getCameraCharacteristicsLocked(const std::string &id,
             CameraMetadata* characteristics) const;
+
+    bool isPublicallyHiddenSecureCameraLocked(const std::string& id) const;
+
     void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
+
+    bool isPublicallyHiddenSecureCameraLocked(const std::string& id);
+
+    std::pair<bool, CameraProviderManager::ProviderInfo::DeviceInfo *>
+            isHiddenPhysicalCameraInternal(const std::string& cameraId) const;
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp b/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp
index 3c90de0..94541d8 100644
--- a/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp
+++ b/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp
@@ -419,7 +419,7 @@
 
     std::vector<std::unique_ptr<Item>> items;
     std::vector<std::unique_ptr<Camera>> cameraList;
-    auto image = Image::FromDataForPrimaryImage("android/mainimage", &items);
+    auto image = Image::FromDataForPrimaryImage("image/jpeg", &items);
     std::unique_ptr<CameraParams> cameraParams(new CameraParams(std::move(image)));
     if (cameraParams == nullptr) {
         ALOGE("%s: Failed to initialize camera parameters", __FUNCTION__);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index a8e80fa..4227a3b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -29,6 +29,9 @@
 #define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
             ##__VA_ARGS__)
 
+#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+            ##__VA_ARGS__)
+
 // Convenience macros for transitioning to the error state
 #define SET_ERR(fmt, ...) setErrorState(   \
     "%s: " fmt, __FUNCTION__,              \
@@ -3267,14 +3270,19 @@
         ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
      }
 
-    // Sanity check - if we have too many in-flight frames, something has
-    // likely gone wrong
-    if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
-        CLOGE("In-flight list too large: %zu", mInFlightMap.size());
-    } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
-            kInFlightWarnLimitHighSpeed) {
-        CLOGE("In-flight list too large for high speed configuration: %zu",
-                mInFlightMap.size());
+    // Sanity check - if we have too many in-flight frames with long total inflight duration,
+    // something has likely gone wrong. This might still be legit only if application send in
+    // a long burst of long exposure requests.
+    if (mExpectedInflightDuration > kMinWarnInflightDuration) {
+        if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
+            CLOGW("In-flight list too large: %zu, total inflight duration %" PRIu64,
+                    mInFlightMap.size(), mExpectedInflightDuration);
+        } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
+                kInFlightWarnLimitHighSpeed) {
+            CLOGW("In-flight list too large for high speed configuration: %zu,"
+                    "total inflight duration %" PRIu64,
+                    mInFlightMap.size(), mExpectedInflightDuration);
+        }
     }
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 6e8ac84..cae34ce 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -227,6 +227,7 @@
     static const size_t        kDumpLockAttempts  = 10;
     static const size_t        kDumpSleepDuration = 100000; // 0.10 sec
     static const nsecs_t       kActiveTimeout     = 500000000;  // 500 ms
+    static const nsecs_t       kMinWarnInflightDuration = 5000000000; // 5 s
     static const size_t        kInFlightWarnLimit = 30;
     static const size_t        kInFlightWarnLimitHighSpeed = 256; // batch size 32 * pipe depth 8
     static const nsecs_t       kDefaultExpectedDuration = 100000000; // 100 ms
diff --git a/services/mediaanalytics/Android.bp b/services/mediaanalytics/Android.bp
index 72f4b52..c27aced 100644
--- a/services/mediaanalytics/Android.bp
+++ b/services/mediaanalytics/Android.bp
@@ -50,7 +50,7 @@
         "frameworks/av/media/libstagefright/rtsp",
         "frameworks/av/media/libstagefright/webm",
         "frameworks/av/include/media",
-        "frameworks/av/include/camera",
+        "frameworks/av/camera/include/camera",
         "frameworks/native/include/media/openmax",
         "frameworks/native/include/media/hardware",
         "external/tremolo/Tremolo",
diff --git a/services/mediaanalytics/statsd_audiopolicy.cpp b/services/mediaanalytics/statsd_audiopolicy.cpp
index 06c4dde..95cb274 100644
--- a/services/mediaanalytics/statsd_audiopolicy.cpp
+++ b/services/mediaanalytics/statsd_audiopolicy.cpp
@@ -60,14 +60,14 @@
         metrics_proto.set_status(status);
     }
     //string char kAudioPolicyRqstSrc[] = "android.media.audiopolicy.rqst.src";
-    char *rqst_src = NULL;
-    if (item->getCString("android.media.audiopolicy.rqst.src", &rqst_src)) {
-        metrics_proto.set_request_source(rqst_src);
+    std::string rqst_src;
+    if (item->getString("android.media.audiopolicy.rqst.src", &rqst_src)) {
+        metrics_proto.set_request_source(std::move(rqst_src));
     }
     //string char kAudioPolicyRqstPkg[] = "android.media.audiopolicy.rqst.pkg";
-    char *rqst_pkg = NULL;
-    if (item->getCString("android.media.audiopolicy.rqst.pkg", &rqst_pkg)) {
-        metrics_proto.set_request_package(rqst_pkg);
+    std::string rqst_pkg;
+    if (item->getString("android.media.audiopolicy.rqst.pkg", &rqst_pkg)) {
+        metrics_proto.set_request_package(std::move(rqst_pkg));
     }
     //int32 char kAudioPolicyRqstSession[] = "android.media.audiopolicy.rqst.session";
     int32_t rqst_session = -1;
@@ -75,20 +75,20 @@
         metrics_proto.set_request_session(rqst_session);
     }
     //string char kAudioPolicyRqstDevice[] = "android.media.audiopolicy.rqst.device";
-    char *rqst_device = NULL;
-    if (item->getCString("android.media.audiopolicy.rqst.device", &rqst_device)) {
-        metrics_proto.set_request_device(rqst_device);
+    std::string rqst_device;
+    if (item->getString("android.media.audiopolicy.rqst.device", &rqst_device)) {
+        metrics_proto.set_request_device(std::move(rqst_device));
     }
 
     //string char kAudioPolicyActiveSrc[] = "android.media.audiopolicy.active.src";
-    char *active_src = NULL;
-    if (item->getCString("android.media.audiopolicy.active.src", &active_src)) {
-        metrics_proto.set_active_source(active_src);
+    std::string active_src;
+    if (item->getString("android.media.audiopolicy.active.src", &active_src)) {
+        metrics_proto.set_active_source(std::move(active_src));
     }
     //string char kAudioPolicyActivePkg[] = "android.media.audiopolicy.active.pkg";
-    char *active_pkg = NULL;
-    if (item->getCString("android.media.audiopolicy.active.pkg", &active_pkg)) {
-        metrics_proto.set_active_package(active_pkg);
+    std::string active_pkg;
+    if (item->getString("android.media.audiopolicy.active.pkg", &active_pkg)) {
+        metrics_proto.set_active_package(std::move(active_pkg));
     }
     //int32 char kAudioPolicyActiveSession[] = "android.media.audiopolicy.active.session";
     int32_t active_session = -1;
@@ -96,9 +96,9 @@
         metrics_proto.set_active_session(active_session);
     }
     //string char kAudioPolicyActiveDevice[] = "android.media.audiopolicy.active.device";
-    char *active_device = NULL;
-    if (item->getCString("android.media.audiopolicy.active.device", &active_device)) {
-        metrics_proto.set_active_device(active_device);
+    std::string active_device;
+    if (item->getString("android.media.audiopolicy.active.device", &active_device)) {
+        metrics_proto.set_active_device(std::move(active_device));
     }
 
 
@@ -119,14 +119,6 @@
         ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
     }
 
-    // must free the strings that we were given
-    free(rqst_src);
-    free(rqst_pkg);
-    free(rqst_device);
-    free(active_src);
-    free(active_pkg);
-    free(active_device);
-
     return true;
 }
 
diff --git a/services/mediaanalytics/statsd_audiorecord.cpp b/services/mediaanalytics/statsd_audiorecord.cpp
index c9edb27..7c7a62c 100644
--- a/services/mediaanalytics/statsd_audiorecord.cpp
+++ b/services/mediaanalytics/statsd_audiorecord.cpp
@@ -54,14 +54,14 @@
 
     // flesh out the protobuf we'll hand off with our data
     //
-    char *encoding = NULL;
-    if (item->getCString("android.media.audiorecord.encoding", &encoding)) {
-        metrics_proto.set_encoding(encoding);
+    std::string encoding;
+    if (item->getString("android.media.audiorecord.encoding", &encoding)) {
+        metrics_proto.set_encoding(std::move(encoding));
     }
 
-    char *source = NULL;
-    if (item->getCString("android.media.audiorecord.source", &source)) {
-        metrics_proto.set_source(source);
+    std::string source;
+    if (item->getString("android.media.audiorecord.source", &source)) {
+        metrics_proto.set_source(std::move(source));
     }
 
     int32_t latency = -1;
@@ -101,11 +101,11 @@
         metrics_proto.set_error_code(errcode);
     }
 
-    char *errfunc = NULL;
-    if (item->getCString("android.media.audiorecord.errfunc", &errfunc)) {
-        metrics_proto.set_error_function(errfunc);
-    } else if (item->getCString("android.media.audiorecord.lastError.at", &errfunc)) {
-        metrics_proto.set_error_function(errfunc);
+    std::string errfunc;
+    if (item->getString("android.media.audiorecord.errfunc", &errfunc)) {
+        metrics_proto.set_error_function(std::move(errfunc));
+    } else if (item->getString("android.media.audiorecord.lastError.at", &errfunc)) {
+        metrics_proto.set_error_function(std::move(errfunc));
     }
 
     // portId (int32)
@@ -119,9 +119,9 @@
         metrics_proto.set_frame_count(frameCount);
     }
     // attributes (string)
-    char *attributes = NULL;
-    if (item->getCString("android.media.audiorecord.attributes", &attributes)) {
-        metrics_proto.set_attributes(attributes);
+    std::string attributes;
+    if (item->getString("android.media.audiorecord.attributes", &attributes)) {
+        metrics_proto.set_attributes(std::move(attributes));
     }
     // channelMask (int64)
     int64_t channelMask = -1;
@@ -152,12 +152,6 @@
         ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
     }
 
-    // must free the strings that we were given
-    free(encoding);
-    free(source);
-    free(errfunc);
-    free(attributes);
-
     return true;
 }
 
diff --git a/services/mediaanalytics/statsd_audiothread.cpp b/services/mediaanalytics/statsd_audiothread.cpp
index 8232424..e9d6b17 100644
--- a/services/mediaanalytics/statsd_audiothread.cpp
+++ b/services/mediaanalytics/statsd_audiothread.cpp
@@ -56,9 +56,9 @@
 
     // flesh out the protobuf we'll hand off with our data
     //
-    char *mytype = NULL;
-    if (item->getCString(MM_PREFIX "type", &mytype)) {
-        metrics_proto.set_type(mytype);
+    std::string mytype;
+    if (item->getString(MM_PREFIX "type", &mytype)) {
+        metrics_proto.set_type(std::move(mytype));
     }
     int32_t framecount = -1;
     if (item->getInt32(MM_PREFIX "framecount", &framecount)) {
@@ -68,17 +68,17 @@
     if (item->getInt32(MM_PREFIX "samplerate", &samplerate)) {
         metrics_proto.set_samplerate(samplerate);
     }
-    char *workhist = NULL;
-    if (item->getCString(MM_PREFIX "workMs.hist", &workhist)) {
-        metrics_proto.set_work_millis_hist(workhist);
+    std::string workhist;
+    if (item->getString(MM_PREFIX "workMs.hist", &workhist)) {
+        metrics_proto.set_work_millis_hist(std::move(workhist));
     }
-    char *latencyhist = NULL;
-    if (item->getCString(MM_PREFIX "latencyMs.hist", &latencyhist)) {
-        metrics_proto.set_latency_millis_hist(latencyhist);
+    std::string latencyhist;
+    if (item->getString(MM_PREFIX "latencyMs.hist", &latencyhist)) {
+        metrics_proto.set_latency_millis_hist(std::move(latencyhist));
     }
-    char *warmuphist = NULL;
-    if (item->getCString(MM_PREFIX "warmupMs.hist", &warmuphist)) {
-        metrics_proto.set_warmup_millis_hist(warmuphist);
+    std::string warmuphist;
+    if (item->getString(MM_PREFIX "warmupMs.hist", &warmuphist)) {
+        metrics_proto.set_warmup_millis_hist(std::move(warmuphist));
     }
     int64_t underruns = -1;
     if (item->getInt64(MM_PREFIX "underruns", &underruns)) {
@@ -108,9 +108,9 @@
         metrics_proto.set_port_id(port_id);
     }
     // item->setCString(MM_PREFIX "type", threadTypeToString(mType));
-    char *type = NULL;
-    if (item->getCString(MM_PREFIX "type", &type)) {
-        metrics_proto.set_type(type);
+    std::string type;
+    if (item->getString(MM_PREFIX "type", &type)) {
+        metrics_proto.set_type(std::move(type));
     }
     // item->setInt32(MM_PREFIX "sampleRate", (int32_t)mSampleRate);
     int32_t sample_rate = -1;
@@ -123,9 +123,9 @@
         metrics_proto.set_channel_mask(channel_mask);
     }
     // item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
-    char *encoding = NULL;
-    if (item->getCString(MM_PREFIX "encoding", &encoding)) {
-        metrics_proto.set_encoding(encoding);
+    std::string encoding;
+    if (item->getString(MM_PREFIX "encoding", &encoding)) {
+        metrics_proto.set_encoding(std::move(encoding));
     }
     // item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
     int32_t frame_count = -1;
@@ -133,14 +133,14 @@
         metrics_proto.set_frame_count(frame_count);
     }
     // item->setCString(MM_PREFIX "outDevice", toString(mOutDevice).c_str());
-    char *outDevice = NULL;
-    if (item->getCString(MM_PREFIX "outDevice", &outDevice)) {
-        metrics_proto.set_output_device(outDevice);
+    std::string outDevice;
+    if (item->getString(MM_PREFIX "outDevice", &outDevice)) {
+        metrics_proto.set_output_device(std::move(outDevice));
     }
     // item->setCString(MM_PREFIX "inDevice", toString(mInDevice).c_str());
-    char *inDevice = NULL;
-    if (item->getCString(MM_PREFIX "inDevice", &inDevice)) {
-        metrics_proto.set_input_device(inDevice);
+    std::string inDevice;
+    if (item->getString(MM_PREFIX "inDevice", &inDevice)) {
+        metrics_proto.set_input_device(std::move(inDevice));
     }
     // item->setDouble(MM_PREFIX "ioJitterMs.mean", mIoJitterMs.getMean());
     double iojitters_ms_mean = -1;
@@ -201,16 +201,6 @@
         ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
     }
 
-    // must free the strings that we were given
-    free(mytype);
-    free(workhist);
-    free(latencyhist);
-    free(warmuphist);
-    free(type);
-    free(encoding);
-    free(inDevice);
-    free(outDevice);
-
     return true;
 }
 
diff --git a/services/mediaanalytics/statsd_audiotrack.cpp b/services/mediaanalytics/statsd_audiotrack.cpp
index f250ced..57cda99 100644
--- a/services/mediaanalytics/statsd_audiotrack.cpp
+++ b/services/mediaanalytics/statsd_audiotrack.cpp
@@ -57,23 +57,23 @@
 
     // static constexpr char kAudioTrackStreamType[] = "android.media.audiotrack.streamtype";
     // optional string streamType;
-    char *streamtype = NULL;
-    if (item->getCString("android.media.audiotrack.streamtype", &streamtype)) {
-        metrics_proto.set_stream_type(streamtype);
+    std::string streamtype;
+    if (item->getString("android.media.audiotrack.streamtype", &streamtype)) {
+        metrics_proto.set_stream_type(std::move(streamtype));
     }
 
     // static constexpr char kAudioTrackContentType[] = "android.media.audiotrack.type";
     // optional string contentType;
-    char *contenttype = NULL;
-    if (item->getCString("android.media.audiotrack.type", &contenttype)) {
-        metrics_proto.set_content_type(contenttype);
+    std::string contenttype;
+    if (item->getString("android.media.audiotrack.type", &contenttype)) {
+        metrics_proto.set_content_type(std::move(contenttype));
     }
 
     // static constexpr char kAudioTrackUsage[] = "android.media.audiotrack.usage";
     // optional string trackUsage;
-    char *trackusage = NULL;
-    if (item->getCString("android.media.audiotrack.usage", &trackusage)) {
-        metrics_proto.set_track_usage(trackusage);
+    std::string trackusage;
+    if (item->getString("android.media.audiotrack.usage", &trackusage)) {
+        metrics_proto.set_track_usage(std::move(trackusage));
     }
 
     // static constexpr char kAudioTrackSampleRate[] = "android.media.audiotrack.samplerate";
@@ -111,9 +111,9 @@
         metrics_proto.set_port_id(port_id);
     }
     // encoding (string)
-    char *encoding = NULL;
-    if (item->getCString("android.media.audiotrack.encoding", &encoding)) {
-        metrics_proto.set_encoding(encoding);
+    std::string encoding;
+    if (item->getString("android.media.audiotrack.encoding", &encoding)) {
+        metrics_proto.set_encoding(std::move(encoding));
     }
     // frameCount (int32)
     int32_t frame_count = -1;
@@ -121,9 +121,9 @@
         metrics_proto.set_frame_count(frame_count);
     }
     // attributes (string)
-    char *attributes = NULL;
-    if (item->getCString("android.media.audiotrack.attributes", &attributes)) {
-        metrics_proto.set_attributes(attributes);
+    std::string attributes;
+    if (item->getString("android.media.audiotrack.attributes", &attributes)) {
+        metrics_proto.set_attributes(std::move(attributes));
     }
 
     std::string serialized;
@@ -143,13 +143,6 @@
         ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
     }
 
-    // must free the strings that we were given
-    free(streamtype);
-    free(contenttype);
-    free(trackusage);
-    free(encoding);
-    free(attributes);
-
     return true;
 }
 
diff --git a/services/mediaanalytics/statsd_codec.cpp b/services/mediaanalytics/statsd_codec.cpp
index dc8e4ef..bf82e50 100644
--- a/services/mediaanalytics/statsd_codec.cpp
+++ b/services/mediaanalytics/statsd_codec.cpp
@@ -55,19 +55,19 @@
     // flesh out the protobuf we'll hand off with our data
     //
     // android.media.mediacodec.codec   string
-    char *codec = NULL;
-    if (item->getCString("android.media.mediacodec.codec", &codec)) {
-        metrics_proto.set_codec(codec);
+    std::string codec;
+    if (item->getString("android.media.mediacodec.codec", &codec)) {
+        metrics_proto.set_codec(std::move(codec));
     }
     // android.media.mediacodec.mime    string
-    char *mime = NULL;
-    if (item->getCString("android.media.mediacodec.mime", &mime)) {
-        metrics_proto.set_mime(mime);
+    std::string mime;
+    if (item->getString("android.media.mediacodec.mime", &mime)) {
+        metrics_proto.set_mime(std::move(mime));
     }
     // android.media.mediacodec.mode    string
-    char *mode = NULL;
-    if ( item->getCString("android.media.mediacodec.mode", &mode)) {
-        metrics_proto.set_mode(mode);
+    std::string mode;
+    if ( item->getString("android.media.mediacodec.mode", &mode)) {
+        metrics_proto.set_mode(std::move(mode));
     }
     // android.media.mediacodec.encoder int32
     int32_t encoder = -1;
@@ -125,9 +125,9 @@
         metrics_proto.set_error_code(errcode);
     }
     // android.media.mediacodec.errstate        string
-    char *errstate = NULL;
-    if ( item->getCString("android.media.mediacodec.errstate", &errstate)) {
-        metrics_proto.set_error_state(errstate);
+    std::string errstate;
+    if ( item->getString("android.media.mediacodec.errstate", &errstate)) {
+        metrics_proto.set_error_state(std::move(errstate));
     }
     // android.media.mediacodec.latency.max  int64
     int64_t latency_max = -1;
@@ -173,12 +173,6 @@
         ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
     }
 
-    // must free the strings that we were given
-    free(codec);
-    free(mime);
-    free(mode);
-    free(errstate);
-
     return true;
 }
 
diff --git a/services/mediaanalytics/statsd_extractor.cpp b/services/mediaanalytics/statsd_extractor.cpp
index 395c912..d84930c 100644
--- a/services/mediaanalytics/statsd_extractor.cpp
+++ b/services/mediaanalytics/statsd_extractor.cpp
@@ -56,14 +56,14 @@
     //
 
     // android.media.mediaextractor.fmt         string
-    char *fmt = NULL;
-    if (item->getCString("android.media.mediaextractor.fmt", &fmt)) {
-        metrics_proto.set_format(fmt);
+    std::string fmt;
+    if (item->getString("android.media.mediaextractor.fmt", &fmt)) {
+        metrics_proto.set_format(std::move(fmt));
     }
     // android.media.mediaextractor.mime        string
-    char *mime = NULL;
-    if (item->getCString("android.media.mediaextractor.mime", &mime)) {
-        metrics_proto.set_mime(mime);
+    std::string mime;
+    if (item->getString("android.media.mediaextractor.mime", &mime)) {
+        metrics_proto.set_mime(std::move(mime));
     }
     // android.media.mediaextractor.ntrk        int32
     int32_t ntrk = -1;
@@ -88,10 +88,6 @@
         ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
     }
 
-    // must free the strings that we were given
-    free(fmt);
-    free(mime);
-
     return true;
 }
 
diff --git a/services/mediaanalytics/statsd_nuplayer.cpp b/services/mediaanalytics/statsd_nuplayer.cpp
index 5ec118a..e6e0f2c 100644
--- a/services/mediaanalytics/statsd_nuplayer.cpp
+++ b/services/mediaanalytics/statsd_nuplayer.cpp
@@ -62,13 +62,13 @@
     // differentiate between nuplayer and nuplayer2
     metrics_proto.set_whichplayer(item->getKey().c_str());
 
-    char *video_mime = NULL;
-    if (item->getCString("android.media.mediaplayer.video.mime", &video_mime)) {
-        metrics_proto.set_video_mime(video_mime);
+    std::string video_mime;
+    if (item->getString("android.media.mediaplayer.video.mime", &video_mime)) {
+        metrics_proto.set_video_mime(std::move(video_mime));
     }
-    char *video_codec = NULL;
-    if (item->getCString("android.media.mediaplayer.video.codec", &video_codec)) {
-        metrics_proto.set_video_codec(video_codec);
+    std::string video_codec;
+    if (item->getString("android.media.mediaplayer.video.codec", &video_codec)) {
+        metrics_proto.set_video_codec(std::move(video_codec));
     }
 
     int32_t width = -1;
@@ -97,13 +97,13 @@
         metrics_proto.set_framerate(fps);
     }
 
-    char *audio_mime = NULL;
-    if (item->getCString("android.media.mediaplayer.audio.mime", &audio_mime)) {
-        metrics_proto.set_audio_mime(audio_mime);
+    std::string audio_mime;
+    if (item->getString("android.media.mediaplayer.audio.mime", &audio_mime)) {
+        metrics_proto.set_audio_mime(std::move(audio_mime));
     }
-    char *audio_codec = NULL;
-    if (item->getCString("android.media.mediaplayer.audio.codec", &audio_codec)) {
-        metrics_proto.set_audio_codec(audio_codec);
+    std::string audio_codec;
+    if (item->getString("android.media.mediaplayer.audio.codec", &audio_codec)) {
+        metrics_proto.set_audio_codec(std::move(audio_codec));
     }
 
     int64_t duration_ms = -1;
@@ -123,14 +123,14 @@
     if (item->getInt32("android.media.mediaplayer.errcode", &error_code)) {
         metrics_proto.set_error_code(error_code);
     }
-    char *error_state = NULL;
-    if (item->getCString("android.media.mediaplayer.errstate", &error_state)) {
-        metrics_proto.set_error_state(error_state);
+    std::string error_state;
+    if (item->getString("android.media.mediaplayer.errstate", &error_state)) {
+        metrics_proto.set_error_state(std::move(error_state));
     }
 
-    char *data_source_type = NULL;
-    if (item->getCString("android.media.mediaplayer.dataSource", &data_source_type)) {
-        metrics_proto.set_data_source_type(data_source_type);
+    std::string data_source_type;
+    if (item->getString("android.media.mediaplayer.dataSource", &data_source_type)) {
+        metrics_proto.set_data_source_type(std::move(data_source_type));
     }
 
     int64_t rebufferingMs = -1;
@@ -164,14 +164,6 @@
         ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
     }
 
-    // must free the strings that we were given
-    free(video_mime);
-    free(video_codec);
-    free(audio_mime);
-    free(audio_codec);
-    free(error_state);
-    free(data_source_type);
-
     return true;
 }
 
diff --git a/services/mediaanalytics/statsd_recorder.cpp b/services/mediaanalytics/statsd_recorder.cpp
index 4d981b4..d286f00 100644
--- a/services/mediaanalytics/statsd_recorder.cpp
+++ b/services/mediaanalytics/statsd_recorder.cpp
@@ -56,14 +56,14 @@
     //
 
     // string kRecorderAudioMime = "android.media.mediarecorder.audio.mime";
-    char *audio_mime = NULL;
-    if (item->getCString("android.media.mediarecorder.audio.mime", &audio_mime)) {
-        metrics_proto.set_audio_mime(audio_mime);
+    std::string audio_mime;
+    if (item->getString("android.media.mediarecorder.audio.mime", &audio_mime)) {
+        metrics_proto.set_audio_mime(std::move(audio_mime));
     }
     // string kRecorderVideoMime = "android.media.mediarecorder.video.mime";
-    char *video_mime = NULL;
-    if (item->getCString("android.media.mediarecorder.video.mime", &video_mime)) {
-        metrics_proto.set_video_mime(video_mime);
+    std::string video_mime;
+    if (item->getString("android.media.mediarecorder.video.mime", &video_mime)) {
+        metrics_proto.set_video_mime(std::move(video_mime));
     }
     // int32 kRecorderVideoProfile = "android.media.mediarecorder.video-encoder-profile";
     int32_t videoProfile = -1;
@@ -183,10 +183,6 @@
         ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
     }
 
-    // must free the strings that we were given
-    free(audio_mime);
-    free(video_mime);
-
     return true;
 }
 
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index f668c33..6a82b1b 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -21,6 +21,7 @@
 #include "minijail.h"
 
 #include <binder/ProcessState.h>
+#include <cutils/properties.h>
 #include <hidl/HidlTransportSupport.h>
 #include <media/stagefright/omx/1.0/Omx.h>
 #include <media/stagefright/omx/1.0/OmxStore.h>
@@ -57,7 +58,8 @@
     } else {
         LOG(INFO) << "IOmx HAL service created.";
     }
-    sp<IOmxStore> omxStore = new implementation::OmxStore(omx);
+    sp<IOmxStore> omxStore = new implementation::OmxStore(
+            property_get_int64("vendor.media.omx", 1) ? omx : nullptr);
     if (omxStore == nullptr) {
         LOG(ERROR) << "Cannot create IOmxStore HAL service.";
     } else if (omxStore->registerAsService() != OK) {
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index 3e94596..9f03964 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -20,6 +20,10 @@
     MediaDrmService.cpp \
     main_mediadrmserver.cpp
 
+LOCAL_HEADER_LIBRARIES:= \
+    libmedia_headers \
+    libmediadrm_headers
+
 LOCAL_SHARED_LIBRARIES:= \
     libbinder \
     liblog \
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index b812244..e906500 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -8,6 +8,7 @@
     srcs: ["MediaExtractorService.cpp"],
 
     shared_libs: [
+        "libdatasource",
         "libmedia",
         "libstagefright",
         "libbinder",
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 36e084b..6239fb2 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -20,8 +20,8 @@
 
 #include <utils/Vector.h>
 
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaExtractorFactory.h>
 #include <media/stagefright/RemoteDataSource.h>
@@ -55,7 +55,7 @@
 
 sp<IDataSource> MediaExtractorService::makeIDataSource(int fd, int64_t offset, int64_t length)
 {
-    sp<DataSource> source = DataSourceFactory::CreateFromFd(fd, offset, length);
+    sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromFd(fd, offset, length);
     return CreateIDataSourceFromDataSource(source);
 }
 
diff --git a/services/medialog/Android.bp b/services/medialog/Android.bp
index bee5d25..74b63d5 100644
--- a/services/medialog/Android.bp
+++ b/services/medialog/Android.bp
@@ -6,6 +6,10 @@
         "MediaLogService.cpp",
     ],
 
+    header_libs: [
+        "libmedia_headers",
+    ],
+
     shared_libs: [
         "libaudioutils",
         "libbinder",