Merge "AudioPolicy: Add unit tests for the MSD use cases"
diff --git a/apex/Android.bp b/apex/Android.bp
index 05cc2c5..604b268 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -31,8 +31,25 @@
     key: "com.android.media.key",
 }
 
+apex {
+    name: "com.android.media.swcodec",
+    compile_multilib: "32",
+    manifest: "manifest_codec.json",
+    native_shared_libs: [
+        "libmedia_codecserviceregistrant",
+    ],
+    use_vendor: true,
+    key: "com.android.media.swcodec.key",
+}
+
 apex_key {
     name: "com.android.media.key",
     public_key: "com.android.media.avbpubkey",
     private_key: "com.android.media.pem",
 }
+
+apex_key {
+    name: "com.android.media.swcodec.key",
+    public_key: "com.android.media.swcodec.avbpubkey",
+    private_key: "com.android.media.swcodec.pem",
+}
diff --git a/apex/com.android.media.swcodec.avbpubkey b/apex/com.android.media.swcodec.avbpubkey
new file mode 100644
index 0000000..0459723
--- /dev/null
+++ b/apex/com.android.media.swcodec.avbpubkey
Binary files differ
diff --git a/apex/com.android.media.swcodec.pem b/apex/com.android.media.swcodec.pem
new file mode 100644
index 0000000..e379cd3
--- /dev/null
+++ b/apex/com.android.media.swcodec.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEAvB6lOEEOR58KMcFlayEZjsXuPgcfHi/OPxcvfpiGLCpOcK3l
+OPChWUvDRcIHMB7BO+Csfxs0HgsHvvZfNyoNIm99WcjFbboiO7WrBBArIszPr14X
+cfY2NxzT9LBj+EqAnbdL+4OQW1/npLHNE0qtDcxL71ipbjSuKNb58E9qGL0KwvkS
+fwwueWj++bg/iz7dq0mz7iKpnxYscNm4RhJjqcG2Usmg4Ejhr8h5UmOUmTJbObC/
+vzClXQqeeuzS8NTtGVgQ/CI9gC2WN9upq2p/2T7P4U3o3CWvBytUoLKR0UyC83ey
+S8XJgOa42uWR3T/eJOI1ZS4H6Srg1o2XC8Yb8EprFI/NM6/+/5DX/FgDimsslAP6
+Qq4+pSte9v/FjWGqy7QBQaefFRGRuS63xHcSZhXC9J2CFdnxo8+65QT8r4yfQEei
+Ax/0Q94yB7VIL1pIJxHEonKjtd3iKdFEKQzADJ3edsmtHybERdJKCxcm9QIrDCsC
+4YVT9nX0OoC9RD5d5EVD7W5I6eEnRu6igrKIKgUVppeYFQNZD+o+eiNJa4yoggRl
+h8sT0/xLKjMRxAQ7fafi1j+LB2O7UgJmIDDAnidq8Aoz7h3pNi139rNWrjNfwhus
+nMcZvL9dTVv26JWeESHP/zAfAX7j1rfkDwR02ocRLquwEUs1+UHA27Wi1bMCAwEA
+AQKCAgAO3PT83tb7/arWh4s1zaWxTB4otHNW9Tv8bB6KiA6Bys3rxTGJMCnvXjcN
+eekLekKWMoguer3BaemwwtJ/D0l+YQSsZVqD8uLliNL8PTLLSxdVqb98d5GNBTAR
+8yXS5kAHNgZA1wI+1fL9ZjbnwUyu/Gc7f+vTE0J3Y5TX0c52KemBwiAd/Z5mZU9P
+96i9nbfx4p7ev8pbEWttdyZCEw3gybdYDyowzlFWjCZZxhhlij7+7eIYfwVxtncT
+C0cXVBtvly+wXBwz1mY5/5cGPiHfzkCqcndlfWy4ykmjcLhoqvzls51Ys0Xac2BD
+m0PNEVDB5UWGuv5RA9xD12gJvBtU3D7ggMw6C5RcXJT+jSYmSFtD2klWi+It8A/N
+Hv42soKskt6JqYAWE1cvJ3PEqH9ASEJNq2R0Z/PmuM000UJyzU9KId3SNwjXA1Xc
+Kn9hRga4uf9elHTjkTDt79/8+Xv7hjer9sF/S/np7g04rUjIWkuFkC/7NK2tQSh1
+mljV1sD9SF4DPfVK75LwJJaQUlI7TtGd5KJ7FzZwvb+w8ODrpW3hkt6FcI6KwE/a
+QT1T2Z9DknXJSYNdWGrj6vMHsYMiyz8IdAHSCrOB6eXCQxpitbn6W71Raw7f9UaZ
+VDK5AhTU493hkGj1no4cJwecXInMigg/c4ywk2Ibh6IV8O0nkQKCAQEA2+dQQ0IF
+vvVgmQ2WxHBD7M2mbOyf43YBY6Ka6oPBNGPVpZE8X8LoTavQLV+SgCkH8T6gY7XS
+5L4Ze0JFxfua0o1rm6+L2XrOx5F/A2Y40YcPclEik5h1woSwH/J1iHGiEhY8Nqeu
+9GCvjQojkgXx/Rn3Nz+lpvZ329O3H85RWWGF0l60RwLOkig0ZwUb619t8affmGIl
+sxdDv2nfy7OtJX8iGDua7Kf64dvVWQKKtACWkARrlkcWX3uoESxkpSDxue+z7ndH
+o7uHLfM8Tx+Rn+QvYWuRW5TPLbEDMbIYrX65ISt2r/T7v/04XdAC8YpCQRytlqPI
+fpDm15htyHBizQKCAQEA2v+5otRoY56JduISaVGlsJ/IbvKzDAIyWmM14EpRCR5E
+lu+MpTcRAiFQAbHGXr1tMlTFdVFD090WAzIKaKtADFVLXobIHeGspnRCq5OpVp9W
+RvLtVwLxflHAc2yN9/LNtnBqHUgt+S01LBPElybdGHQRTtqAKXhkp31sM21O34Go
+Pri/IxgupWxykMaW44Kig1Cr5DKvc8cwUsGuyDdJm8oBQeNPTMWqSnXtqoTWSaYg
+2kxiMTFokrkSXgufb8wng6OXt/QelywrhG3hAsldPO3GdKidDSxhWZSgpUXXFdAX
+y4GO0IcRJBF/WJtYTYtR+l84nQA2/1Ye4ujFlT0afwKCAQEAmXrXpSm2cvI2CnzW
+hqJIdkWOa6W3bn1VOOIrt5Rfy54GZnl4pumVU2igcpqq2HJKzdDFBvLHj8kyZbn6
+ktUp2NzFhzK9q/uvyNA+0vOMoojeeg4w0MzvG+WaO6Hw8FtHH9KPEiJ01LGKtSin
+bOpjXCC8T75HcsHBJBefTz6jvnt3eD2LG6jU3mPbNy/0rZG8XZaqU2PlJhsNuNI/
+VaBBL9OMy1cGqTgQvYS+YlKI1ls2uqurH4bcEaZvxhSy5iGZNQodDkoIITnofmSu
+6haBgBQ2EYuPN1kkRKKwNQY1fRneQk1gmCynbPdiWO+urkCuP12xtlr3u4aM51rG
+/Meb3QKCAQEA12SxZm9XhLOHLIBJ74A4YLGm50iZxXPbpn7xnHo7naZBe9p8EHtK
+pTeygxggrUnOPrSVyT92YMiQP/BVwIC+a+LwUDZsWMd/ke/DKxH+eY4Zw4pm2S+x
+6bXqfRwFvhr3LTr/g3FcljlalNGUh73Xs5dk9pN9fkxFY16+rw4Rh0709Uur4o6E
+QnuZar+H5Ji10kXj6nvXiR4ebybEC3QlV66k8fLqKe44AShf61jfkmxs34hFA3E/
+EyAn6ouv8rtvGdArBuh5teHho0yXBLCcnbKXgGHepfhCf2LpZeR9GZ0j6iqxFnPh
+7gGvqKyReyNOK9y/x9tQPG6tzit3OcNxbQKCAQEAuDheDOSkXPopXMvLAKOHBIdZ
+rbQ7oFTDHt59gbucM7U8/l2YtaxuKOQFBLnzQa/amIkkrtklYwOsz8E24d7Nm39w
+ykLHwX0XrmjAm6M4XKmDv66a+kSnSV6LEbKZdjvXP02DV+tGeZ5VsnNvJDquxMsD
+fvRTspB8j8CpU96szekxl/tCRhqbdw/4kVTSj5BF++OaRRcJrAyj1B2qf1ynAZE1
+gUvVPkEYa914zcrxg9XIXT4M7yqB7i8KJegOtOtcWjJ7uTiP+638AvygJLMJnSrV
++HjFZWG6P9btZmLHSEBRvwGOAilp0qejXo866l0fmnlGy7ehKz8u3PzvnlPYjQ==
+-----END RSA PRIVATE KEY-----
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
new file mode 100644
index 0000000..e2bceec
--- /dev/null
+++ b/apex/manifest_codec.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.media.swcodec",
+  "version": 1
+}
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 321eb08..4e9b27d 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -167,19 +167,23 @@
 }
 
 OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+        const String16& physicalId,
         int surfaceSetID, bool isShared) {
     mGbps.push_back(gbp);
     mRotation = rotation;
     mSurfaceSetID = surfaceSetID;
     mIsDeferred = false;
     mIsShared = isShared;
+    mPhysicalCameraId = physicalId;
 }
 
 OutputConfiguration::OutputConfiguration(
         const std::vector<sp<IGraphicBufferProducer>>& gbps,
-    int rotation, int surfaceSetID,  int surfaceType, int width, int height, bool isShared)
+    int rotation, const String16& physicalCameraId, int surfaceSetID,  int surfaceType,
+    int width, int height, bool isShared)
   : mGbps(gbps), mRotation(rotation), mSurfaceSetID(surfaceSetID), mSurfaceType(surfaceType),
-    mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared) { }
+    mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared),
+    mPhysicalCameraId(physicalCameraId) { }
 
 status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
 
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 5b117fb..95c4f39 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -65,10 +65,12 @@
     OutputConfiguration(const android::Parcel& parcel);
 
     OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+            const String16& physicalCameraId,
             int surfaceSetID = INVALID_SET_ID, bool isShared = false);
 
     OutputConfiguration(const std::vector<sp<IGraphicBufferProducer>>& gbps,
-                        int rotation, int surfaceSetID = INVALID_SET_ID,
+                        int rotation, const String16& physicalCameraId,
+                        int surfaceSetID = INVALID_SET_ID,
                         int surfaceType = OutputConfiguration::SURFACE_TYPE_UNKNOWN, int width = 0,
                         int height = 0, bool isShared = false);
 
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index fd95296..540d84e 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -28,6 +28,8 @@
 #include <camera/NdkCameraCaptureSession.h>
 #include "impl/ACameraCaptureSession.h"
 
+#include "impl/ACameraCaptureSession.inc"
+
 using namespace android;
 
 EXPORT
@@ -82,7 +84,31 @@
         return ACAMERA_ERROR_SESSION_CLOSED;
     }
 
-    return session->capture(cbs, numRequests, requests, captureSequenceId);
+    return session->capture(
+            cbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_capture(
+        ACameraCaptureSession* session,
+        /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    ATRACE_CALL();
+    if (session == nullptr || requests == nullptr || numRequests < 1) {
+        ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+                __FUNCTION__, session, numRequests, requests);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    if (session->isClosed()) {
+        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+        *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    return session->capture(
+            lcbs, numRequests, requests, captureSequenceId);
 }
 
 EXPORT
@@ -107,6 +133,28 @@
 }
 
 EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest(
+        ACameraCaptureSession* session,
+        /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    ATRACE_CALL();
+    if (session == nullptr || requests == nullptr || numRequests < 1) {
+        ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+                __FUNCTION__, session, numRequests, requests);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    if (session->isClosed()) {
+        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+        *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    return session->setRepeatingRequest(lcbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
 camera_status_t ACameraCaptureSession_stopRepeating(ACameraCaptureSession* session) {
     ATRACE_CALL();
     if (session == nullptr) {
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index ef05e0b..98608da 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -129,6 +129,20 @@
 }
 
 EXPORT
+camera_status_t ACaptureSessionPhysicalOutput_create(
+        ACameraWindowType* window, const char* physicalId,
+        /*out*/ACaptureSessionOutput** out) {
+    ATRACE_CALL();
+    if (window == nullptr || physicalId == nullptr || out == nullptr) {
+        ALOGE("%s: Error: bad argument. window %p, physicalId %p, out %p",
+                __FUNCTION__, window, physicalId, out);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    *out = new ACaptureSessionOutput(window, false, physicalId);
+    return ACAMERA_OK;
+}
+
+EXPORT
 camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *out,
         ACameraWindowType* window) {
     ATRACE_CALL();
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
index 34ec2da..9a39ed8 100644
--- a/camera/ndk/NdkCameraMetadata.cpp
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -69,3 +69,20 @@
         metadata->decStrong((void*) ACameraMetadata_free);
     }
 }
+
+EXPORT
+bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,
+        /*out*/size_t* numPhysicalCameras, /*out*/const char*const** physicalCameraIds) {
+    ATRACE_CALL();
+    if (numPhysicalCameras == nullptr || physicalCameraIds == nullptr) {
+        ALOGE("%s: Invalid input: numPhysicalCameras %p, physicalCameraIds %p",
+                 __FUNCTION__, numPhysicalCameras, physicalCameraIds);
+        return false;
+    }
+    if (staticMetadata == nullptr) {
+        ALOGE("%s: Invalid input: staticMetadata is null.", __FUNCTION__);
+        return false;
+    }
+
+    return staticMetadata->isLogicalMultiCamera(numPhysicalCameras, physicalCameraIds);
+}
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index fb72bdb..d6f1412 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -107,47 +107,6 @@
     return ret;
 }
 
-camera_status_t
-ACameraCaptureSession::setRepeatingRequest(
-        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
-        int numRequests, ACaptureRequest** requests,
-        /*optional*/int* captureSequenceId) {
-    sp<acam::CameraDevice> dev = getDeviceSp();
-    if (dev == nullptr) {
-        ALOGE("Error: Device associated with session %p has been closed!", this);
-        return ACAMERA_ERROR_SESSION_CLOSED;
-    }
-
-    camera_status_t ret;
-    dev->lockDeviceForSessionOps();
-    {
-        Mutex::Autolock _l(mSessionLock);
-        ret = dev->setRepeatingRequestsLocked(
-                this, cbs, numRequests, requests, captureSequenceId);
-    }
-    dev->unlockDevice();
-    return ret;
-}
-
-camera_status_t ACameraCaptureSession::capture(
-        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
-        int numRequests, ACaptureRequest** requests,
-        /*optional*/int* captureSequenceId) {
-    sp<acam::CameraDevice> dev = getDeviceSp();
-    if (dev == nullptr) {
-        ALOGE("Error: Device associated with session %p has been closed!", this);
-        return ACAMERA_ERROR_SESSION_CLOSED;
-    }
-    camera_status_t ret;
-    dev->lockDeviceForSessionOps();
-    {
-        Mutex::Autolock _l(mSessionLock);
-        ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
-    }
-    dev->unlockDevice();
-    return ret;
-}
-
 camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSessionOutput *output) {
     sp<acam::CameraDevice> dev = getDeviceSp();
     if (dev == nullptr) {
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index 133c2c8..08a9226 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -17,6 +17,7 @@
 #define _ACAMERA_CAPTURE_SESSION_H
 
 #include <set>
+#include <string>
 #include <hardware/camera3.h>
 #include <camera/NdkCameraDevice.h>
 
@@ -29,8 +30,9 @@
 using namespace android;
 
 struct ACaptureSessionOutput {
-    explicit ACaptureSessionOutput(ACameraWindowType* window, bool isShared = false) :
-            mWindow(window), mIsShared(isShared) {};
+    explicit ACaptureSessionOutput(ACameraWindowType* window, bool isShared = false,
+            const char* physicalCameraId = "") :
+            mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {};
 
     bool operator == (const ACaptureSessionOutput& other) const {
         return mWindow == other.mWindow;
@@ -49,6 +51,7 @@
     std::set<ACameraWindowType *> mSharedWindows;
     bool           mIsShared;
     int            mRotation = CAMERA3_STREAM_ROTATION_0;
+    std::string mPhysicalCameraId;
 };
 #endif
 
@@ -88,13 +91,15 @@
 
     camera_status_t abortCaptures();
 
+    template<class T>
     camera_status_t setRepeatingRequest(
-            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            /*optional*/T* cbs,
             int numRequests, ACaptureRequest** requests,
             /*optional*/int* captureSequenceId);
 
+    template<class T>
     camera_status_t capture(
-            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            /*optional*/T* cbs,
             int numRequests, ACaptureRequest** requests,
             /*optional*/int* captureSequenceId);
 
diff --git a/camera/ndk/impl/ACameraCaptureSession.inc b/camera/ndk/impl/ACameraCaptureSession.inc
new file mode 100644
index 0000000..86bf8a5
--- /dev/null
+++ b/camera/ndk/impl/ACameraCaptureSession.inc
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#include "ACameraCaptureSession.h"
+
+#ifdef __ANDROID_VNDK__
+#include "ndk_vendor/impl/ACameraDeviceVendor.inc"
+#else
+#include "ACameraDevice.inc"
+#endif
+
+using namespace android;
+
+template <class T>
+camera_status_t
+ACameraCaptureSession::setRepeatingRequest(
+        /*optional*/T* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    sp<acam::CameraDevice> dev = getDeviceSp();
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    camera_status_t ret;
+    dev->lockDeviceForSessionOps();
+    {
+        Mutex::Autolock _l(mSessionLock);
+        ret = dev->setRepeatingRequestsLocked(
+                this, cbs, numRequests, requests, captureSequenceId);
+    }
+    dev->unlockDevice();
+    return ret;
+}
+
+template <class T>
+camera_status_t ACameraCaptureSession::capture(
+        /*optional*/T* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    sp<acam::CameraDevice> dev = getDeviceSp();
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+    camera_status_t ret;
+    dev->lockDeviceForSessionOps();
+    {
+        Mutex::Autolock _l(mSessionLock);
+        ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
+    }
+    dev->unlockDevice();
+    return ret;
+}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 657d41f..d8a5765 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -20,13 +20,14 @@
 #include <vector>
 #include <inttypes.h>
 #include <android/hardware/ICameraService.h>
-#include <camera2/SubmitInfo.h>
 #include <gui/Surface.h>
 #include "ACameraDevice.h"
 #include "ACameraMetadata.h"
 #include "ACaptureRequest.h"
 #include "ACameraCaptureSession.h"
 
+#include "ACameraCaptureSession.inc"
+
 namespace android {
 namespace acam {
 
@@ -39,6 +40,7 @@
 const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
 const char* CameraDevice::kTimeStampKey      = "TimeStamp";
 const char* CameraDevice::kCaptureResultKey  = "CaptureResult";
+const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult";
 const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
 const char* CameraDevice::kSequenceIdKey     = "SequenceId";
 const char* CameraDevice::kFrameNumberKey    = "FrameNumber";
@@ -190,106 +192,6 @@
     return ACAMERA_OK;
 }
 
-camera_status_t
-CameraDevice::captureLocked(
-        sp<ACameraCaptureSession> session,
-        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
-        int numRequests, ACaptureRequest** requests,
-        /*optional*/int* captureSequenceId) {
-    return submitRequestsLocked(
-            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
-}
-
-camera_status_t
-CameraDevice::setRepeatingRequestsLocked(
-        sp<ACameraCaptureSession> session,
-        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
-        int numRequests, ACaptureRequest** requests,
-        /*optional*/int* captureSequenceId) {
-    return submitRequestsLocked(
-            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
-}
-
-camera_status_t
-CameraDevice::submitRequestsLocked(
-        sp<ACameraCaptureSession> session,
-        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
-        int numRequests, ACaptureRequest** requests,
-        /*optional*/int* captureSequenceId,
-        bool isRepeating) {
-    camera_status_t ret = checkCameraClosedOrErrorLocked();
-    if (ret != ACAMERA_OK) {
-        ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
-        return ret;
-    }
-
-    // Form two vectors of capture request, one for internal tracking
-    std::vector<hardware::camera2::CaptureRequest> requestList;
-    Vector<sp<CaptureRequest> > requestsV;
-    requestsV.setCapacity(numRequests);
-    for (int i = 0; i < numRequests; i++) {
-        sp<CaptureRequest> req;
-        ret = allocateCaptureRequest(requests[i], req);
-        if (ret != ACAMERA_OK) {
-            ALOGE("Convert capture request to internal format failure! ret %d", ret);
-            return ret;
-        }
-        if (req->mSurfaceList.empty()) {
-            ALOGE("Capture request without output target cannot be submitted!");
-            return ACAMERA_ERROR_INVALID_PARAMETER;
-        }
-        requestList.push_back(*(req.get()));
-        requestsV.push_back(req);
-    }
-
-    if (isRepeating) {
-        ret = stopRepeatingLocked();
-        if (ret != ACAMERA_OK) {
-            ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
-            return ret;
-        }
-    }
-
-    binder::Status remoteRet;
-    hardware::camera2::utils::SubmitInfo info;
-    remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
-    int sequenceId = info.mRequestId;
-    int64_t lastFrameNumber = info.mLastFrameNumber;
-    if (sequenceId < 0) {
-        ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
-        return ACAMERA_ERROR_UNKNOWN;
-    }
-
-    CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
-    mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
-
-    if (isRepeating) {
-        // stopRepeating above should have cleanup repeating sequence id
-        if (mRepeatingSequenceId != REQUEST_ID_NONE) {
-            setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
-            return ACAMERA_ERROR_CAMERA_DEVICE;
-        }
-        mRepeatingSequenceId = sequenceId;
-    } else {
-        mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
-    }
-
-    if (mIdle) {
-        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
-        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
-        msg->setObject(kSessionSpKey, session);
-        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
-        postSessionMsgAndCleanup(msg);
-    }
-    mIdle = false;
-    mBusySession = session;
-
-    if (captureSequenceId) {
-        *captureSequenceId = sequenceId;
-    }
-    return ACAMERA_OK;
-}
-
 camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
@@ -325,8 +227,9 @@
         return ret;
     }
 
-    OutputConfiguration outConfig(iGBP, output->mRotation, OutputConfiguration::INVALID_SET_ID,
-            true);
+    String16 physicalId16(output->mPhysicalCameraId.c_str());
+    OutputConfiguration outConfig(iGBP, output->mRotation, physicalId16,
+            OutputConfiguration::INVALID_SET_ID, true);
 
     for (auto& anw : output->mSharedWindows) {
         ret = getIGBPfromAnw(anw, iGBP);
@@ -640,8 +543,9 @@
         if (ret != ACAMERA_OK) {
             return ret;
         }
+        String16 physicalId16(outConfig.mPhysicalCameraId.c_str());
         outputSet.insert(std::make_pair(
-                anw, OutputConfiguration(iGBP, outConfig.mRotation,
+                anw, OutputConfiguration(iGBP, outConfig.mRotation, physicalId16,
                         OutputConfiguration::INVALID_SET_ID, outConfig.mIsShared)));
     }
     auto addSet = outputSet;
@@ -829,7 +733,7 @@
     if (errorCode == hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER) {
         int32_t streamId = resultExtras.errorStreamId;
         ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
-                cbh.mCallbacks.onCaptureBufferLost;
+                cbh.mOnCaptureBufferLost;
         auto outputPairIt = mConfiguredOutputs.find(streamId);
         if (outputPairIt == mConfiguredOutputs.end()) {
             ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
@@ -846,7 +750,7 @@
                             getId(), anw, frameNumber);
 
                     sp<AMessage> msg = new AMessage(kWhatCaptureBufferLost, mHandler);
-                    msg->setPointer(kContextKey, cbh.mCallbacks.context);
+                    msg->setPointer(kContextKey, cbh.mContext);
                     msg->setObject(kSessionSpKey, session);
                     msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
                     msg->setObject(kCaptureRequestKey, request);
@@ -858,7 +762,7 @@
         }
     } else { // Handle other capture failures
         // Fire capture failure callback if there is one registered
-        ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
+        ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed;
         sp<CameraCaptureFailure> failure(new CameraCaptureFailure());
         failure->frameNumber = frameNumber;
         // TODO: refine this when implementing flush
@@ -868,7 +772,7 @@
                 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT);
 
         sp<AMessage> msg = new AMessage(kWhatCaptureFail, mHandler);
-        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setPointer(kContextKey, cbh.mContext);
         msg->setObject(kSessionSpKey, session);
         msg->setPointer(kCallbackFpKey, (void*) onError);
         msg->setObject(kCaptureRequestKey, request);
@@ -890,6 +794,7 @@
         case kWhatSessionStateCb:
         case kWhatCaptureStart:
         case kWhatCaptureResult:
+        case kWhatLogicalCaptureResult:
         case kWhatCaptureFail:
         case kWhatCaptureSeqEnd:
         case kWhatCaptureSeqAbort:
@@ -960,6 +865,7 @@
         case kWhatSessionStateCb:
         case kWhatCaptureStart:
         case kWhatCaptureResult:
+        case kWhatLogicalCaptureResult:
         case kWhatCaptureFail:
         case kWhatCaptureSeqEnd:
         case kWhatCaptureSeqAbort:
@@ -977,6 +883,7 @@
             switch (msg->what()) {
                 case kWhatCaptureStart:
                 case kWhatCaptureResult:
+                case kWhatLogicalCaptureResult:
                 case kWhatCaptureFail:
                 case kWhatCaptureBufferLost:
                     found = msg->findObject(kCaptureRequestKey, &obj);
@@ -1048,6 +955,64 @@
                     freeACaptureRequest(request);
                     break;
                 }
+                case kWhatLogicalCaptureResult:
+                {
+                    ACameraCaptureSession_logicalCamera_captureCallback_result onResult;
+                    found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+                    if (!found) {
+                        ALOGE("%s: Cannot find logicalCamera capture result callback!",
+                                __FUNCTION__);
+                        return;
+                    }
+                    if (onResult == nullptr) {
+                        return;
+                    }
+
+                    found = msg->findObject(kCaptureResultKey, &obj);
+                    if (!found) {
+                        ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+                        return;
+                    }
+                    sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
+
+                    found = msg->findObject(kPhysicalCaptureResultKey, &obj);
+                    if (!found) {
+                        ALOGE("%s: Cannot find physical capture result!", __FUNCTION__);
+                        return;
+                    }
+                    sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+                            static_cast<ACameraPhysicalCaptureResultInfo*>(obj.get()));
+                    std::vector<PhysicalCaptureResultInfo>& physicalResultInfo =
+                            physicalResult->mPhysicalResultInfo;
+
+                    std::vector<std::string> physicalCameraIds;
+                    std::vector<sp<ACameraMetadata>> physicalMetadataCopy;
+                    for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+                        String8 physicalId8(physicalResultInfo[i].mPhysicalCameraId);
+                        physicalCameraIds.push_back(physicalId8.c_str());
+
+                        CameraMetadata clone = physicalResultInfo[i].mPhysicalCameraMetadata;
+                        clone.update(ANDROID_SYNC_FRAME_NUMBER,
+                                &physicalResult->mFrameNumber, /*data_count*/1);
+                        sp<ACameraMetadata> metadata =
+                                new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+                        physicalMetadataCopy.push_back(metadata);
+                    }
+
+                    std::vector<const char*> physicalCameraIdPtrs;
+                    std::vector<const ACameraMetadata*> physicalMetadataCopyPtrs;
+                    for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+                        physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str());
+                        physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
+                    }
+
+                    ACaptureRequest* request = allocateACaptureRequest(requestSp);
+                    (*onResult)(context, session.get(), request, result.get(),
+                            physicalResultInfo.size(), physicalCameraIdPtrs.data(),
+                            physicalMetadataCopyPtrs.data());
+                    freeACaptureRequest(request);
+                    break;
+                }
                 case kWhatCaptureFail:
                 {
                     ACameraCaptureSession_captureCallback_failed onFail;
@@ -1158,12 +1123,34 @@
 }
 
 CameraDevice::CallbackHolder::CallbackHolder(
-    sp<ACameraCaptureSession>          session,
-    const Vector<sp<CaptureRequest> >& requests,
-    bool                               isRepeating,
-    ACameraCaptureSession_captureCallbacks* cbs) :
-    mSession(session), mRequests(requests),
-    mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {}
+        sp<ACameraCaptureSession>          session,
+        const Vector<sp<CaptureRequest> >& requests,
+        bool                               isRepeating,
+        ACameraCaptureSession_captureCallbacks* cbs) :
+        mSession(session), mRequests(requests),
+        mIsRepeating(isRepeating),
+        mIsLogicalCameraCallback(false) {
+    initCaptureCallbacks(cbs);
+
+    if (cbs != nullptr) {
+        mOnCaptureCompleted = cbs->onCaptureCompleted;
+    }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+        sp<ACameraCaptureSession>          session,
+        const Vector<sp<CaptureRequest> >& requests,
+        bool                               isRepeating,
+        ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
+        mSession(session), mRequests(requests),
+        mIsRepeating(isRepeating),
+        mIsLogicalCameraCallback(true) {
+    initCaptureCallbacks(lcbs);
+
+    if (lcbs != nullptr) {
+        mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+    }
+}
 
 void
 CameraDevice::checkRepeatingSequenceCompleteLocked(
@@ -1180,9 +1167,9 @@
         mSequenceCallbackMap.erase(cbIt);
         // send seq aborted callback
         sp<AMessage> msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
-        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setPointer(kContextKey, cbh.mContext);
         msg->setObject(kSessionSpKey, cbh.mSession);
-        msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
+        msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted);
         msg->setInt32(kSequenceIdKey, sequenceId);
         postSessionMsgAndCleanup(msg);
     } else {
@@ -1230,9 +1217,9 @@
             mSequenceCallbackMap.erase(cbIt);
             // send seq complete callback
             sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
-            msg->setPointer(kContextKey, cbh.mCallbacks.context);
+            msg->setPointer(kContextKey, cbh.mContext);
             msg->setObject(kSessionSpKey, cbh.mSession);
-            msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted);
+            msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
             msg->setInt32(kSequenceIdKey, sequenceId);
             msg->setInt64(kFrameNumberKey, lastFrameNumber);
 
@@ -1389,7 +1376,7 @@
     auto it = dev->mSequenceCallbackMap.find(sequenceId);
     if (it != dev->mSequenceCallbackMap.end()) {
         CallbackHolder cbh = (*it).second;
-        ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted;
+        ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
         sp<ACameraCaptureSession> session = cbh.mSession;
         if ((size_t) burstId >= cbh.mRequests.size()) {
             ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1398,7 +1385,7 @@
         }
         sp<CaptureRequest> request = cbh.mRequests[burstId];
         sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
-        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setPointer(kContextKey, cbh.mContext);
         msg->setObject(kSessionSpKey, session);
         msg->setPointer(kCallbackFpKey, (void*) onStart);
         msg->setObject(kCaptureRequestKey, request);
@@ -1413,7 +1400,6 @@
         const CameraMetadata& metadata,
         const CaptureResultExtras& resultExtras,
         const std::vector<PhysicalCaptureResultInfo>& physicalResultInfos) {
-    (void) physicalResultInfos;
     binder::Status ret = binder::Status::ok();
 
     sp<CameraDevice> dev = mDevice.promote();
@@ -1449,9 +1435,6 @@
     auto it = dev->mSequenceCallbackMap.find(sequenceId);
     if (it != dev->mSequenceCallbackMap.end()) {
         CallbackHolder cbh = (*it).second;
-        ACameraCaptureSession_captureCallback_result onResult = isPartialResult ?
-                cbh.mCallbacks.onCaptureProgressed :
-                cbh.mCallbacks.onCaptureCompleted;
         sp<ACameraCaptureSession> session = cbh.mSession;
         if ((size_t) burstId >= cbh.mRequests.size()) {
             ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1461,13 +1444,27 @@
         sp<CaptureRequest> request = cbh.mRequests[burstId];
         sp<ACameraMetadata> result(new ACameraMetadata(
                 metadataCopy.release(), ACameraMetadata::ACM_RESULT));
+        sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+                new ACameraPhysicalCaptureResultInfo(physicalResultInfos, frameNumber));
 
-        sp<AMessage> msg = new AMessage(kWhatCaptureResult, dev->mHandler);
-        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        sp<AMessage> msg = new AMessage(
+                cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult,
+                dev->mHandler);
+        msg->setPointer(kContextKey, cbh.mContext);
         msg->setObject(kSessionSpKey, session);
-        msg->setPointer(kCallbackFpKey, (void*) onResult);
         msg->setObject(kCaptureRequestKey, request);
         msg->setObject(kCaptureResultKey, result);
+        if (isPartialResult) {
+            msg->setPointer(kCallbackFpKey,
+                    (void *)cbh.mOnCaptureProgressed);
+        } else if (cbh.mIsLogicalCameraCallback) {
+            msg->setPointer(kCallbackFpKey,
+                    (void *)cbh.mOnLogicalCameraCaptureCompleted);
+            msg->setObject(kPhysicalCaptureResultKey, physicalResult);
+        } else {
+            msg->setPointer(kCallbackFpKey,
+                    (void *)cbh.mOnCaptureCompleted);
+        }
         dev->postSessionMsgAndCleanup(msg);
     }
 
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 8f56d3f..d0f363b 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -21,6 +21,7 @@
 #include <set>
 #include <atomic>
 #include <utility>
+#include <vector>
 #include <utils/StrongPointer.h>
 #include <utils/Mutex.h>
 #include <utils/String8.h>
@@ -46,6 +47,16 @@
 // Wrap ACameraCaptureFailure so it can be ref-counted
 struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure {};
 
+// Wrap PhysicalCaptureResultInfo so that it can be ref-counted
+struct ACameraPhysicalCaptureResultInfo: public RefBase {
+    ACameraPhysicalCaptureResultInfo(const std::vector<PhysicalCaptureResultInfo>& info,
+            int64_t frameNumber) :
+        mPhysicalResultInfo(info), mFrameNumber(frameNumber) {}
+
+    std::vector<PhysicalCaptureResultInfo> mPhysicalResultInfo;
+    int64_t mFrameNumber;
+};
+
 class CameraDevice final : public RefBase {
   public:
     CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
@@ -109,19 +120,22 @@
     camera_status_t waitUntilIdleLocked();
 
 
+    template<class T>
     camera_status_t captureLocked(sp<ACameraCaptureSession> session,
-            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            /*optional*/T* cbs,
             int numRequests, ACaptureRequest** requests,
             /*optional*/int* captureSequenceId);
 
+    template<class T>
     camera_status_t setRepeatingRequestsLocked(sp<ACameraCaptureSession> session,
-            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            /*optional*/T* cbs,
             int numRequests, ACaptureRequest** requests,
             /*optional*/int* captureSequenceId);
 
+    template<class T>
     camera_status_t submitRequestsLocked(
             sp<ACameraCaptureSession> session,
-            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            /*optional*/T* cbs,
             int numRequests, ACaptureRequest** requests,
             /*out*/int* captureSequenceId,
             bool isRepeating);
@@ -192,6 +206,7 @@
         // Capture callbacks
         kWhatCaptureStart,     // onCaptureStarted
         kWhatCaptureResult,    // onCaptureProgressed, onCaptureCompleted
+        kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted
         kWhatCaptureFail,      // onCaptureFailed
         kWhatCaptureSeqEnd,    // onCaptureSequenceCompleted
         kWhatCaptureSeqAbort,  // onCaptureSequenceAborted
@@ -207,6 +222,7 @@
     static const char* kCaptureRequestKey;
     static const char* kTimeStampKey;
     static const char* kCaptureResultKey;
+    static const char* kPhysicalCaptureResultKey;
     static const char* kCaptureFailureKey;
     static const char* kSequenceIdKey;
     static const char* kFrameNumberKey;
@@ -245,19 +261,46 @@
                        const Vector<sp<CaptureRequest> >& requests,
                        bool                               isRepeating,
                        ACameraCaptureSession_captureCallbacks* cbs);
+        CallbackHolder(sp<ACameraCaptureSession>          session,
+                       const Vector<sp<CaptureRequest> >& requests,
+                       bool                               isRepeating,
+                       ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
 
-        static ACameraCaptureSession_captureCallbacks fillCb(
-                ACameraCaptureSession_captureCallbacks* cbs) {
+        template <class T>
+        void initCaptureCallbacks(T* cbs) {
+            mContext = nullptr;
+            mOnCaptureStarted = nullptr;
+            mOnCaptureProgressed = nullptr;
+            mOnCaptureCompleted = nullptr;
+            mOnLogicalCameraCaptureCompleted = nullptr;
+            mOnCaptureFailed = nullptr;
+            mOnCaptureSequenceCompleted = nullptr;
+            mOnCaptureSequenceAborted = nullptr;
+            mOnCaptureBufferLost = nullptr;
             if (cbs != nullptr) {
-                return *cbs;
+                mContext = cbs->context;
+                mOnCaptureStarted = cbs->onCaptureStarted;
+                mOnCaptureProgressed = cbs->onCaptureProgressed;
+                mOnCaptureFailed = cbs->onCaptureFailed;
+                mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted;
+                mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted;
+                mOnCaptureBufferLost = cbs->onCaptureBufferLost;
             }
-            return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
         }
-
         sp<ACameraCaptureSession>   mSession;
         Vector<sp<CaptureRequest> > mRequests;
         const bool                  mIsRepeating;
-        ACameraCaptureSession_captureCallbacks mCallbacks;
+        const bool                  mIsLogicalCameraCallback;
+
+        void*                       mContext;
+        ACameraCaptureSession_captureCallback_start mOnCaptureStarted;
+        ACameraCaptureSession_captureCallback_result mOnCaptureProgressed;
+        ACameraCaptureSession_captureCallback_result mOnCaptureCompleted;
+        ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted;
+        ACameraCaptureSession_captureCallback_failed mOnCaptureFailed;
+        ACameraCaptureSession_captureCallback_sequenceEnd mOnCaptureSequenceCompleted;
+        ACameraCaptureSession_captureCallback_sequenceAbort mOnCaptureSequenceAborted;
+        ACameraCaptureSession_captureCallback_bufferLost mOnCaptureBufferLost;
     };
     // sequence id -> callbacks map
     std::map<int, CallbackHolder> mSequenceCallbackMap;
diff --git a/camera/ndk/impl/ACameraDevice.inc b/camera/ndk/impl/ACameraDevice.inc
new file mode 100644
index 0000000..1fc5352
--- /dev/null
+++ b/camera/ndk/impl/ACameraDevice.inc
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+#include <vector>
+#include <inttypes.h>
+#include "ACameraDevice.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "ACameraCaptureSession.h"
+
+namespace android {
+namespace acam {
+
+template<class T>
+camera_status_t
+CameraDevice::captureLocked(
+        sp<ACameraCaptureSession> session,
+        /*optional*/T* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    return submitRequestsLocked(
+            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
+}
+
+template<class T>
+camera_status_t
+CameraDevice::setRepeatingRequestsLocked(
+        sp<ACameraCaptureSession> session,
+        /*optional*/T* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    return submitRequestsLocked(
+            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
+}
+
+template<class T>
+camera_status_t CameraDevice::submitRequestsLocked(
+        sp<ACameraCaptureSession> session,
+        /*optional*/T* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId,
+        bool isRepeating) {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
+        return ret;
+    }
+
+    // Form two vectors of capture request, one for internal tracking
+    std::vector<hardware::camera2::CaptureRequest> requestList;
+    Vector<sp<CaptureRequest> > requestsV;
+    requestsV.setCapacity(numRequests);
+    for (int i = 0; i < numRequests; i++) {
+        sp<CaptureRequest> req;
+        ret = allocateCaptureRequest(requests[i], req);
+        if (ret != ACAMERA_OK) {
+            ALOGE("Convert capture request to internal format failure! ret %d", ret);
+            return ret;
+        }
+        if (req->mSurfaceList.empty()) {
+            ALOGE("Capture request without output target cannot be submitted!");
+            return ACAMERA_ERROR_INVALID_PARAMETER;
+        }
+        requestList.push_back(*(req.get()));
+        requestsV.push_back(req);
+    }
+
+    if (isRepeating) {
+        ret = stopRepeatingLocked();
+        if (ret != ACAMERA_OK) {
+            ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+            return ret;
+        }
+    }
+
+    binder::Status remoteRet;
+    hardware::camera2::utils::SubmitInfo info;
+    remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
+    int sequenceId = info.mRequestId;
+    int64_t lastFrameNumber = info.mLastFrameNumber;
+    if (sequenceId < 0) {
+        ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+
+    CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
+    mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+
+    if (isRepeating) {
+        // stopRepeating above should have cleanup repeating sequence id
+        if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+            setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+            return ACAMERA_ERROR_CAMERA_DEVICE;
+        }
+        mRepeatingSequenceId = sequenceId;
+    } else {
+        mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+    }
+
+    if (mIdle) {
+        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+        postSessionMsgAndCleanup(msg);
+    }
+    mIdle = false;
+    mBusySession = session;
+
+    if (captureSequenceId) {
+        *captureSequenceId = sequenceId;
+    }
+    return ACAMERA_OK;
+}
+
+} // namespace acam
+} // namespace android
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 94b5713..c661233 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -50,6 +50,7 @@
         case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS:
         case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE:
         case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT:
+        case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA:
             return true;
         case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING:
         case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING:
@@ -79,11 +80,41 @@
         uint8_t capability = entry.data.u8[i];
         if (isNdkSupportedCapability(capability)) {
             capabilities.push(capability);
+
+            if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+                derivePhysicalCameraIds();
+            }
         }
     }
     mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
 }
 
+void
+ACameraMetadata::derivePhysicalCameraIds() {
+    ACameraMetadata_const_entry entry;
+    auto ret = getConstEntry(ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS, &entry);
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: Get ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS key failed. ret %d",
+                __FUNCTION__, ret);
+        return;
+    }
+
+    const uint8_t* ids = entry.data.u8;
+    size_t start = 0;
+    for (size_t i = 0; i < entry.count; ++i) {
+        if (ids[i] == '\0') {
+            if (start != i) {
+                mStaticPhysicalCameraIds.push_back((const char*)ids+start);
+            }
+            start = i+1;
+        }
+    }
+
+    if (mStaticPhysicalCameraIds.size() < 2) {
+        ALOGW("%s: Logical multi-camera device only has %zu physical cameras",
+                __FUNCTION__, mStaticPhysicalCameraIds.size());
+    }
+}
 
 void
 ACameraMetadata::filterDurations(uint32_t tag) {
@@ -309,6 +340,27 @@
     return mData;
 }
 
+bool
+ACameraMetadata::isLogicalMultiCamera(size_t* count, const char*const** physicalCameraIds) const {
+    if (mType != ACM_CHARACTERISTICS) {
+        ALOGE("%s must be called for a static metadata!", __FUNCTION__);
+        return false;
+    }
+    if (count == nullptr || physicalCameraIds == nullptr) {
+        ALOGE("%s: Invalid input count: %p, physicalCameraIds: %p", __FUNCTION__,
+                count, physicalCameraIds);
+        return false;
+    }
+
+    if (mStaticPhysicalCameraIds.size() >= 2) {
+        *count = mStaticPhysicalCameraIds.size();
+        *physicalCameraIds = mStaticPhysicalCameraIds.data();
+        return true;
+    }
+
+    return false;
+}
+
 // TODO: some of key below should be hidden from user
 // ex: ACAMERA_REQUEST_ID and ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
 /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h
index f21dbaf..7049c4b 100644
--- a/camera/ndk/impl/ACameraMetadata.h
+++ b/camera/ndk/impl/ACameraMetadata.h
@@ -17,6 +17,7 @@
 #define _ACAMERA_METADATA_H
 
 #include <unordered_set>
+#include <vector>
 
 #include <sys/types.h>
 #include <utils/Mutex.h>
@@ -65,6 +66,7 @@
                             /*out*/const uint32_t** tags) const;
 
     const CameraMetadata& getInternalData() const;
+    bool isLogicalMultiCamera(size_t* count, const char* const** physicalCameraIds) const;
 
   private:
 
@@ -74,6 +76,7 @@
     void filterUnsupportedFeatures(); // Hide features not yet supported by NDK
     void filterStreamConfigurations(); // Hide input streams, translate hal format to NDK formats
     void filterDurations(uint32_t tag); // translate hal format to NDK formats
+    void derivePhysicalCameraIds(); // Derive array of physical ids.
 
     template<typename INTERNAL_T, typename NDK_T>
     camera_status_t updateImpl(uint32_t tag, uint32_t count, const NDK_T* data) {
@@ -112,6 +115,8 @@
     const ACAMERA_METADATA_TYPE mType;
 
     static std::unordered_set<uint32_t> sSystemTags;
+
+    std::vector<const char*> mStaticPhysicalCameraIds;
 };
 
 #endif // _ACAMERA_METADATA_H
diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h
index 1244582..d13a818 100644
--- a/camera/ndk/include/camera/NdkCameraCaptureSession.h
+++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h
@@ -643,6 +643,103 @@
         ACaptureSessionOutput* output) __INTRODUCED_IN(28);
 #endif /* __ANDROID_API__ >= 28 */
 
+#if __ANDROID_API__ >= 29
+/**
+ * The definition of final capture result callback with logical multi-camera support.
+ *
+ * This has the same functionality as final ACameraCaptureSession_captureCallback_result, with
+ * added ability to return physical camera result metadata within a logical multi-camera.
+ *
+ * For a logical multi-camera, this function will be called with the Id and result metadata
+ * of the underlying physical cameras, which the corresponding capture request contains targets for.
+ * If the capture request doesn't contain targets specific to any physical camera, or the current
+ * camera device isn't a logical multi-camera, physicalResultCount will be 0.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param request The capture request of interest. Note that this pointer points to a copy of
+ *                capture request sent by application, so the address is different to what
+ *                application sent but the content will match. This request will be freed by
+ *                framework immediately after this callback returns.
+ * @param result The capture result metadata reported by camera device. The memory is managed by
+ *                camera framework. Do not access this pointer after this callback returns.
+ * @param physicalResultCount The number of physical camera result metadata
+ * @param physicalCameraIds The array of physical camera IDs on which the
+ *                physical result metadata are reported.
+ * @param physicalResults The array of capture result metadata reported by the
+ *                physical camera devices.
+ */
+typedef void (*ACameraCaptureSession_logicalCamera_captureCallback_result)(
+        void* context, ACameraCaptureSession* session,
+        ACaptureRequest* request, const ACameraMetadata* result,
+        size_t physicalResultCount, const char** physicalCameraIds,
+        const ACameraMetadata** physicalResults);
+
+/**
+ * This has the same functionality as ACameraCaptureSession_captureCallbacks,
+ * with the exception that an onLogicalCameraCaptureCompleted callback is
+ * used, instead of onCaptureCompleted, to support logical multi-camera.
+ */
+typedef struct ACameraCaptureSession_logicalCamera_captureCallbacks {
+    /**
+     * Same as ACameraCaptureSession_captureCallbacks
+     */
+    void*                                               context;
+    ACameraCaptureSession_captureCallback_start         onCaptureStarted;
+    ACameraCaptureSession_captureCallback_result        onCaptureProgressed;
+
+    /**
+     * This callback is called when an image capture has fully completed and all the
+     * result metadata is available. For a logical multi-camera, this callback
+     * also returns the result metadata for all physical cameras being
+     * explicitly requested on.
+     *
+     * <p>This callback will always fire after the last {@link onCaptureProgressed};
+     * in other words, no more partial results will be delivered once the completed result
+     * is available.</p>
+     *
+     * <p>For performance-intensive use-cases where latency is a factor, consider
+     * using {@link onCaptureProgressed} instead.</p>
+     *
+     * <p>Note that the ACaptureRequest pointer in the callback will not match what application has
+     * submitted, but the contents the ACaptureRequest will match what application submitted.</p>
+     */
+    ACameraCaptureSession_logicalCamera_captureCallback_result onLogicalCameraCaptureCompleted;
+
+    /**
+     * Same as ACameraCaptureSession_captureCallbacks
+     */
+    ACameraCaptureSession_captureCallback_failed        onCaptureFailed;
+    ACameraCaptureSession_captureCallback_sequenceEnd   onCaptureSequenceCompleted;
+    ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted;
+    ACameraCaptureSession_captureCallback_bufferLost    onCaptureBufferLost;
+} ACameraCaptureSession_logicalCamera_captureCallbacks;
+
+/**
+ * This has the same functionality as ACameraCaptureSession_capture, with added
+ * support for logical multi-camera where the capture callbacks supports result metadata for
+ * physical cameras.
+ */
+camera_status_t ACameraCaptureSession_logicalCamera_capture(
+        ACameraCaptureSession* session,
+        /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) __INTRODUCED_IN(29);
+
+/**
+ * This has the same functionality as ACameraCaptureSession_setRepeatingRequest, with added
+ * support for logical multi-camera where the capture callbacks supports result metadata for
+ * physical cameras.
+ */
+camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest(
+        ACameraCaptureSession* session,
+        /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
 __END_DECLS
 
 #endif /* _NDK_CAMERA_CAPTURE_SESSION_H */
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 4fe43d5..26af4f8 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -765,6 +765,36 @@
 
 #endif /* __ANDROID_API__ >= 28 */
 
+#if __ANDROID_API__ >= 29
+
+/**
+ * Create a ACaptureSessionOutput object used for streaming from a physical
+ * camera as part of a logical camera device.
+ *
+ * <p>The ACaptureSessionOutput is used in {@link ACaptureSessionOutputContainer_add} method to add
+ * an output {@link ANativeWindow} to ACaptureSessionOutputContainer. Use
+ * {@link ACaptureSessionOutput_free} to free the object and its memory after application no longer
+ * needs the {@link ACaptureSessionOutput}.</p>
+ *
+ * @param anw the {@link ANativeWindow} to be associated with the {@link ACaptureSessionOutput}
+ * @param physicalId the Id of the physical camera this output is associated
+ *                  with.
+ * @param output the output {@link ACaptureSessionOutput} will be stored here if the
+ *                  method call succeeds.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds. The created container will be
+ *                                filled in the output argument.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if anw, physicalId or output is NULL.</li></ul>
+ *
+ * @see ACaptureSessionOutputContainer_add
+ */
+camera_status_t ACaptureSessionPhysicalOutput_create(
+        ACameraWindowType* anw, const char* physicalId,
+        /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
 __END_DECLS
 
 #endif /* _NDK_CAMERA_DEVICE_H */
diff --git a/camera/ndk/include/camera/NdkCameraMetadata.h b/camera/ndk/include/camera/NdkCameraMetadata.h
index 611e270..9bbfb83 100644
--- a/camera/ndk/include/camera/NdkCameraMetadata.h
+++ b/camera/ndk/include/camera/NdkCameraMetadata.h
@@ -233,6 +233,28 @@
 
 #endif /* __ANDROID_API__ >= 24 */
 
+#if __ANDROID_API__ >= 29
+
+/**
+ * Helper function to check if a camera is logical multi-camera.
+ *
+ * <p> Check whether a camera device is a logical multi-camera based on its
+ * static metadata. If it is, also returns its physical sub camera Ids.</p>
+ *
+ * @param staticMetadata the static metadata of the camera being checked.
+ * @param numPhysicalCameras returns the number of physical cameras.
+ * @param physicalCameraIds returns the array of physical camera Ids backing this logical
+ *                          camera device. Note that this pointer is only valid
+ *                          during the lifetime of the staticMetadata object.
+ *
+ * @return true if this is a logical multi-camera, false otherwise.
+ */
+bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,
+        /*out*/size_t* numPhysicalCameras, /*out*/const char* const** physicalCameraIds)
+        __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
 __END_DECLS
 
 #endif /* _NDK_CAMERA_METADATA_H */
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index cb474f4..4bb74cb 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -5552,6 +5552,25 @@
     ACAMERA_DEPTH_END,
 
     /**
+     * <p>String containing the ids of the underlying physical cameras.</p>
+     *
+     * <p>Type: byte[n]</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+     * </ul></p>
+     *
+     * <p>For a logical camera, this is concatenation of all underlying physical camera ids.
+     * The null terminator for physical camera id must be preserved so that the whole string
+     * can be tokenized using '\0' to generate list of physical camera ids.</p>
+     * <p>For example, if the physical camera ids of the logical camera are "2" and "3", the
+     * value of this tag will be ['2', '\0', '3', '\0'].</p>
+     * <p>The number of physical camera ids must be no less than 2.</p>
+     */
+    ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS =                 // byte[n]
+            ACAMERA_LOGICAL_MULTI_CAMERA_START,
+    /**
      * <p>The accuracy of frame timestamp synchronization between physical cameras</p>
      *
      * <p>Type: byte (acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t)</p>
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index a29e96d..5a00022 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -2,9 +2,11 @@
   global:
     ACameraCaptureSession_abortCaptures;
     ACameraCaptureSession_capture;
+    ACameraCaptureSession_logicalCamera_capture; # introduced=29
     ACameraCaptureSession_close;
     ACameraCaptureSession_getDevice;
     ACameraCaptureSession_setRepeatingRequest;
+    ACameraCaptureSession_logicalCamera_setRepeatingRequest; # introduced=29
     ACameraCaptureSession_stopRepeating;
     ACameraCaptureSession_updateSharedOutput; # introduced=28
     ACameraDevice_close;
@@ -24,6 +26,7 @@
     ACameraMetadata_free;
     ACameraMetadata_getAllTags;
     ACameraMetadata_getConstEntry;
+    ACameraMetadata_isLogicalMultiCamera; # introduced=29
     ACameraOutputTarget_create;
     ACameraOutputTarget_free;
     ACaptureRequest_addTarget;
@@ -48,6 +51,7 @@
     ACaptureSessionSharedOutput_create; # introduced=28
     ACaptureSessionSharedOutput_add; # introduced=28
     ACaptureSessionSharedOutput_remove; # introduced=28
+    ACaptureSessionPhysicalOutput_create; # introduced=29
     ACaptureSessionOutput_free;
   local:
     *;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
index 8d9e90c..e1af8c1 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
+#include <string>
 #include "utils.h"
 
 struct ACaptureSessionOutput {
-    explicit ACaptureSessionOutput(native_handle_t* window, bool isShared = false) :
-            mWindow(window), mIsShared(isShared) {};
+    explicit ACaptureSessionOutput(native_handle_t* window, bool isShared = false,
+            const char* physicalCameraId = "") :
+            mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {};
 
     bool operator == (const ACaptureSessionOutput& other) const {
         return (mWindow == other.mWindow);
@@ -40,6 +42,7 @@
     std::set<android::acam::utils::native_handle_ptr_wrapper> mSharedWindows;
     bool           mIsShared;
     int            mRotation = CAMERA3_STREAM_ROTATION_0;
+    std::string mPhysicalCameraId;
 };
 
 
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 26e6b3c..f7863a5 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -29,6 +29,8 @@
 #include "ACaptureRequest.h"
 #include "utils.h"
 
+#include "ACameraCaptureSession.inc"
+
 using namespace android;
 
 namespace android {
@@ -47,6 +49,7 @@
 const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
 const char* CameraDevice::kTimeStampKey      = "TimeStamp";
 const char* CameraDevice::kCaptureResultKey  = "CaptureResult";
+const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult";
 const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
 const char* CameraDevice::kSequenceIdKey     = "SequenceId";
 const char* CameraDevice::kFrameNumberKey    = "FrameNumber";
@@ -206,28 +209,8 @@
     return ACAMERA_OK;
 }
 
-camera_status_t
-CameraDevice::captureLocked(
-        sp<ACameraCaptureSession> session,
-        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
-        int numRequests, ACaptureRequest** requests,
-        /*optional*/int* captureSequenceId) {
-    return submitRequestsLocked(
-            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
-}
-
-camera_status_t
-CameraDevice::setRepeatingRequestsLocked(
-        sp<ACameraCaptureSession> session,
-        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
-        int numRequests, ACaptureRequest** requests,
-        /*optional*/int* captureSequenceId) {
-    return submitRequestsLocked(
-            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
-}
-
-void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
-                                sp<CaptureRequest> &req) {
+void CameraDevice::addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
+        sp<CaptureRequest> &req) {
     CameraMetadata metadataCopy = aCaptureRequest->settings->getInternalData();
     const camera_metadata_t *camera_metadata = metadataCopy.getAndLock();
     HCameraMetadata hCameraMetadata;
@@ -237,101 +220,6 @@
     req->mPhysicalCameraSettings[0].settings.metadata(std::move(hCameraMetadata));
 }
 
-camera_status_t
-CameraDevice::submitRequestsLocked(
-        sp<ACameraCaptureSession> session,
-        /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
-        int numRequests, ACaptureRequest** requests,
-        /*optional*/int* captureSequenceId,
-        bool isRepeating) {
-    camera_status_t ret = checkCameraClosedOrErrorLocked();
-    if (ret != ACAMERA_OK) {
-        ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
-        return ret;
-    }
-
-    // Form two vectors of capture request, one for internal tracking
-    std::vector<frameworks::cameraservice::device::V2_0::CaptureRequest> requestList;
-    Vector<sp<CaptureRequest>> requestsV;
-    requestsV.setCapacity(numRequests);
-    for (int i = 0; i < numRequests; i++) {
-        sp<CaptureRequest> req;
-        ret = allocateCaptureRequest(requests[i], req);
-        // We need to call this method since after submitRequestList is called,
-        // the request metadata queue might have removed the capture request
-        // metadata. Therefore we simply add the metadata to its wrapper class,
-        // so that it can be retrived later.
-        addRequestSettingsMetadata(requests[i], req);
-        if (ret != ACAMERA_OK) {
-            ALOGE("Convert capture request to internal format failure! ret %d", ret);
-            return ret;
-        }
-        if (req->mCaptureRequest.streamAndWindowIds.size() == 0) {
-            ALOGE("Capture request without output target cannot be submitted!");
-            return ACAMERA_ERROR_INVALID_PARAMETER;
-        }
-        requestList.push_back(utils::convertToHidl(req.get()));
-        requestsV.push_back(req);
-    }
-    if (isRepeating) {
-        ret = stopRepeatingLocked();
-        if (ret != ACAMERA_OK) {
-            ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
-            return ret;
-        }
-    }
-
-    SubmitInfo info;
-    Status status;
-    auto remoteRet = mRemote->submitRequestList(requestList, isRepeating,
-                                                [&status, &info](auto s, auto &submitInfo) {
-                                                    status = s;
-                                                    info = submitInfo;
-                                                });
-    if (!remoteRet.isOk()) {
-        ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__,
-              remoteRet.description().c_str());
-    }
-    if (status != Status::NO_ERROR) {
-        return utils::convertFromHidl(status);
-    }
-    int32_t sequenceId = info.requestId;
-    int64_t lastFrameNumber = info.lastFrameNumber;
-    if (sequenceId < 0) {
-        ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
-        return ACAMERA_ERROR_UNKNOWN;
-    }
-
-    CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
-    mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
-
-    if (isRepeating) {
-        // stopRepeating above should have cleanup repeating sequence id
-        if (mRepeatingSequenceId != REQUEST_ID_NONE) {
-            setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
-            return ACAMERA_ERROR_CAMERA_DEVICE;
-        }
-        mRepeatingSequenceId = sequenceId;
-    } else {
-        mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
-    }
-
-    if (mIdle) {
-        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
-        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
-        msg->setObject(kSessionSpKey, session);
-        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
-        postSessionMsgAndCleanup(msg);
-    }
-    mIdle = false;
-    mBusySession = session;
-
-    if (captureSequenceId) {
-        *captureSequenceId = sequenceId;
-    }
-    return ACAMERA_OK;
-}
-
 camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
@@ -365,6 +253,7 @@
     outConfig.windowGroupId = -1; // ndk doesn't support inter OutputConfiguration buffer sharing.
     outConfig.windowHandles.resize(output->mSharedWindows.size() + 1);
     outConfig.windowHandles[0] = output->mWindow;
+    outConfig.physicalCameraId = output->mPhysicalCameraId;
     int i = 1;
     for (auto& anw : output->mSharedWindows) {
         outConfig.windowHandles[i++] = anw;
@@ -668,6 +557,7 @@
         outConfigInsert.windowGroupId = -1;
         outConfigInsert.windowHandles.resize(outConfig.mSharedWindows.size() + 1);
         outConfigInsert.windowHandles[0] = anw;
+        outConfigInsert.physicalCameraId = outConfig.mPhysicalCameraId;
         native_handle_ptr_wrapper wrap(anw);
         outputSet.insert(std::make_pair(anw, outConfigInsertW));
     }
@@ -894,7 +784,7 @@
     if (errorCode == ErrorCode::CAMERA_BUFFER) {
         int32_t streamId = resultExtras.errorStreamId;
         ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
-                cbh.mCallbacks.onCaptureBufferLost;
+                cbh.mOnCaptureBufferLost;
         auto outputPairIt = mConfiguredOutputs.find(streamId);
         if (outputPairIt == mConfiguredOutputs.end()) {
             ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
@@ -913,7 +803,7 @@
                             getId(), anw, frameNumber);
 
                     sp<AMessage> msg = new AMessage(kWhatCaptureBufferLost, mHandler);
-                    msg->setPointer(kContextKey, cbh.mCallbacks.context);
+                    msg->setPointer(kContextKey, cbh.mContext);
                     msg->setObject(kSessionSpKey, session);
                     msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
                     msg->setObject(kCaptureRequestKey, request);
@@ -925,7 +815,7 @@
         }
     } else { // Handle other capture failures
         // Fire capture failure callback if there is one registered
-        ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
+        ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed;
         sp<CameraCaptureFailure> failure(new CameraCaptureFailure());
         failure->frameNumber = frameNumber;
         // TODO: refine this when implementing flush
@@ -934,7 +824,7 @@
         failure->wasImageCaptured = (errorCode == ErrorCode::CAMERA_RESULT);
 
         sp<AMessage> msg = new AMessage(kWhatCaptureFail, mHandler);
-        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setPointer(kContextKey, cbh.mContext);
         msg->setObject(kSessionSpKey, session);
         msg->setPointer(kCallbackFpKey, (void*) onError);
         msg->setObject(kCaptureRequestKey, request);
@@ -956,6 +846,7 @@
         case kWhatSessionStateCb:
         case kWhatCaptureStart:
         case kWhatCaptureResult:
+        case kWhatLogicalCaptureResult:
         case kWhatCaptureFail:
         case kWhatCaptureSeqEnd:
         case kWhatCaptureSeqAbort:
@@ -1026,6 +917,7 @@
         case kWhatSessionStateCb:
         case kWhatCaptureStart:
         case kWhatCaptureResult:
+        case kWhatLogicalCaptureResult:
         case kWhatCaptureFail:
         case kWhatCaptureSeqEnd:
         case kWhatCaptureSeqAbort:
@@ -1043,6 +935,7 @@
             switch (msg->what()) {
                 case kWhatCaptureStart:
                 case kWhatCaptureResult:
+                case kWhatLogicalCaptureResult:
                 case kWhatCaptureFail:
                 case kWhatCaptureBufferLost:
                     found = msg->findObject(kCaptureRequestKey, &obj);
@@ -1114,6 +1007,62 @@
                     freeACaptureRequest(request);
                     break;
                 }
+                case kWhatLogicalCaptureResult:
+                {
+                    ACameraCaptureSession_logicalCamera_captureCallback_result onResult;
+                    found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+                    if (!found) {
+                        ALOGE("%s: Cannot find capture result callback!", __FUNCTION__);
+                        return;
+                    }
+                    if (onResult == nullptr) {
+                        return;
+                    }
+
+                    found = msg->findObject(kCaptureResultKey, &obj);
+                    if (!found) {
+                        ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+                        return;
+                    }
+                    sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
+
+                    found = msg->findObject(kPhysicalCaptureResultKey, &obj);
+                    if (!found) {
+                        ALOGE("%s: Cannot find physical capture result!", __FUNCTION__);
+                        return;
+                    }
+                    sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+                            static_cast<ACameraPhysicalCaptureResultInfo*>(obj.get()));
+                    std::vector<PhysicalCaptureResultInfoLocal>& physicalResultInfo =
+                            physicalResult->mPhysicalResultInfo;
+
+                    std::vector<std::string> physicalCameraIds;
+                    std::vector<sp<ACameraMetadata>> physicalMetadataCopy;
+                    for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+                        physicalCameraIds.push_back(physicalResultInfo[i].physicalCameraId);
+
+                        CameraMetadata clone = physicalResultInfo[i].physicalMetadata;
+                        clone.update(ANDROID_SYNC_FRAME_NUMBER,
+                                &physicalResult->mFrameNumber, /*data_count*/1);
+                        sp<ACameraMetadata> metadata =
+                                new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+                        physicalMetadataCopy.push_back(metadata);
+                    }
+                    std::vector<const char*> physicalCameraIdPtrs;
+                    std::vector<const ACameraMetadata*> physicalMetadataCopyPtrs;
+                    for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+                        physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str());
+                        physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
+                    }
+
+                    ACaptureRequest* request = allocateACaptureRequest(requestSp);
+                    (*onResult)(context, session.get(), request, result.get(),
+                            physicalResultInfo.size(), physicalCameraIdPtrs.data(),
+                            physicalMetadataCopyPtrs.data());
+                    freeACaptureRequest(request);
+                    break;
+                }
+
                 case kWhatCaptureFail:
                 {
                     ACameraCaptureSession_captureCallback_failed onFail;
@@ -1224,12 +1173,34 @@
 }
 
 CameraDevice::CallbackHolder::CallbackHolder(
-    sp<ACameraCaptureSession>          session,
-    const Vector<sp<CaptureRequest> >& requests,
-    bool                               isRepeating,
-    ACameraCaptureSession_captureCallbacks* cbs) :
-    mSession(session), mRequests(requests),
-    mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {}
+        sp<ACameraCaptureSession>          session,
+        const Vector<sp<CaptureRequest> >& requests,
+        bool                               isRepeating,
+        ACameraCaptureSession_captureCallbacks* cbs) :
+        mSession(session), mRequests(requests),
+        mIsRepeating(isRepeating),
+        mIsLogicalCameraCallback(false) {
+    initCaptureCallbacks(cbs);
+
+    if (cbs != nullptr) {
+        mOnCaptureCompleted = cbs->onCaptureCompleted;
+    }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+        sp<ACameraCaptureSession>          session,
+        const Vector<sp<CaptureRequest> >& requests,
+        bool                               isRepeating,
+        ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
+        mSession(session), mRequests(requests),
+        mIsRepeating(isRepeating),
+        mIsLogicalCameraCallback(true) {
+    initCaptureCallbacks(lcbs);
+
+    if (lcbs != nullptr) {
+        mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+    }
+}
 
 void
 CameraDevice::checkRepeatingSequenceCompleteLocked(
@@ -1246,9 +1217,9 @@
         mSequenceCallbackMap.erase(cbIt);
         // send seq aborted callback
         sp<AMessage> msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
-        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setPointer(kContextKey, cbh.mContext);
         msg->setObject(kSessionSpKey, cbh.mSession);
-        msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
+        msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted);
         msg->setInt32(kSequenceIdKey, sequenceId);
         postSessionMsgAndCleanup(msg);
     } else {
@@ -1295,9 +1266,9 @@
             mSequenceCallbackMap.erase(cbIt);
             // send seq complete callback
             sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
-            msg->setPointer(kContextKey, cbh.mCallbacks.context);
+            msg->setPointer(kContextKey, cbh.mContext);
             msg->setObject(kSessionSpKey, cbh.mSession);
-            msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted);
+            msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
             msg->setInt32(kSequenceIdKey, sequenceId);
             msg->setInt64(kFrameNumberKey, lastFrameNumber);
 
@@ -1454,7 +1425,7 @@
     auto it = dev->mSequenceCallbackMap.find(sequenceId);
     if (it != dev->mSequenceCallbackMap.end()) {
         CallbackHolder cbh = (*it).second;
-        ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted;
+        ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
         sp<ACameraCaptureSession> session = cbh.mSession;
         if ((size_t) burstId >= cbh.mRequests.size()) {
             ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1463,7 +1434,7 @@
         }
         sp<CaptureRequest> request = cbh.mRequests[burstId];
         sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
-        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        msg->setPointer(kContextKey, cbh.mContext);
         msg->setObject(kSessionSpKey, session);
         msg->setPointer(kCallbackFpKey, (void*) onStart);
         msg->setObject(kCaptureRequestKey, request);
@@ -1478,7 +1449,6 @@
         const FmqSizeOrMetadata& resultMetadata,
         const CaptureResultExtras& resultExtras,
         const hidl_vec<PhysicalCaptureResultInfo>& physicalResultInfos) {
-    (void) physicalResultInfos;
     auto ret = Void();
 
     sp<CameraDevice> dev = mDevice.promote();
@@ -1508,27 +1478,10 @@
     }
 
     CameraMetadata metadataCopy;
-    HCameraMetadata hCameraMetadata;
-    bool converted = false;
-    if (resultMetadata.getDiscriminator() ==
-        FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
-        hCameraMetadata.resize(resultMetadata.fmqMetadataSize());
-        bool read = dev->mCaptureResultMetadataQueue->read(hCameraMetadata.data(),
-                                                           resultMetadata.fmqMetadataSize());
-            if (!read) {
-                ALOGE("%s capture request settings could't be read from fmq",
-                      __FUNCTION__);
-                return ret;
-            }
-            // TODO: Do we actually need to clone here ?
-            converted = utils::convertFromHidlCloned(hCameraMetadata, &metadataCopy);
-
-    } else {
-          converted = utils::convertFromHidlCloned(resultMetadata.metadata(), &metadataCopy);
-    }
-
-    if (!converted) {
-        ALOGE("%s result metadata couldn't be converted", __FUNCTION__);
+    camera_status_t status = readOneResultMetadata(resultMetadata,
+            dev->mCaptureResultMetadataQueue.get(), &metadataCopy);
+    if (status != ACAMERA_OK) {
+        ALOGE("%s: result metadata couldn't be converted", __FUNCTION__);
         return ret;
     }
 
@@ -1538,9 +1491,6 @@
     auto it = dev->mSequenceCallbackMap.find(sequenceId);
     if (it != dev->mSequenceCallbackMap.end()) {
         CallbackHolder cbh = (*it).second;
-        ACameraCaptureSession_captureCallback_result onResult = isPartialResult ?
-                cbh.mCallbacks.onCaptureProgressed :
-                cbh.mCallbacks.onCaptureCompleted;
         sp<ACameraCaptureSession> session = cbh.mSession;
         if ((size_t) burstId >= cbh.mRequests.size()) {
             ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1551,12 +1501,39 @@
         sp<ACameraMetadata> result(new ACameraMetadata(
                 metadataCopy.release(), ACameraMetadata::ACM_RESULT));
 
-        sp<AMessage> msg = new AMessage(kWhatCaptureResult, dev->mHandler);
-        msg->setPointer(kContextKey, cbh.mCallbacks.context);
+        std::vector<PhysicalCaptureResultInfoLocal> localPhysicalResult;
+        localPhysicalResult.resize(physicalResultInfos.size());
+        for (size_t i = 0; i < physicalResultInfos.size(); i++) {
+            localPhysicalResult[i].physicalCameraId = physicalResultInfos[i].physicalCameraId;
+            status = readOneResultMetadata(physicalResultInfos[i].physicalCameraMetadata,
+                    dev->mCaptureResultMetadataQueue.get(),
+                    &localPhysicalResult[i].physicalMetadata);
+            if (status != ACAMERA_OK) {
+                ALOGE("%s: physical camera result metadata couldn't be converted", __FUNCTION__);
+                return ret;
+            }
+        }
+        sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+                new ACameraPhysicalCaptureResultInfo(localPhysicalResult, frameNumber));
+
+        sp<AMessage> msg = new AMessage(
+                cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult,
+                dev->mHandler);
+        msg->setPointer(kContextKey, cbh.mContext);
         msg->setObject(kSessionSpKey, session);
-        msg->setPointer(kCallbackFpKey, (void*) onResult);
         msg->setObject(kCaptureRequestKey, request);
         msg->setObject(kCaptureResultKey, result);
+        if (isPartialResult) {
+            msg->setPointer(kCallbackFpKey,
+                    (void *)cbh.mOnCaptureProgressed);
+        } else if (cbh.mIsLogicalCameraCallback) {
+            msg->setPointer(kCallbackFpKey,
+                    (void *)cbh.mOnLogicalCameraCaptureCompleted);
+            msg->setObject(kPhysicalCaptureResultKey, physicalResult);
+        } else {
+            msg->setPointer(kCallbackFpKey,
+                    (void *)cbh.mOnCaptureCompleted);
+        }
         dev->postSessionMsgAndCleanup(msg);
     }
 
@@ -1590,5 +1567,31 @@
     return ret;
 }
 
+camera_status_t CameraDevice::ServiceCallback::readOneResultMetadata(
+        const FmqSizeOrMetadata& fmqSizeOrMetadata, ResultMetadataQueue* metadataQueue,
+        CameraMetadata* metadata) {
+    if (metadataQueue == nullptr || metadata == nullptr) {
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    bool converted;
+    HCameraMetadata hCameraMetadata;
+    if (fmqSizeOrMetadata.getDiscriminator() ==
+            FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
+        hCameraMetadata.resize(fmqSizeOrMetadata.fmqMetadataSize());
+        bool read = metadataQueue->read(
+                hCameraMetadata.data(), fmqSizeOrMetadata.fmqMetadataSize());
+        if (!read) {
+            ALOGE("%s capture request settings could't be read from fmq", __FUNCTION__);
+            return ACAMERA_ERROR_UNKNOWN;
+        }
+        // TODO: Do we actually need to clone here ?
+        converted = utils::convertFromHidlCloned(hCameraMetadata, metadata);
+    } else {
+        converted = utils::convertFromHidlCloned(fmqSizeOrMetadata.metadata(), metadata);
+    }
+
+    return converted ? ACAMERA_OK : ACAMERA_ERROR_UNKNOWN;
+}
+
 } // namespace acam
 } // namespace android
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index 01a219f..c63b97f 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -21,6 +21,7 @@
 #include <set>
 #include <atomic>
 #include <utility>
+#include <vector>
 #include <utils/StrongPointer.h>
 #include <utils/Mutex.h>
 #include <utils/List.h>
@@ -65,6 +66,21 @@
 // Wrap ACameraCaptureFailure so it can be ref-counted
 struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure { };
 
+// Wrap PhysicalCaptureResultInfo so that it can be ref-counted
+struct PhysicalCaptureResultInfoLocal {
+    std::string physicalCameraId;
+    CameraMetadata physicalMetadata;
+};
+
+struct ACameraPhysicalCaptureResultInfo: public RefBase {
+    ACameraPhysicalCaptureResultInfo(const std::vector<PhysicalCaptureResultInfoLocal>& info,
+            int64_t frameNumber) :
+        mPhysicalResultInfo(info), mFrameNumber(frameNumber) {}
+
+    std::vector<PhysicalCaptureResultInfoLocal> mPhysicalResultInfo;
+    int64_t mFrameNumber;
+};
+
 class CameraDevice final : public RefBase {
   public:
     CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
@@ -99,6 +115,8 @@
         android::hardware::Return<void> onRepeatingRequestError(uint64_t lastFrameNumber,
                 int32_t stoppedSequenceId) override;
       private:
+        camera_status_t readOneResultMetadata(const FmqSizeOrMetadata& fmqSizeOrMetadata,
+                ResultMetadataQueue* metadataQueue, CameraMetadata* metadata);
         const wp<CameraDevice> mDevice;
     };
     inline sp<ICameraDeviceCallback> getServiceCallback() {
@@ -127,24 +145,28 @@
 
     camera_status_t waitUntilIdleLocked();
 
-
+    template<class T>
     camera_status_t captureLocked(sp<ACameraCaptureSession> session,
-            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            /*optional*/T* cbs,
             int numRequests, ACaptureRequest** requests,
             /*optional*/int* captureSequenceId);
 
+    template<class T>
     camera_status_t setRepeatingRequestsLocked(sp<ACameraCaptureSession> session,
-            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            /*optional*/T* cbs,
             int numRequests, ACaptureRequest** requests,
             /*optional*/int* captureSequenceId);
 
+    template<class T>
     camera_status_t submitRequestsLocked(
             sp<ACameraCaptureSession> session,
-            /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+            /*optional*/T* cbs,
             int numRequests, ACaptureRequest** requests,
             /*out*/int* captureSequenceId,
             bool isRepeating);
 
+    void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest, sp<CaptureRequest> &req);
+
     camera_status_t updateOutputConfigurationLocked(ACaptureSessionOutput *output);
 
     camera_status_t allocateCaptureRequest(
@@ -206,6 +228,7 @@
         // Capture callbacks
         kWhatCaptureStart,     // onCaptureStarted
         kWhatCaptureResult,    // onCaptureProgressed, onCaptureCompleted
+        kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted
         kWhatCaptureFail,      // onCaptureFailed
         kWhatCaptureSeqEnd,    // onCaptureSequenceCompleted
         kWhatCaptureSeqAbort,  // onCaptureSequenceAborted
@@ -221,6 +244,7 @@
     static const char* kCaptureRequestKey;
     static const char* kTimeStampKey;
     static const char* kCaptureResultKey;
+    static const char* kPhysicalCaptureResultKey;
     static const char* kCaptureFailureKey;
     static const char* kSequenceIdKey;
     static const char* kFrameNumberKey;
@@ -259,19 +283,47 @@
                        const Vector<sp<CaptureRequest>>&  requests,
                        bool                               isRepeating,
                        ACameraCaptureSession_captureCallbacks* cbs);
+        CallbackHolder(sp<ACameraCaptureSession>          session,
+                       const Vector<sp<CaptureRequest>>&  requests,
+                       bool                               isRepeating,
+                       ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
 
-        static ACameraCaptureSession_captureCallbacks fillCb(
-                ACameraCaptureSession_captureCallbacks* cbs) {
+        template <class T>
+        void initCaptureCallbacks(T* cbs) {
+            mContext = nullptr;
+            mOnCaptureStarted = nullptr;
+            mOnCaptureProgressed = nullptr;
+            mOnCaptureCompleted = nullptr;
+            mOnLogicalCameraCaptureCompleted = nullptr;
+            mOnCaptureFailed = nullptr;
+            mOnCaptureSequenceCompleted = nullptr;
+            mOnCaptureSequenceAborted = nullptr;
+            mOnCaptureBufferLost = nullptr;
             if (cbs != nullptr) {
-                return *cbs;
+                mContext = cbs->context;
+                mOnCaptureStarted = cbs->onCaptureStarted;
+                mOnCaptureProgressed = cbs->onCaptureProgressed;
+                mOnCaptureFailed = cbs->onCaptureFailed;
+                mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted;
+                mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted;
+                mOnCaptureBufferLost = cbs->onCaptureBufferLost;
             }
-            return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
         }
 
         sp<ACameraCaptureSession>   mSession;
-        Vector<sp<CaptureRequest>> mRequests;
+        Vector<sp<CaptureRequest>>  mRequests;
         const bool                  mIsRepeating;
-        ACameraCaptureSession_captureCallbacks mCallbacks;
+        const bool                  mIsLogicalCameraCallback;
+
+        void*                       mContext;
+        ACameraCaptureSession_captureCallback_start mOnCaptureStarted;
+        ACameraCaptureSession_captureCallback_result mOnCaptureProgressed;
+        ACameraCaptureSession_captureCallback_result mOnCaptureCompleted;
+        ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted;
+        ACameraCaptureSession_captureCallback_failed mOnCaptureFailed;
+        ACameraCaptureSession_captureCallback_sequenceEnd mOnCaptureSequenceCompleted;
+        ACameraCaptureSession_captureCallback_sequenceAbort mOnCaptureSequenceAborted;
+        ACameraCaptureSession_captureCallback_bufferLost mOnCaptureBufferLost;
     };
     // sequence id -> callbacks map
     std::map<int, CallbackHolder> mSequenceCallbackMap;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
new file mode 100644
index 0000000..7d2304e
--- /dev/null
+++ b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+#include <vector>
+#include <inttypes.h>
+#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
+#include <android/frameworks/cameraservice/device/2.0/types.h>
+#include <CameraMetadata.h>
+
+#include "ndk_vendor/impl/ACameraDevice.h"
+#include "ACameraCaptureSession.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "utils.h"
+
+using namespace android;
+
+namespace android {
+namespace acam {
+
+template<class T>
+camera_status_t
+CameraDevice::captureLocked(
+        sp<ACameraCaptureSession> session,
+        /*optional*/T* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    return submitRequestsLocked(
+            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
+}
+
+template<class T>
+camera_status_t
+CameraDevice::setRepeatingRequestsLocked(
+        sp<ACameraCaptureSession> session,
+        /*optional*/T* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*optional*/int* captureSequenceId) {
+    return submitRequestsLocked(
+            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
+}
+
+template<class T>
+camera_status_t CameraDevice::submitRequestsLocked(
+        sp<ACameraCaptureSession> session,
+        /*optional*/T* cbs,
+        int numRequests, ACaptureRequest** requests,
+        /*out*/int* captureSequenceId,
+        bool isRepeating)
+{
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
+        return ret;
+    }
+
+    // Form two vectors of capture request, one for internal tracking
+    std::vector<frameworks::cameraservice::device::V2_0::CaptureRequest> requestList;
+    Vector<sp<CaptureRequest>> requestsV;
+    requestsV.setCapacity(numRequests);
+    for (int i = 0; i < numRequests; i++) {
+        sp<CaptureRequest> req;
+        ret = allocateCaptureRequest(requests[i], req);
+        // We need to call this method since after submitRequestList is called,
+        // the request metadata queue might have removed the capture request
+        // metadata. Therefore we simply add the metadata to its wrapper class,
+        // so that it can be retrieved later.
+        addRequestSettingsMetadata(requests[i], req);
+        if (ret != ACAMERA_OK) {
+            ALOGE("Convert capture request to internal format failure! ret %d", ret);
+            return ret;
+        }
+        if (req->mCaptureRequest.streamAndWindowIds.size() == 0) {
+            ALOGE("Capture request without output target cannot be submitted!");
+            return ACAMERA_ERROR_INVALID_PARAMETER;
+        }
+        requestList.push_back(utils::convertToHidl(req.get()));
+        requestsV.push_back(req);
+    }
+    if (isRepeating) {
+        ret = stopRepeatingLocked();
+        if (ret != ACAMERA_OK) {
+            ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+            return ret;
+        }
+    }
+
+    SubmitInfo info;
+    Status status;
+    auto remoteRet = mRemote->submitRequestList(requestList, isRepeating,
+                                                [&status, &info](auto s, auto &submitInfo) {
+                                                    status = s;
+                                                    info = submitInfo;
+                                                });
+    if (!remoteRet.isOk()) {
+        ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__,
+              remoteRet.description().c_str());
+    }
+    if (status != Status::NO_ERROR) {
+        return utils::convertFromHidl(status);
+    }
+    int32_t sequenceId = info.requestId;
+    int64_t lastFrameNumber = info.lastFrameNumber;
+    if (sequenceId < 0) {
+        ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+
+    CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
+    mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+    if (isRepeating) {
+        // stopRepeating above should have cleanup repeating sequence id
+        if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+            setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+            return ACAMERA_ERROR_CAMERA_DEVICE;
+        }
+        mRepeatingSequenceId = sequenceId;
+    } else {
+        mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+    }
+
+    if (mIdle) {
+        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+        postSessionMsgAndCleanup(msg);
+    }
+    mIdle = false;
+    mBusySession = session;
+
+    if (captureSequenceId) {
+        *captureSequenceId = sequenceId;
+    }
+    return ACAMERA_OK;
+}
+
+} // namespace acam
+} // namespace android
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 579412e..f9bb3ac 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -55,38 +55,27 @@
 
 class CameraHelper {
    public:
-    CameraHelper(native_handle_t* imgReaderAnw) : mImgReaderAnw(imgReaderAnw) {}
+    CameraHelper(const char* id, ACameraManager *manager) :
+            mImgReaderAnw(nullptr), mCameraId(id), mCameraManager(manager) {}
     ~CameraHelper() { closeCamera(); }
 
-    int initCamera() {
-        if (mImgReaderAnw == nullptr) {
+    struct PhysicalImgReaderInfo {
+        const char* physicalCameraId;
+        native_handle_t* anw;
+    };
+    int initCamera(native_handle_t* imgReaderAnw,
+            const std::vector<PhysicalImgReaderInfo>& physicalImgReaders) {
+        if (imgReaderAnw == nullptr) {
             ALOGE("Cannot initialize camera before image reader get initialized.");
             return -1;
         }
+        if (mIsCameraReady) {
+            ALOGE("initCamera should only be called once.");
+            return -1;
+        }
+
         int ret;
-
-        mCameraManager = ACameraManager_create();
-        if (mCameraManager == nullptr) {
-            ALOGE("Failed to create ACameraManager.");
-            return -1;
-        }
-
-        ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
-        if (ret != AMEDIA_OK) {
-            ALOGE("Failed to get cameraIdList: ret=%d", ret);
-            return ret;
-        }
-        if (mCameraIdList->numCameras < 1) {
-            ALOGW("Device has no camera on board.");
-            return 0;
-        }
-
-        // We always use the first camera.
-        mCameraId = mCameraIdList->cameraIds[0];
-        if (mCameraId == nullptr) {
-            ALOGE("Failed to get cameraId.");
-            return -1;
-        }
+        mImgReaderAnw = imgReaderAnw;
 
         ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice);
         if (ret != AMEDIA_OK || mDevice == nullptr) {
@@ -94,18 +83,6 @@
             return -1;
         }
 
-        ret = ACameraManager_getCameraCharacteristics(mCameraManager, mCameraId, &mCameraMetadata);
-        if (ret != ACAMERA_OK || mCameraMetadata == nullptr) {
-            ALOGE("Get camera %s characteristics failure. ret %d, metadata %p", mCameraId, ret,
-                  mCameraMetadata);
-            return -1;
-        }
-
-        if (!isCapabilitySupported(ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE)) {
-            ALOGW("Camera does not support BACKWARD_COMPATIBLE.");
-            return 0;
-        }
-
         // Create capture session
         ret = ACaptureSessionOutputContainer_create(&mOutputs);
         if (ret != AMEDIA_OK) {
@@ -122,6 +99,25 @@
             ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
             return ret;
         }
+
+        for (auto& physicalStream : physicalImgReaders) {
+            ACaptureSessionOutput* sessionOutput = nullptr;
+            ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
+                    physicalStream.physicalCameraId, &sessionOutput);
+            if (ret != ACAMERA_OK) {
+                ALOGE("ACaptureSessionPhysicalOutput_create failed, ret=%d", ret);
+                return ret;
+            }
+            ret = ACaptureSessionOutputContainer_add(mOutputs, sessionOutput);
+            if (ret != AMEDIA_OK) {
+                ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
+                return ret;
+            }
+            mExtraOutputs.push_back(sessionOutput);
+            // Assume that at most one physical stream per physical camera.
+            mPhysicalCameraIds.push_back(physicalStream.physicalCameraId);
+        }
+
         ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
         if (ret != AMEDIA_OK) {
             ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
@@ -145,21 +141,25 @@
             return ret;
         }
 
+        for (auto& physicalStream : physicalImgReaders) {
+            ACameraOutputTarget* outputTarget = nullptr;
+            ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget);
+            if (ret != AMEDIA_OK) {
+                ALOGE("ACameraOutputTarget_create failed, ret=%d", ret);
+                return ret;
+            }
+            ret = ACaptureRequest_addTarget(mStillRequest, outputTarget);
+            if (ret != AMEDIA_OK) {
+                ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
+                return ret;
+            }
+            mReqExtraOutputs.push_back(outputTarget);
+        }
+
         mIsCameraReady = true;
         return 0;
     }
 
-    bool isCapabilitySupported(acamera_metadata_enum_android_request_available_capabilities_t cap) {
-        ACameraMetadata_const_entry entry;
-        ACameraMetadata_getConstEntry(
-                mCameraMetadata, ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, &entry);
-        for (uint32_t i = 0; i < entry.count; i++) {
-            if (entry.data.u8[i] == cap) {
-                return true;
-            }
-        }
-        return false;
-    }
 
     bool isCameraReady() { return mIsCameraReady; }
 
@@ -169,6 +169,10 @@
             ACameraOutputTarget_free(mReqImgReaderOutput);
             mReqImgReaderOutput = nullptr;
         }
+        for (auto& outputTarget : mReqExtraOutputs) {
+            ACameraOutputTarget_free(outputTarget);
+        }
+        mReqExtraOutputs.clear();
         if (mStillRequest) {
             ACaptureRequest_free(mStillRequest);
             mStillRequest = nullptr;
@@ -182,6 +186,10 @@
             ACaptureSessionOutput_free(mImgReaderOutput);
             mImgReaderOutput = nullptr;
         }
+        for (auto& extraOutput : mExtraOutputs) {
+            ACaptureSessionOutput_free(extraOutput);
+        }
+        mExtraOutputs.clear();
         if (mOutputs) {
             ACaptureSessionOutputContainer_free(mOutputs);
             mOutputs = nullptr;
@@ -191,19 +199,6 @@
             ACameraDevice_close(mDevice);
             mDevice = nullptr;
         }
-        if (mCameraMetadata) {
-          ACameraMetadata_free(mCameraMetadata);
-          mCameraMetadata = nullptr;
-        }
-        // Destroy camera manager
-        if (mCameraIdList) {
-            ACameraManager_deleteCameraIdList(mCameraIdList);
-            mCameraIdList = nullptr;
-        }
-        if (mCameraManager) {
-            ACameraManager_delete(mCameraManager);
-            mCameraManager = nullptr;
-        }
         mIsCameraReady = false;
     }
 
@@ -213,6 +208,12 @@
                                              &seqId);
     }
 
+    int takeLogicalCameraPicture() {
+        int seqId;
+        return ACameraCaptureSession_logicalCamera_capture(mSession, &mLogicalCaptureCallbacks,
+                1, &mStillRequest, &seqId);
+    }
+
     bool checkCallbacks(int pictureCount) {
         std::lock_guard<std::mutex> lock(mMutex);
         if (mCompletedCaptureCallbackCount != pictureCount) {
@@ -241,22 +242,22 @@
 
     native_handle_t* mImgReaderAnw = nullptr;  // not owned by us.
 
-    // Camera manager
-    ACameraManager* mCameraManager = nullptr;
-    ACameraIdList* mCameraIdList = nullptr;
     // Camera device
-    ACameraMetadata* mCameraMetadata = nullptr;
     ACameraDevice* mDevice = nullptr;
     // Capture session
     ACaptureSessionOutputContainer* mOutputs = nullptr;
     ACaptureSessionOutput* mImgReaderOutput = nullptr;
+    std::vector<ACaptureSessionOutput*> mExtraOutputs;
+
     ACameraCaptureSession* mSession = nullptr;
     // Capture request
     ACaptureRequest* mStillRequest = nullptr;
     ACameraOutputTarget* mReqImgReaderOutput = nullptr;
+    std::vector<ACameraOutputTarget*> mReqExtraOutputs;
 
     bool mIsCameraReady = false;
     const char* mCameraId;
+    ACameraManager* mCameraManager;
     int mCompletedCaptureCallbackCount = 0;
     std::mutex mMutex;
     ACameraCaptureSession_captureCallbacks mCaptureCallbacks = {
@@ -264,7 +265,6 @@
         this, // context
         nullptr, // onCaptureStarted
         nullptr, // onCaptureProgressed
-        // onCaptureCompleted, called serially, so no lock needed.
         [](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
                                           const ACameraMetadata *) {
             CameraHelper *ch = static_cast<CameraHelper *>(ctx);
@@ -275,8 +275,44 @@
         nullptr, // onCaptureSequenceCompleted
         nullptr, // onCaptureSequenceAborted
         nullptr, // onCaptureBufferLost
-  };
+    };
 
+    std::vector<std::string> mPhysicalCameraIds;
+    ACameraCaptureSession_logicalCamera_captureCallbacks mLogicalCaptureCallbacks = {
+        // TODO: Add tests for other callbacks
+        this, // context
+        nullptr, // onCaptureStarted
+        nullptr, // onCaptureProgressed
+        [](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
+                const ACameraMetadata *, size_t physicalResultCount,
+                const char** physicalCameraIds, const ACameraMetadata** physicalResults) {
+            CameraHelper *ch = static_cast<CameraHelper *>(ctx);
+            std::lock_guard<std::mutex> lock(ch->mMutex);
+            ASSERT_EQ(physicalResultCount, ch->mPhysicalCameraIds.size());
+            for (size_t i = 0; i < physicalResultCount; i++) {
+                ASSERT_TRUE(physicalCameraIds[i] != nullptr);
+                ASSERT_TRUE(physicalResults[i] != nullptr);
+                ASSERT_NE(std::find(ch->mPhysicalCameraIds.begin(),
+                        ch->mPhysicalCameraIds.end(), physicalCameraIds[i]),
+                        ch->mPhysicalCameraIds.end());
+
+                // Verify frameNumber and sensorTimestamp exist in physical
+                // result metadata
+                ACameraMetadata_const_entry entry;
+                ACameraMetadata_getConstEntry(
+                        physicalResults[i], ACAMERA_SYNC_FRAME_NUMBER, &entry);
+                ASSERT_EQ(entry.count, 1);
+                ACameraMetadata_getConstEntry(
+                        physicalResults[i], ACAMERA_SENSOR_TIMESTAMP, &entry);
+                ASSERT_EQ(entry.count, 1);
+            }
+            ch->mCompletedCaptureCallbackCount++;
+        },
+        nullptr, // onCaptureFailed
+        nullptr, // onCaptureSequenceCompleted
+        nullptr, // onCaptureSequenceAborted
+        nullptr, // onCaptureBufferLost
+    };
 };
 
 class ImageReaderTestCase {
@@ -476,84 +512,276 @@
     AImageReader_BufferRemovedListener mReaderDetachedCb{this, onBufferRemoved};
 };
 
-bool takePictures(uint64_t readerUsage, int readerMaxImages, bool readerAsync, int pictureCount) {
-    int ret = 0;
-    ImageReaderTestCase testCase(
-            kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
-            readerAsync);
-    ret = testCase.initImageReader();
-    if (ret < 0) {
-        ALOGE("Unable to initialize ImageReader");
+
+class AImageReaderVendorTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        mCameraManager = ACameraManager_create();
+        if (mCameraManager == nullptr) {
+            ALOGE("Failed to create ACameraManager.");
+            return;
+        }
+
+        camera_status_t ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
+        if (ret != ACAMERA_OK) {
+            ALOGE("Failed to get cameraIdList: ret=%d", ret);
+            return;
+        }
+        if (mCameraIdList->numCameras < 1) {
+            ALOGW("Device has no camera on board.");
+            return;
+        }
+    }
+    void TearDown() override {
+        // Destroy camera manager
+        if (mCameraIdList) {
+            ACameraManager_deleteCameraIdList(mCameraIdList);
+            mCameraIdList = nullptr;
+        }
+        if (mCameraManager) {
+            ACameraManager_delete(mCameraManager);
+            mCameraManager = nullptr;
+        }
+    }
+
+    bool takePictures(const char* id, uint64_t readerUsage, int readerMaxImages,
+            bool readerAsync, int pictureCount) {
+        int ret = 0;
+
+        ImageReaderTestCase testCase(
+                kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
+                readerAsync);
+        ret = testCase.initImageReader();
+        if (ret < 0) {
+            ALOGE("Unable to initialize ImageReader");
+            return false;
+        }
+
+        CameraHelper cameraHelper(id, mCameraManager);
+        ret = cameraHelper.initCamera(testCase.getNativeWindow(), {});
+        if (ret < 0) {
+            ALOGE("Unable to initialize camera helper");
+            return false;
+        }
+
+        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 "
+                  "camera on board.");
+            return true;
+        }
+
+        for (int i = 0; i < pictureCount; i++) {
+            ret = cameraHelper.takePicture();
+            if (ret < 0) {
+                ALOGE("Unable to take picture");
+                return false;
+            }
+        }
+
+        // Sleep until all capture finished
+        for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
+            usleep(kCaptureWaitUs);
+            if (testCase.getAcquiredImageCount() == pictureCount) {
+                ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
+                      pictureCount);
+                break;
+            }
+        }
+        return testCase.getAcquiredImageCount() == pictureCount &&
+                cameraHelper.checkCallbacks(pictureCount);
+    }
+
+    bool testTakePicturesNative(const char* id) {
+        for (auto& readerUsage :
+             {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
+            for (auto& readerMaxImages : {1, 4, 8}) {
+                for (auto& readerAsync : {true, false}) {
+                    for (auto& pictureCount : {1, 4, 8}) {
+                        if (!takePictures(id, readerUsage, readerMaxImages,
+                                readerAsync, pictureCount)) {
+                            ALOGE("Test takePictures failed for test case usage=%" PRIu64
+                                  ", maxImages=%d, async=%d, pictureCount=%d",
+                                  readerUsage, readerMaxImages, readerAsync, pictureCount);
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    // Camera manager
+    ACameraManager* mCameraManager = nullptr;
+    ACameraIdList* mCameraIdList = nullptr;
+
+    bool isCapabilitySupported(ACameraMetadata* staticInfo,
+            acamera_metadata_enum_android_request_available_capabilities_t cap) {
+        ACameraMetadata_const_entry entry;
+        ACameraMetadata_getConstEntry(
+                staticInfo, ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+        for (uint32_t i = 0; i < entry.count; i++) {
+            if (entry.data.u8[i] == cap) {
+                return true;
+            }
+        }
         return false;
     }
 
-    CameraHelper cameraHelper(testCase.getNativeWindow());
-    ret = cameraHelper.initCamera();
-    if (ret < 0) {
-        ALOGE("Unable to initialize camera helper");
+    bool isSizeSupportedForFormat(ACameraMetadata* staticInfo,
+            int32_t format, int32_t width, int32_t height) {
+        ACameraMetadata_const_entry entry;
+        ACameraMetadata_getConstEntry(staticInfo,
+                ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
+        for (uint32_t i = 0; i < entry.count; i += 4) {
+            if (entry.data.i32[i] == format &&
+                    entry.data.i32[i+3] == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+                    entry.data.i32[i+1] == width &&
+                    entry.data.i32[i+2] == height) {
+                return true;
+            }
+        }
         return false;
     }
 
+    void findCandidateLogicalCamera(const char **cameraId,
+            ACameraMetadata** staticMetadata,
+            std::vector<const char*>* candidatePhysicalIds) {
+        // Find first available logical camera
+        for (int i = 0; i < mCameraIdList->numCameras; i++) {
+            camera_status_t ret;
+            ret = ACameraManager_getCameraCharacteristics(
+                    mCameraManager, mCameraIdList->cameraIds[i], staticMetadata);
+            ASSERT_EQ(ret, ACAMERA_OK);
+            ASSERT_NE(*staticMetadata, nullptr);
+
+            if (!isCapabilitySupported(*staticMetadata,
+                    ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA)) {
+                ACameraMetadata_free(*staticMetadata);
+                *staticMetadata = nullptr;
+                continue;
+            }
+
+            // Check returned physical camera Ids are valid
+            size_t physicalCameraIdCnt = 0;
+            const char*const* physicalCameraIds = nullptr;
+            bool isLogicalCamera = ACameraMetadata_isLogicalMultiCamera(*staticMetadata,
+                    &physicalCameraIdCnt, &physicalCameraIds);
+            ASSERT_TRUE(isLogicalCamera);
+            ASSERT_GE(physicalCameraIdCnt, 2);
+            ACameraMetadata* physicalCameraMetadata = nullptr;
+            candidatePhysicalIds->clear();
+            for (size_t j = 0; j < physicalCameraIdCnt && candidatePhysicalIds->size() < 2; j++) {
+                ASSERT_GT(strlen(physicalCameraIds[j]), 0);
+                ret = ACameraManager_getCameraCharacteristics(
+                        mCameraManager, physicalCameraIds[j], &physicalCameraMetadata);
+                ASSERT_EQ(ret, ACAMERA_OK);
+                ASSERT_NE(physicalCameraMetadata, nullptr);
+
+                if (isSizeSupportedForFormat(physicalCameraMetadata, kTestImageFormat,
+                        kTestImageWidth, kTestImageHeight)) {
+                    candidatePhysicalIds->push_back(physicalCameraIds[j]);
+                }
+                ACameraMetadata_free(physicalCameraMetadata);
+            }
+            if (candidatePhysicalIds->size() == 2) {
+                *cameraId = mCameraIdList->cameraIds[i];
+                return;
+            } else {
+                ACameraMetadata_free(*staticMetadata);
+                *staticMetadata = nullptr;
+            }
+        }
+        *cameraId = nullptr;
+        return;
+    }
+};
+
+TEST_F(AImageReaderVendorTest, CreateWindowNativeHandle) {
+    // We always use the first camera.
+    const char* cameraId = mCameraIdList->cameraIds[0];
+    ASSERT_TRUE(cameraId != nullptr);
+
+    ACameraMetadata* staticMetadata = nullptr;
+    camera_status_t ret = ACameraManager_getCameraCharacteristics(
+            mCameraManager, cameraId, &staticMetadata);
+    ASSERT_EQ(ret, ACAMERA_OK);
+    ASSERT_NE(staticMetadata, nullptr);
+
+    bool isBC = isCapabilitySupported(staticMetadata,
+            ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
+
+    ACameraMetadata_free(staticMetadata);
+
+    if (!isBC) {
+        ALOGW("Camera does not support BACKWARD_COMPATIBLE.");
+        return;
+    }
+
+    EXPECT_TRUE(testTakePicturesNative(cameraId));
+}
+
+TEST_F(AImageReaderVendorTest, LogicalCameraPhysicalStream) {
+    const char* cameraId = nullptr;
+    ACameraMetadata* staticMetadata = nullptr;
+    std::vector<const char*> physicalCameraIds;
+
+    findCandidateLogicalCamera(&cameraId, &staticMetadata, &physicalCameraIds);
+    if (cameraId == nullptr) {
+        // Couldn't find logical camera to test
+        return;
+    }
+
+    // Test streaming the logical multi-camera
+    uint64_t readerUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
+    int32_t readerMaxImages = 8;
+    bool readerAsync = false;
+    const int pictureCount = 6;
+    std::vector<ImageReaderTestCase*> testCases;
+    for (size_t i = 0; i < 3; i++) {
+        ImageReaderTestCase* testCase = new ImageReaderTestCase(
+                kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
+                readerAsync);
+        ASSERT_EQ(testCase->initImageReader(), 0);
+        testCases.push_back(testCase);
+    }
+
+    CameraHelper cameraHelper(cameraId, mCameraManager);
+    std::vector<CameraHelper::PhysicalImgReaderInfo> physicalImgReaderInfo;
+    physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
+    physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
+
+    int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo);
+    ASSERT_EQ(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 camera on "
               "board.");
-        return true;
+        return;
     }
 
     for (int i = 0; i < pictureCount; i++) {
-        ret = cameraHelper.takePicture();
-        if (ret < 0) {
-            ALOGE("Unable to take picture");
-            return false;
-        }
+        ret = cameraHelper.takeLogicalCameraPicture();
+        ASSERT_EQ(ret, 0);
     }
 
     // Sleep until all capture finished
     for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
         usleep(kCaptureWaitUs);
-        if (testCase.getAcquiredImageCount() == pictureCount) {
+        if (testCases[0]->getAcquiredImageCount() == pictureCount) {
             ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
                   pictureCount);
             break;
         }
     }
-    return testCase.getAcquiredImageCount() == pictureCount &&
-            cameraHelper.checkCallbacks(pictureCount);
-}
+    ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount);
+    ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount);
+    ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount);
+    ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
 
-class AImageReaderWindowHandleTest : public ::testing::Test {
-   public:
-    void SetUp() override {
-    }
-    void TearDown() override {
-
-    }
-
-};
-
-bool testTakePicturesNative() {
-    for (auto& readerUsage :
-         {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
-        for (auto& readerMaxImages : {1, 4, 8}) {
-            for (auto& readerAsync : {true, false}) {
-                for (auto& pictureCount : {1, 4, 8}) {
-                    if (!takePictures(readerUsage, readerMaxImages, readerAsync, pictureCount)) {
-                        ALOGE("Test takePictures failed for test case usage=%" PRIu64 ", maxImages=%d, "
-                              "async=%d, pictureCount=%d",
-                              readerUsage, readerMaxImages, readerAsync, pictureCount);
-                        return false;
-                    }
-                }
-            }
-        }
-    }
-    return true;
-}
-
-
-TEST_F(AImageReaderWindowHandleTest, CreateWindowNativeHandle) {
-    EXPECT_TRUE(testTakePicturesNative());
+    ACameraMetadata_free(staticMetadata);
 }
 
 }  // namespace
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index fa8a7a3..8534b28 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -480,7 +480,8 @@
 
         sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
 
-        OutputConfiguration output(gbProducer, /*rotation*/0);
+        String16 noPhysicalId;
+        OutputConfiguration output(gbProducer, /*rotation*/0, noPhysicalId);
 
         // Can we configure?
         res = device->beginConfigure();
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 86e9040..34a9a40 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -224,11 +224,15 @@
         player->setSource(rawSource);
         rawSource.clear();
 
-        player->start(true /* sourceAlreadyStarted */);
+        err = player->start(true /* sourceAlreadyStarted */);
 
-        status_t finalStatus;
-        while (!player->reachedEOS(&finalStatus)) {
-            usleep(100000ll);
+        if (err == OK) {
+            status_t finalStatus;
+            while (!player->reachedEOS(&finalStatus)) {
+                usleep(100000ll);
+            }
+        } else {
+            fprintf(stderr, "unable to start playback err=%d (0x%08x)\n", err, err);
         }
 
         delete player;
@@ -651,7 +655,8 @@
         MEDIA_MIMETYPE_AUDIO_G711_ALAW, MEDIA_MIMETYPE_AUDIO_VORBIS,
         MEDIA_MIMETYPE_VIDEO_VP8, MEDIA_MIMETYPE_VIDEO_VP9,
         MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, MEDIA_MIMETYPE_VIDEO_HEVC,
-        MEDIA_MIMETYPE_AUDIO_EAC3, MEDIA_MIMETYPE_AUDIO_AC4
+        MEDIA_MIMETYPE_AUDIO_EAC3, MEDIA_MIMETYPE_AUDIO_AC4,
+        MEDIA_MIMETYPE_VIDEO_AV1
     };
 
     const char *codecType = queryDecoders? "decoder" : "encoder";
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index 28a78aa..bb9d7ec 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -29,8 +29,7 @@
     srcs: ["src/FwdLockEngine.cpp"],
 
     shared_libs: [
-        "libicui18n",
-        "libicuuc",
+        "libandroidicu",
         "libutils",
         "liblog",
         "libdl",
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 41d1833..01efb22 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -27,7 +27,6 @@
         "libmediadrmmetrics_lite",
         "libmediametrics",
         "libmediautils",
-        "libprotobuf-cpp-lite",
         "libstagefright_foundation",
         "libutils",
         "android.hardware.drm@1.0",
@@ -60,13 +59,11 @@
     shared_libs: [
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
-        "libbase",
         "libbinder",
         "libhidlbase",
         "liblog",
         "libmediametrics",
         "libprotobuf-cpp-lite",
-        "libstagefright_foundation",
         "libutils",
     ],
     cflags: [
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 14ff493..66c509f 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -553,12 +553,14 @@
         const String8& appPackageName) {
     Mutex::Autolock autoLock(mLock);
 
-    for (size_t i = 0; i < mFactories.size(); i++) {
+    for (size_t i = mFactories.size() - 1; i >= 0; i--) {
         if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
-            mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
-            if (mPlugin != NULL) {
+            auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
+            if (plugin != NULL) {
+                mPlugin = plugin;
                 mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
                 mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
+                break;
             }
         }
     }
@@ -567,6 +569,9 @@
         mInitCheck = ERROR_UNSUPPORTED;
     } else {
         if (!mPlugin->setListener(this).isOk()) {
+            mPlugin = NULL;
+            mPluginV1_1 = NULL;
+            mPluginV1_2 = NULL;
             mInitCheck = DEAD_OBJECT;
         } else {
             mInitCheck = OK;
diff --git a/include/media/MediaExtractorPluginApi.h b/include/media/MediaExtractorPluginApi.h
index 854bf83..916472c 100644
--- a/include/media/MediaExtractorPluginApi.h
+++ b/include/media/MediaExtractorPluginApi.h
@@ -135,8 +135,16 @@
     const char *extractor_name;
 
     union {
-        SnifferFunc v2;
-    } sniff;
+        struct {
+            SnifferFunc sniff;
+        } v2;
+        struct {
+            SnifferFunc sniff;
+            // a NULL terminated list of container mime types and/or file extensions
+            // that this extractor supports
+            const char **supported_types;
+        } v3;
+    } u;
 };
 
 // the C++ based API which first shipped in P and is no longer supported
@@ -145,7 +153,10 @@
 // the first C/NDK based API
 const uint32_t EXTRACTORDEF_VERSION_NDK_V1 = 2;
 
-const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_NDK_V1;
+// the second C/NDK based API
+const uint32_t EXTRACTORDEF_VERSION_NDK_V2 = 3;
+
+const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_NDK_V2;
 
 // each plugin library exports one function of this type
 typedef ExtractorDef (*GetExtractorDef)();
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index f1e815b..dfb1a3f 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -16,3 +16,6 @@
     stop audioserver
 on property:vts.native_server.on=0
     start audioserver
+
+on init
+    mkdir /dev/socket/audioserver 0775 audioserver audioserver
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index aeefbdb..87730ae 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -468,7 +468,8 @@
 
             if (outargs.numOutBytes > 0) {
                 mInputSize = 0;
-                int consumed = ((capacity / sizeof(int16_t)) - inargs.numInSamples);
+                int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples
+                        + outargs.numInSamples;
                 mInputTimeUs = work->input.ordinal.timestamp
                         + (consumed * 1000000ll / channelCount / sampleRate);
                 buffer = createLinearBuffer(block, 0, outargs.numOutBytes);
diff --git a/media/codec2/components/aom/Android.bp b/media/codec2/components/aom/Android.bp
new file mode 100644
index 0000000..0fabf5c
--- /dev/null
+++ b/media/codec2/components/aom/Android.bp
@@ -0,0 +1,14 @@
+cc_library_shared {
+    name: "libcodec2_soft_av1dec",
+    defaults: [
+        "libcodec2_soft-defaults",
+        "libcodec2_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["C2SoftAomDec.cpp"],
+    static_libs: ["libaom"],
+
+    include_dirs: [
+        "external/libaom/",
+    ],
+}
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
new file mode 100644
index 0000000..6be1807
--- /dev/null
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -0,0 +1,750 @@
+/*
+ * 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
+#define LOG_TAG "C2SoftAomDec"
+#include <log/log.h>
+
+#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+#include <SimpleC2Interface.h>
+
+#include "C2SoftAomDec.h"
+
+namespace android {
+
+constexpr char COMPONENT_NAME[] = "c2.android.av1.decoder";
+
+class C2SoftAomDec::IntfImpl : public SimpleInterface<void>::BaseParams {
+  public:
+    explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
+        : SimpleInterface<void>::BaseParams(
+              helper, COMPONENT_NAME, C2Component::KIND_DECODER,
+              C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_AV1) {
+        noPrivateBuffers();  // TODO: account for our buffers here
+        noInputReferences();
+        noOutputReferences();
+        noInputLatency();
+        noTimeStretch();
+
+        addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
+                         .withConstValue(new C2ComponentAttributesSetting(
+                             C2Component::ATTRIB_IS_TEMPORAL))
+                         .build());
+
+        addParameter(
+            DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
+                .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
+                .withFields({
+                    C2F(mSize, width).inRange(2, 2048, 2),
+                    C2F(mSize, height).inRange(2, 2048, 2),
+                })
+                .withSetter(SizeSetter)
+                .build());
+
+        addParameter(
+                DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+                .withDefault(new C2StreamProfileLevelInfo::input(0u,
+                        C2Config::PROFILE_AV1_0, C2Config::LEVEL_AV1_2_1))
+                .withFields({
+                    C2F(mProfileLevel, profile).oneOf({
+                            C2Config::PROFILE_AV1_0,
+                            C2Config::PROFILE_AV1_1}),
+                    C2F(mProfileLevel, level).oneOf({
+                            C2Config::LEVEL_AV1_2,
+                            C2Config::LEVEL_AV1_2_1,
+                            C2Config::LEVEL_AV1_2_2,
+                            C2Config::LEVEL_AV1_3,
+                            C2Config::LEVEL_AV1_3_1,
+                            C2Config::LEVEL_AV1_3_2,
+                    })
+                })
+                .withSetter(ProfileLevelSetter, mSize)
+                .build());
+
+        addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
+                         .withDefault(new C2StreamMaxPictureSizeTuning::output(
+                             0u, 320, 240))
+                         .withFields({
+                             C2F(mSize, width).inRange(2, 2048, 2),
+                             C2F(mSize, height).inRange(2, 2048, 2),
+                         })
+                         .withSetter(MaxPictureSizeSetter, mSize)
+                         .build());
+
+        addParameter(
+            DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
+                .withDefault(
+                    new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+                .withFields({
+                    C2F(mMaxInputSize, value).any(),
+                })
+                .calculatedAs(MaxInputSizeSetter, mMaxSize)
+                .build());
+
+        C2ChromaOffsetStruct locations[1] = {
+            C2ChromaOffsetStruct::ITU_YUV_420_0()};
+        std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
+            C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
+                                                   C2Color::YUV_420);
+        memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
+
+        defaultColorInfo = C2StreamColorInfo::output::AllocShared(
+            {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
+            C2Color::YUV_420);
+        helper->addStructDescriptors<C2ChromaOffsetStruct>();
+
+        addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
+                         .withConstValue(defaultColorInfo)
+                         .build());
+
+        addParameter(
+                DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
+                .withDefault(new C2StreamColorAspectsTuning::output(
+                        0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+                        C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                .withFields({
+                    C2F(mDefaultColorAspects, range).inRange(
+                                C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
+                    C2F(mDefaultColorAspects, primaries).inRange(
+                                C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+                    C2F(mDefaultColorAspects, transfer).inRange(
+                                C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
+                    C2F(mDefaultColorAspects, matrix).inRange(
+                                C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
+                })
+                .withSetter(DefaultColorAspectsSetter)
+                .build());
+
+        // TODO: support more formats?
+        addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
+                         .withConstValue(new C2StreamPixelFormatInfo::output(
+                             0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
+                         .build());
+    }
+
+    static C2R SizeSetter(bool mayBlock,
+                          const C2P<C2StreamPictureSizeInfo::output>& oldMe,
+                          C2P<C2VideoSizeStreamInfo::output>& me) {
+        (void)mayBlock;
+        C2R res = C2R::Ok();
+        if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
+            res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
+            me.set().width = oldMe.v.width;
+        }
+        if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
+            res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
+            me.set().height = oldMe.v.height;
+        }
+        return res;
+    }
+
+    static C2R MaxPictureSizeSetter(
+        bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output>& me,
+        const C2P<C2StreamPictureSizeInfo::output>& size) {
+        (void)mayBlock;
+        // TODO: get max width/height from the size's field helpers vs.
+        // hardcoding
+        me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
+        me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
+        return C2R::Ok();
+    }
+
+    static C2R MaxInputSizeSetter(
+        bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input>& me,
+        const C2P<C2StreamMaxPictureSizeTuning::output>& maxSize) {
+        (void)mayBlock;
+        // assume compression ratio of 2
+        me.set().value = (((maxSize.v.width + 63) / 64) *
+                          ((maxSize.v.height + 63) / 64) * 3072);
+        return C2R::Ok();
+    }
+    static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
+        (void)mayBlock;
+        if (me.v.range > C2Color::RANGE_OTHER) {
+            me.set().range = C2Color::RANGE_OTHER;
+        }
+        if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
+            me.set().primaries = C2Color::PRIMARIES_OTHER;
+        }
+        if (me.v.transfer > C2Color::TRANSFER_OTHER) {
+            me.set().transfer = C2Color::TRANSFER_OTHER;
+        }
+        if (me.v.matrix > C2Color::MATRIX_OTHER) {
+            me.set().matrix = C2Color::MATRIX_OTHER;
+        }
+        return C2R::Ok();
+    }
+
+    static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
+                                  const C2P<C2StreamPictureSizeInfo::output> &size) {
+        (void)mayBlock;
+        (void)size;
+        (void)me;  // TODO: validate
+        return C2R::Ok();
+    }
+    std::shared_ptr<C2StreamColorAspectsTuning::output> getDefaultColorAspects_l() {
+        return mDefaultColorAspects;
+    }
+
+  private:
+    std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
+    std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
+    std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
+    std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
+    std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
+    std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
+    std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
+};
+
+C2SoftAomDec::C2SoftAomDec(const char* name, c2_node_id_t id,
+                           const std::shared_ptr<IntfImpl>& intfImpl)
+    : SimpleC2Component(
+          std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
+      mIntf(intfImpl),
+      mCodecCtx(nullptr){
+
+    GENERATE_FILE_NAMES();
+    CREATE_DUMP_FILE(mInFile);
+    CREATE_DUMP_FILE(mOutFile);
+
+    gettimeofday(&mTimeStart, nullptr);
+    gettimeofday(&mTimeEnd, nullptr);
+}
+
+C2SoftAomDec::~C2SoftAomDec() {
+    onRelease();
+}
+
+c2_status_t C2SoftAomDec::onInit() {
+    status_t err = initDecoder();
+    return err == OK ? C2_OK : C2_CORRUPTED;
+}
+
+c2_status_t C2SoftAomDec::onStop() {
+    mSignalledError = false;
+    mSignalledOutputEos = false;
+    return C2_OK;
+}
+
+void C2SoftAomDec::onReset() {
+    (void)onStop();
+    c2_status_t err = onFlush_sm();
+    if (err != C2_OK) {
+        ALOGW("Failed to flush decoder. Try to hard reset decoder.");
+        destroyDecoder();
+        (void)initDecoder();
+    }
+}
+
+void C2SoftAomDec::onRelease() {
+    destroyDecoder();
+}
+
+c2_status_t C2SoftAomDec::onFlush_sm() {
+    if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
+        ALOGE("Failed to flush av1 decoder.");
+        return C2_CORRUPTED;
+    }
+
+    aom_codec_iter_t iter = nullptr;
+    while (aom_codec_get_frame(mCodecCtx, &iter)) {
+    }
+
+    mSignalledError = false;
+    mSignalledOutputEos = false;
+
+    return C2_OK;
+}
+
+static int GetCPUCoreCount() {
+    int cpuCoreCount = 1;
+#if defined(_SC_NPROCESSORS_ONLN)
+    cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+    // _SC_NPROC_ONLN must be defined...
+    cpuCoreCount = sysconf(_SC_NPROC_ONLN);
+#endif
+    CHECK(cpuCoreCount >= 1);
+    ALOGV("Number of CPU cores: %d", cpuCoreCount);
+    return cpuCoreCount;
+}
+
+status_t C2SoftAomDec::initDecoder() {
+    mSignalledError = false;
+    mSignalledOutputEos = false;
+    if (!mCodecCtx) {
+        mCodecCtx = new aom_codec_ctx_t;
+    }
+
+    if (!mCodecCtx) {
+        ALOGE("mCodecCtx is null");
+        return NO_MEMORY;
+    }
+
+    aom_codec_dec_cfg_t cfg;
+    memset(&cfg, 0, sizeof(aom_codec_dec_cfg_t));
+    cfg.threads = GetCPUCoreCount();
+    cfg.allow_lowbitdepth = 1;
+
+    aom_codec_flags_t flags;
+    memset(&flags, 0, sizeof(aom_codec_flags_t));
+
+    aom_codec_err_t err;
+    if ((err = aom_codec_dec_init(mCodecCtx, aom_codec_av1_dx(), &cfg, 0))) {
+        ALOGE("av1 decoder failed to initialize. (%d)", err);
+        return UNKNOWN_ERROR;
+    }
+
+    return OK;
+}
+
+status_t C2SoftAomDec::destroyDecoder() {
+    if (mCodecCtx) {
+        aom_codec_destroy(mCodecCtx);
+        delete mCodecCtx;
+        mCodecCtx = nullptr;
+    }
+    return OK;
+}
+
+void fillEmptyWork(const std::unique_ptr<C2Work>& work) {
+    uint32_t flags = 0;
+    if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
+        flags |= C2FrameData::FLAG_END_OF_STREAM;
+        ALOGV("signalling eos");
+    }
+    work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
+    work->worklets.front()->output.buffers.clear();
+    work->worklets.front()->output.ordinal = work->input.ordinal;
+    work->workletsProcessed = 1u;
+}
+
+void C2SoftAomDec::finishWork(uint64_t index,
+                              const std::unique_ptr<C2Work>& work,
+                              const std::shared_ptr<C2GraphicBlock>& block) {
+    std::shared_ptr<C2Buffer> buffer =
+        createGraphicBuffer(block, C2Rect(mWidth, mHeight));
+    auto fillWork = [buffer, index](const std::unique_ptr<C2Work>& work) {
+        uint32_t flags = 0;
+        if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
+            (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
+            flags |= C2FrameData::FLAG_END_OF_STREAM;
+            ALOGV("signalling eos");
+        }
+        work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
+        work->worklets.front()->output.buffers.clear();
+        work->worklets.front()->output.buffers.push_back(buffer);
+        work->worklets.front()->output.ordinal = work->input.ordinal;
+        work->workletsProcessed = 1u;
+    };
+    if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
+        fillWork(work);
+    } else {
+        finish(index, fillWork);
+    }
+}
+
+void C2SoftAomDec::process(const std::unique_ptr<C2Work>& work,
+                           const std::shared_ptr<C2BlockPool>& pool) {
+    work->result = C2_OK;
+    work->workletsProcessed = 0u;
+    work->worklets.front()->output.configUpdate.clear();
+    work->worklets.front()->output.flags = work->input.flags;
+    if (mSignalledError || mSignalledOutputEos) {
+        work->result = C2_BAD_VALUE;
+        return;
+    }
+
+    size_t inOffset = 0u;
+    size_t inSize = 0u;
+    C2ReadView rView = mDummyReadView;
+    if (!work->input.buffers.empty()) {
+        rView =
+            work->input.buffers[0]->data().linearBlocks().front().map().get();
+        inSize = rView.capacity();
+        if (inSize && rView.error()) {
+            ALOGE("read view map failed %d", rView.error());
+            work->result = C2_CORRUPTED;
+            return;
+        }
+    }
+
+    bool codecConfig =
+        ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
+    bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
+
+    ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
+          inSize, (int)work->input.ordinal.timestamp.peeku(),
+          (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
+
+    if (codecConfig) {
+        fillEmptyWork(work);
+        return;
+    }
+
+    int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
+    if (inSize) {
+        uint8_t* bitstream = const_cast<uint8_t*>(rView.data() + inOffset);
+        int32_t decodeTime = 0;
+        int32_t delay = 0;
+
+        DUMP_TO_FILE(mOutFile, bitstream, inSize);
+        GETTIME(&mTimeStart, nullptr);
+        TIME_DIFF(mTimeEnd, mTimeStart, delay);
+
+        aom_codec_err_t err =
+            aom_codec_decode(mCodecCtx, bitstream, inSize, &frameIndex);
+
+        GETTIME(&mTimeEnd, nullptr);
+        TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
+        ALOGV("decodeTime=%4d delay=%4d\n", decodeTime, delay);
+
+        if (err != AOM_CODEC_OK) {
+            ALOGE("av1 decoder failed to decode frame err: %d", err);
+            work->result = C2_CORRUPTED;
+            work->workletsProcessed = 1u;
+            mSignalledError = true;
+            return;
+        }
+
+    } else {
+        if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
+            ALOGE("Failed to flush av1 decoder.");
+            work->result = C2_CORRUPTED;
+            work->workletsProcessed = 1u;
+            mSignalledError = true;
+            return;
+        }
+    }
+
+    (void)outputBuffer(pool, work);
+
+    if (eos) {
+        drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
+        mSignalledOutputEos = true;
+    } else if (!inSize) {
+        fillEmptyWork(work);
+    }
+}
+
+static void copyOutputBufferToYV12Frame(uint8_t *dst,
+        const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
+        size_t srcYStride, size_t srcUStride, size_t srcVStride,
+        uint32_t width, uint32_t height) {
+    size_t dstYStride = align(width, 16);
+    size_t dstUVStride = align(dstYStride / 2, 16);
+    uint8_t* dstStart = dst;
+
+
+    for (size_t i = 0; i < height; ++i) {
+        memcpy(dst, srcY, width);
+        srcY += srcYStride;
+        dst += dstYStride;
+    }
+
+    dst = dstStart + dstYStride * height;
+    for (size_t i = 0; i < height / 2; ++i) {
+         memcpy(dst, srcV, width / 2);
+        srcV += srcVStride;
+        dst += dstUVStride;
+    }
+
+    dst = dstStart + (dstYStride * height) + (dstUVStride * height / 2);
+    for (size_t i = 0; i < height / 2; ++i) {
+         memcpy(dst, srcU, width / 2);
+        srcU += srcUStride;
+        dst += dstUVStride;
+    }
+}
+
+static void convertYUV420Planar16ToY410(uint32_t *dst,
+        const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
+        size_t srcYStride, size_t srcUStride, size_t srcVStride,
+        size_t dstStride, size_t width, size_t height) {
+
+    // Converting two lines at a time, slightly faster
+    for (size_t y = 0; y < height; y += 2) {
+        uint32_t *dstTop = (uint32_t *) dst;
+        uint32_t *dstBot = (uint32_t *) (dst + dstStride);
+        uint16_t *ySrcTop = (uint16_t*) srcY;
+        uint16_t *ySrcBot = (uint16_t*) (srcY + srcYStride);
+        uint16_t *uSrc = (uint16_t*) srcU;
+        uint16_t *vSrc = (uint16_t*) srcV;
+
+        uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
+        size_t x = 0;
+        for (; x < width - 3; x += 4) {
+
+            u01 = *((uint32_t*)uSrc); uSrc += 2;
+            v01 = *((uint32_t*)vSrc); vSrc += 2;
+
+            y01 = *((uint32_t*)ySrcTop); ySrcTop += 2;
+            y23 = *((uint32_t*)ySrcTop); ySrcTop += 2;
+            y45 = *((uint32_t*)ySrcBot); ySrcBot += 2;
+            y67 = *((uint32_t*)ySrcBot); ySrcBot += 2;
+
+            uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+            uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
+
+            *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
+            *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
+            *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
+            *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
+
+            *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
+            *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
+            *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
+            *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
+        }
+
+        // There should be at most 2 more pixels to process. Note that we don't
+        // need to consider odd case as the buffer is always aligned to even.
+        if (x < width) {
+            u01 = *uSrc;
+            v01 = *vSrc;
+            y01 = *((uint32_t*)ySrcTop);
+            y45 = *((uint32_t*)ySrcBot);
+            uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+            *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
+            *dstTop++ = ((y01 >> 16) << 10) | uv0;
+            *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
+            *dstBot++ = ((y45 >> 16) << 10) | uv0;
+        }
+
+        srcY += srcYStride * 2;
+        srcU += srcUStride;
+        srcV += srcVStride;
+        dst += dstStride * 2;
+    }
+
+    return;
+}
+
+static void convertYUV420Planar16ToYUV420Planar(uint8_t *dst,
+        const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
+        size_t srcYStride, size_t srcUStride, size_t srcVStride,
+        size_t dstStride, size_t width, size_t height) {
+
+    uint8_t *dstY = (uint8_t *)dst;
+    size_t dstYSize = dstStride * height;
+    size_t dstUVStride = align(dstStride / 2, 16);
+    size_t dstUVSize = dstUVStride * height / 2;
+    uint8_t *dstV = dstY + dstYSize;
+    uint8_t *dstU = dstV + dstUVSize;
+
+    for (size_t y = 0; y < height; ++y) {
+        for (size_t x = 0; x < width; ++x) {
+            dstY[x] = (uint8_t)(srcY[x] >> 2);
+        }
+
+        srcY += srcYStride;
+        dstY += dstStride;
+    }
+
+    for (size_t y = 0; y < (height + 1) / 2; ++y) {
+        for (size_t x = 0; x < (width + 1) / 2; ++x) {
+            dstU[x] = (uint8_t)(srcU[x] >> 2);
+            dstV[x] = (uint8_t)(srcV[x] >> 2);
+        }
+
+        srcU += srcUStride;
+        srcV += srcVStride;
+        dstU += dstUVStride;
+        dstV += dstUVStride;
+    }
+    return;
+}
+bool C2SoftAomDec::outputBuffer(
+        const std::shared_ptr<C2BlockPool> &pool,
+        const std::unique_ptr<C2Work> &work)
+{
+    if (!(work && pool)) return false;
+
+    aom_codec_iter_t iter = nullptr;
+    aom_image_t* img = aom_codec_get_frame(mCodecCtx, &iter);
+
+    if (!img) return false;
+
+    if (img->d_w != mWidth || img->d_h != mHeight) {
+        mWidth = img->d_w;
+        mHeight = img->d_h;
+
+        C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight);
+        std::vector<std::unique_ptr<C2SettingResult>> failures;
+        c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
+        if (err == C2_OK) {
+            work->worklets.front()->output.configUpdate.push_back(
+                C2Param::Copy(size));
+        } else {
+            ALOGE("Config update size failed");
+            mSignalledError = true;
+            work->result = C2_CORRUPTED;
+            work->workletsProcessed = 1u;
+            return false;
+        }
+    }
+
+    CHECK(img->fmt == AOM_IMG_FMT_I420 || img->fmt == AOM_IMG_FMT_I42016);
+
+    std::shared_ptr<C2GraphicBlock> block;
+    uint32_t format = HAL_PIXEL_FORMAT_YV12;
+    if (img->fmt == AOM_IMG_FMT_I42016) {
+        IntfImpl::Lock lock = mIntf->lock();
+        std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects = mIntf->getDefaultColorAspects_l();
+
+        if (defaultColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
+            defaultColorAspects->matrix == C2Color::MATRIX_BT2020 &&
+            defaultColorAspects->transfer == C2Color::TRANSFER_ST2084) {
+            format = HAL_PIXEL_FORMAT_RGBA_1010102;
+        }
+    }
+    C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
+
+    c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight,
+                                              format, usage, &block);
+
+    if (err != C2_OK) {
+        ALOGE("fetchGraphicBlock for Output failed with status %d", err);
+        work->result = err;
+        return false;
+    }
+
+    C2GraphicView wView = block->map().get();
+
+    if (wView.error()) {
+        ALOGE("graphic view map failed %d", wView.error());
+        work->result = C2_CORRUPTED;
+        return false;
+    }
+
+    ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d",
+          block->width(), block->height(), mWidth, mHeight,
+          (int)*(int64_t*)img->user_priv);
+
+    uint8_t* dst = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_Y]);
+    size_t srcYStride = img->stride[AOM_PLANE_Y];
+    size_t srcUStride = img->stride[AOM_PLANE_U];
+    size_t srcVStride = img->stride[AOM_PLANE_V];
+
+    if (img->fmt == AOM_IMG_FMT_I42016) {
+        const uint16_t *srcY = (const uint16_t *)img->planes[AOM_PLANE_Y];
+        const uint16_t *srcU = (const uint16_t *)img->planes[AOM_PLANE_U];
+        const uint16_t *srcV = (const uint16_t *)img->planes[AOM_PLANE_V];
+
+        if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
+            convertYUV420Planar16ToY410((uint32_t *)dst, srcY, srcU, srcV, srcYStride / 2,
+                                    srcUStride / 2, srcVStride / 2,
+                                    align(mWidth, 16),
+                                    mWidth, mHeight);
+        } else {
+            convertYUV420Planar16ToYUV420Planar(dst, srcY, srcU, srcV, srcYStride / 2,
+                                    srcUStride / 2, srcVStride / 2,
+                                    align(mWidth, 16),
+                                    mWidth, mHeight);
+        }
+    } else {
+        const uint8_t *srcY = (const uint8_t *)img->planes[AOM_PLANE_Y];
+        const uint8_t *srcU = (const uint8_t *)img->planes[AOM_PLANE_U];
+        const uint8_t *srcV = (const uint8_t *)img->planes[AOM_PLANE_V];
+        copyOutputBufferToYV12Frame(dst, srcY, srcU, srcV,
+                                srcYStride, srcUStride, srcVStride, mWidth, mHeight);
+    }
+    finishWork(*(int64_t*)img->user_priv, work, std::move(block));
+    block = nullptr;
+    return true;
+}
+
+c2_status_t C2SoftAomDec::drainInternal(
+    uint32_t drainMode, const std::shared_ptr<C2BlockPool>& pool,
+    const std::unique_ptr<C2Work>& work) {
+    if (drainMode == NO_DRAIN) {
+        ALOGW("drain with NO_DRAIN: no-op");
+        return C2_OK;
+    }
+    if (drainMode == DRAIN_CHAIN) {
+        ALOGW("DRAIN_CHAIN not supported");
+        return C2_OMITTED;
+    }
+
+    if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
+        ALOGE("Failed to flush av1 decoder.");
+        return C2_CORRUPTED;
+    }
+
+    while ((outputBuffer(pool, work))) {
+    }
+
+    if (drainMode == DRAIN_COMPONENT_WITH_EOS && work &&
+        work->workletsProcessed == 0u) {
+        fillEmptyWork(work);
+    }
+
+    return C2_OK;
+}
+
+c2_status_t C2SoftAomDec::drain(uint32_t drainMode,
+                                const std::shared_ptr<C2BlockPool>& pool) {
+    return drainInternal(drainMode, pool, nullptr);
+}
+
+class C2SoftAomFactory : public C2ComponentFactory {
+   public:
+    C2SoftAomFactory()
+        : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
+              GetCodec2PlatformComponentStore()->getParamReflector())) {}
+
+    virtual c2_status_t createComponent(
+        c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+        std::function<void(C2Component*)> deleter) override {
+        *component = std::shared_ptr<C2Component>(
+            new C2SoftAomDec(COMPONENT_NAME, id,
+                             std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
+            deleter);
+        return C2_OK;
+    }
+
+    virtual c2_status_t createInterface(
+        c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+        std::function<void(C2ComponentInterface*)> deleter) override {
+        *interface = std::shared_ptr<C2ComponentInterface>(
+            new SimpleInterface<C2SoftAomDec::IntfImpl>(
+                COMPONENT_NAME, id,
+                std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
+            deleter);
+        return C2_OK;
+    }
+
+    virtual ~C2SoftAomFactory() override = default;
+
+   private:
+    std::shared_ptr<C2ReflectorHelper> mHelper;
+};
+
+}  // namespace android
+
+extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
+    ALOGV("in %s", __func__);
+    return new ::android::C2SoftAomFactory();
+}
+
+extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
+    ALOGV("in %s", __func__);
+    delete factory;
+}
diff --git a/media/codec2/components/aom/C2SoftAomDec.h b/media/codec2/components/aom/C2SoftAomDec.h
new file mode 100644
index 0000000..4c82647
--- /dev/null
+++ b/media/codec2/components/aom/C2SoftAomDec.h
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_C2_SOFT_AV1_DEC_H_
+#define ANDROID_C2_SOFT_AV1_DEC_H_
+
+#include <SimpleC2Component.h>
+#include "aom/aom_decoder.h"
+#include "aom/aomdx.h"
+
+#define GETTIME(a, b) gettimeofday(a, b);
+#define TIME_DIFF(start, end, diff)     \
+    diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
+            ((end).tv_usec - (start).tv_usec);
+
+namespace android {
+
+struct C2SoftAomDec : public SimpleC2Component {
+    class IntfImpl;
+
+    C2SoftAomDec(const char* name, c2_node_id_t id,
+                 const std::shared_ptr<IntfImpl>& intfImpl);
+    virtual ~C2SoftAomDec();
+
+    // From SimpleC2Component
+    c2_status_t onInit() override;
+    c2_status_t onStop() override;
+    void onReset() override;
+    void onRelease() override;
+    c2_status_t onFlush_sm() override;
+    void process(const std::unique_ptr<C2Work>& work,
+                 const std::shared_ptr<C2BlockPool>& pool) override;
+    c2_status_t drain(uint32_t drainMode,
+                      const std::shared_ptr<C2BlockPool>& pool) override;
+
+   private:
+    std::shared_ptr<IntfImpl> mIntf;
+    aom_codec_ctx_t* mCodecCtx;
+
+    uint32_t mWidth;
+    uint32_t mHeight;
+    bool mSignalledOutputEos;
+    bool mSignalledError;
+
+    #ifdef FILE_DUMP_ENABLE
+    char mInFile[200];
+    char mOutFile[200];
+    #endif /* FILE_DUMP_ENABLE */
+
+    struct timeval mTimeStart;   // Time at the start of decode()
+    struct timeval mTimeEnd;     // Time at the end of decode()
+
+    status_t initDecoder();
+    status_t destroyDecoder();
+    void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
+                    const std::shared_ptr<C2GraphicBlock>& block);
+    bool outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
+                      const std::unique_ptr<C2Work>& work);
+
+    c2_status_t drainInternal(uint32_t drainMode,
+                              const std::shared_ptr<C2BlockPool>& pool,
+                              const std::unique_ptr<C2Work>& work);
+
+    C2_DO_NOT_COPY(C2SoftAomDec);
+};
+
+#ifdef FILE_DUMP_ENABLE
+
+#define INPUT_DUMP_PATH "/data/local/tmp/temp/av1"
+#define INPUT_DUMP_EXT "webm"
+#define OUTPUT_DUMP_PATH "/data/local/tmp/temp/av1"
+#define OUTPUT_DUMP_EXT "av1"
+#define GENERATE_FILE_NAMES()                                                 \
+    {                                                                         \
+        GETTIME(&mTimeStart, NULL);                                           \
+        strcpy(mInFile, "");                                                  \
+        ALOGD("GENERATE_FILE_NAMES");                                         \
+        sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, mTimeStart.tv_sec, \
+                mTimeStart.tv_usec, INPUT_DUMP_EXT);                          \
+        strcpy(mOutFile, "");                                                 \
+        sprintf(mOutFile, "%s_%ld.%ld.%s", OUTPUT_DUMP_PATH,                  \
+                mTimeStart.tv_sec, mTimeStart.tv_usec, OUTPUT_DUMP_EXT);      \
+    }
+
+#define CREATE_DUMP_FILE(m_filename)                     \
+    {                                                    \
+        FILE* fp = fopen(m_filename, "wb");              \
+        if (fp != NULL) {                                \
+            ALOGD("Opened file %s", m_filename);         \
+            fclose(fp);                                  \
+        } else {                                         \
+            ALOGD("Could not open file %s", m_filename); \
+        }                                                \
+    }
+#define DUMP_TO_FILE(m_filename, m_buf, m_size)              \
+    {                                                        \
+        FILE* fp = fopen(m_filename, "ab");                  \
+        if (fp != NULL && m_buf != NULL) {                   \
+            int i;                                           \
+            ALOGD("Dump to file!");                          \
+            i = fwrite(m_buf, 1, m_size, fp);                \
+            if (i != (int)m_size) {                          \
+                ALOGD("Error in fwrite, returned %d", i);    \
+                perror("Error in write to file");            \
+            }                                                \
+            fclose(fp);                                      \
+        } else {                                             \
+            ALOGD("Could not write to file %s", m_filename); \
+            if (fp != NULL) fclose(fp);                      \
+        }                                                    \
+    }
+#else /* FILE_DUMP_ENABLE */
+#define INPUT_DUMP_PATH
+#define INPUT_DUMP_EXT
+#define OUTPUT_DUMP_PATH
+#define OUTPUT_DUMP_EXT
+#define GENERATE_FILE_NAMES()
+#define CREATE_DUMP_FILE(m_filename)
+#define DUMP_TO_FILE(m_filename, m_buf, m_size)
+#endif /* FILE_DUMP_ENABLE */
+
+}  // namespace android
+
+#endif  // ANDROID_C2_SOFT_AV1_DEC_H_
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 50b4d20..b8baec8 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -132,6 +132,56 @@
     }
 }
 
+class SimpleC2Component::BlockingBlockPool : public C2BlockPool {
+public:
+    BlockingBlockPool(const std::shared_ptr<C2BlockPool>& base): mBase{base} {}
+
+    virtual local_id_t getLocalId() const override {
+        return mBase->getLocalId();
+    }
+
+    virtual C2Allocator::id_t getAllocatorId() const override {
+        return mBase->getAllocatorId();
+    }
+
+    virtual c2_status_t fetchLinearBlock(
+            uint32_t capacity,
+            C2MemoryUsage usage,
+            std::shared_ptr<C2LinearBlock>* block) {
+        c2_status_t status;
+        do {
+            status = mBase->fetchLinearBlock(capacity, usage, block);
+        } while (status == C2_TIMED_OUT);
+        return status;
+    }
+
+    virtual c2_status_t fetchCircularBlock(
+            uint32_t capacity,
+            C2MemoryUsage usage,
+            std::shared_ptr<C2CircularBlock>* block) {
+        c2_status_t status;
+        do {
+            status = mBase->fetchCircularBlock(capacity, usage, block);
+        } while (status == C2_TIMED_OUT);
+        return status;
+    }
+
+    virtual c2_status_t fetchGraphicBlock(
+            uint32_t width, uint32_t height, uint32_t format,
+            C2MemoryUsage usage,
+            std::shared_ptr<C2GraphicBlock>* block) {
+        c2_status_t status;
+        do {
+            status = mBase->fetchGraphicBlock(width, height, format, usage,
+                                              block);
+        } while (status == C2_TIMED_OUT);
+        return status;
+    }
+
+private:
+    std::shared_ptr<C2BlockPool> mBase;
+};
+
 ////////////////////////////////////////////////////////////////////////////////
 
 namespace {
@@ -446,12 +496,16 @@
                 }
             }
 
-            err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool);
+            std::shared_ptr<C2BlockPool> blockPool;
+            err = GetCodec2BlockPool(poolId, shared_from_this(), &blockPool);
             ALOGD("Using output block pool with poolID %llu => got %llu - %d",
                     (unsigned long long)poolId,
                     (unsigned long long)(
-                            mOutputBlockPool ? mOutputBlockPool->getLocalId() : 111000111),
+                            blockPool ? blockPool->getLocalId() : 111000111),
                     err);
+            if (err == C2_OK) {
+                mOutputBlockPool = std::make_shared<BlockingBlockPool>(blockPool);
+            }
             return err;
         }();
         if (err != C2_OK) {
diff --git a/media/codec2/components/base/include/SimpleC2Component.h b/media/codec2/components/base/include/SimpleC2Component.h
index b3a98f4..43029a9 100644
--- a/media/codec2/components/base/include/SimpleC2Component.h
+++ b/media/codec2/components/base/include/SimpleC2Component.h
@@ -234,7 +234,8 @@
     typedef std::unordered_map<uint64_t, std::unique_ptr<C2Work>> PendingWork;
     Mutexed<PendingWork> mPendingWork;
 
-    std::shared_ptr<C2BlockPool> mOutputBlockPool;
+    class BlockingBlockPool;
+    std::shared_ptr<BlockingBlockPool> mOutputBlockPool;
 
     SimpleC2Component() = delete;
 };
diff --git a/media/codec2/components/flac/Android.bp b/media/codec2/components/flac/Android.bp
index d485964..e5eb51d 100644
--- a/media/codec2/components/flac/Android.bp
+++ b/media/codec2/components/flac/Android.bp
@@ -23,5 +23,8 @@
 
     srcs: ["C2SoftFlacEnc.cpp"],
 
-    static_libs: ["libFLAC"],
+    static_libs: [
+        "libaudioutils",
+        "libFLAC",
+    ],
 }
diff --git a/media/codec2/components/flac/C2SoftFlacDec.cpp b/media/codec2/components/flac/C2SoftFlacDec.cpp
index f1e2f51..86b16e8 100644
--- a/media/codec2/components/flac/C2SoftFlacDec.cpp
+++ b/media/codec2/components/flac/C2SoftFlacDec.cpp
@@ -83,8 +83,21 @@
                 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
                 .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 32768))
                 .build());
+
+        addParameter(
+                DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING)
+                .withDefault(new C2StreamPcmEncodingInfo::output(0u, C2Config::PCM_16))
+                .withFields({C2F(mPcmEncodingInfo, value).oneOf({
+                     C2Config::PCM_16,
+                     // C2Config::PCM_8,
+                     C2Config::PCM_FLOAT})
+                })
+                .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
+                .build());
     }
 
+    int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }
+
 private:
     std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
     std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
@@ -94,6 +107,7 @@
     std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
     std::shared_ptr<C2BitrateTuning::input> mBitrate;
     std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
+    std::shared_ptr<C2StreamPcmEncodingInfo::output> mPcmEncodingInfo;
 };
 
 C2SoftFlacDec::C2SoftFlacDec(
@@ -263,11 +277,11 @@
         return;
     }
 
-    size_t outSize;
-    if (mHasStreamInfo)
-        outSize = mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(short);
-    else
-        outSize = kMaxBlockSize * FLACDecoder::kMaxChannels * sizeof(short);
+    const bool outputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+    const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(short);
+    size_t outSize = mHasStreamInfo ?
+            mStreamInfo.max_blocksize * mStreamInfo.channels * sampleSize
+          : kMaxBlockSize * FLACDecoder::kMaxChannels * sampleSize;
 
     std::shared_ptr<C2LinearBlock> block;
     C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
@@ -284,9 +298,8 @@
         return;
     }
 
-    short *output = reinterpret_cast<short *>(wView.data());
     status_t decoderErr = mFLACDecoder->decodeOneFrame(
-                            input, inSize, output, &outSize);
+                            input, inSize, wView.data(), &outSize, outputFloat);
     if (decoderErr != OK) {
         ALOGE("process: FLACDecoder decodeOneFrame returns error %d", decoderErr);
         mSignalledError = true;
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index e4192c7..4ea35c2 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "C2SoftFlacEnc"
 #include <log/log.h>
 
+#include <audio_utils/primitives.h>
 #include <media/stagefright/foundation/MediaDefs.h>
 
 #include <C2PlatformSupport.h>
@@ -72,11 +73,23 @@
                 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
                 .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 4608))
                 .build());
+
+        addParameter(
+                DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING)
+                .withDefault(new C2StreamPcmEncodingInfo::input(0u, C2Config::PCM_16))
+                .withFields({C2F(mPcmEncodingInfo, value).oneOf({
+                     C2Config::PCM_16,
+                     // C2Config::PCM_8,
+                     C2Config::PCM_FLOAT})
+                })
+                .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
+                .build());
     }
 
     uint32_t getSampleRate() const { return mSampleRate->value; }
     uint32_t getChannelCount() const { return mChannelCount->value; }
     uint32_t getBitrate() const { return mBitrate->value; }
+    int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }
 
 private:
     std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
@@ -87,6 +100,7 @@
     std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount;
     std::shared_ptr<C2BitrateTuning::output> mBitrate;
     std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
+    std::shared_ptr<C2StreamPcmEncodingInfo::input> mPcmEncodingInfo;
 };
 constexpr char COMPONENT_NAME[] = "c2.android.flac.encoder";
 
@@ -224,12 +238,15 @@
         mWroteHeader = true;
     }
 
-    uint32_t sampleRate = mIntf->getSampleRate();
-    uint32_t channelCount = mIntf->getChannelCount();
-    uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
+    const uint32_t sampleRate = mIntf->getSampleRate();
+    const uint32_t channelCount = mIntf->getChannelCount();
+    const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+    const unsigned sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
+    const unsigned frameSize = channelCount * sampleSize;
+    const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
 
     size_t outCapacity = inSize;
-    outCapacity += mBlockSize * channelCount * sizeof(int16_t);
+    outCapacity += mBlockSize * frameSize;
 
     C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
     c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &mOutputBlock);
@@ -250,14 +267,19 @@
     size_t inPos = 0;
     while (inPos < inSize) {
         const uint8_t *inPtr = rView.data() + inOffset;
-        size_t processSize = MIN(kInBlockSize * channelCount * sizeof(int16_t), (inSize - inPos));
-        const unsigned nbInputFrames = processSize / (channelCount * sizeof(int16_t));
-        const unsigned nbInputSamples = processSize / sizeof(int16_t);
-        const int16_t *pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
-        ALOGV("about to encode %zu bytes", processSize);
+        const size_t processSize = MIN(kInBlockSize * frameSize, (inSize - inPos));
+        const unsigned nbInputFrames = processSize / frameSize;
+        const unsigned nbInputSamples = processSize / sampleSize;
 
-        for (unsigned i = 0; i < nbInputSamples; i++) {
-            mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+        ALOGV("about to encode %zu bytes", processSize);
+        if (inputFloat) {
+            const float * const pcmFloat = reinterpret_cast<const float *>(inPtr + inPos);
+            memcpy_to_q8_23_from_float_with_clamp(mInputBufferPcm32, pcmFloat, nbInputSamples);
+        } else {
+            const int16_t * const pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
+            for (unsigned i = 0; i < nbInputSamples; i++) {
+                mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+            }
         }
 
         FLAC__bool ok = FLAC__stream_encoder_process_interleaved(
@@ -342,10 +364,12 @@
         return UNKNOWN_ERROR;
     }
 
+    const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+    const int bitsPerSample = inputFloat ? 24 : 16;
     FLAC__bool ok = true;
     ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mIntf->getChannelCount());
     ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mIntf->getSampleRate());
-    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
+    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, bitsPerSample);
     ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder, mCompressionLevel);
     ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
     if (!ok) {
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 27aa064..cf1f6cf 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -392,6 +392,7 @@
     _C2_PL_HEVC_BASE = 0x6000,
     _C2_PL_VP9_BASE  = 0x7000,
     _C2_PL_DV_BASE   = 0x8000,
+    _C2_PL_AV1_BASE  = 0x9000,
 
     C2_PROFILE_LEVEL_VENDOR_START = 0x70000000,
 };
@@ -539,6 +540,11 @@
     PROFILE_DV_HE_07 = _C2_PL_DV_BASE + 7,      ///< Dolby Vision dvhe.07 profile
     PROFILE_DV_HE_08 = _C2_PL_DV_BASE + 8,      ///< Dolby Vision dvhe.08 profile
     PROFILE_DV_AV_09 = _C2_PL_DV_BASE + 9,      ///< Dolby Vision dvav.09 profile
+
+    // AV1 profiles
+    PROFILE_AV1_0 = _C2_PL_AV1_BASE,            ///< AV1 Profile 0 (4:2:0, 8 to 10 bit)
+    PROFILE_AV1_1,                              ///< AV1 Profile 1 (8 to 10 bit)
+    PROFILE_AV1_2,                              ///< AV1 Profile 2 (8 to 12 bit)
 };
 
 enum C2Config::level_t : uint32_t {
@@ -652,6 +658,31 @@
     LEVEL_DV_HIGH_UHD_30,                       ///< Dolby Vision high tier uhd30
     LEVEL_DV_HIGH_UHD_48,                       ///< Dolby Vision high tier uhd48
     LEVEL_DV_HIGH_UHD_60,                       ///< Dolby Vision high tier uhd60
+
+    LEVEL_AV1_2    = _C2_PL_AV1_BASE ,          ///< AV1 Level 2
+    LEVEL_AV1_2_1,                              ///< AV1 Level 2.1
+    LEVEL_AV1_2_2,                              ///< AV1 Level 2.2
+    LEVEL_AV1_2_3,                              ///< AV1 Level 2.3
+    LEVEL_AV1_3,                                ///< AV1 Level 3
+    LEVEL_AV1_3_1,                              ///< AV1 Level 3.1
+    LEVEL_AV1_3_2,                              ///< AV1 Level 3.2
+    LEVEL_AV1_3_3,                              ///< AV1 Level 3.3
+    LEVEL_AV1_4,                                ///< AV1 Level 4
+    LEVEL_AV1_4_1,                              ///< AV1 Level 4.1
+    LEVEL_AV1_4_2,                              ///< AV1 Level 4.2
+    LEVEL_AV1_4_3,                              ///< AV1 Level 4.3
+    LEVEL_AV1_5,                                ///< AV1 Level 5
+    LEVEL_AV1_5_1,                              ///< AV1 Level 5.1
+    LEVEL_AV1_5_2,                              ///< AV1 Level 5.2
+    LEVEL_AV1_5_3,                              ///< AV1 Level 5.3
+    LEVEL_AV1_6,                                ///< AV1 Level 6
+    LEVEL_AV1_6_1,                              ///< AV1 Level 6.1
+    LEVEL_AV1_6_2,                              ///< AV1 Level 6.2
+    LEVEL_AV1_6_3,                              ///< AV1 Level 6.3
+    LEVEL_AV1_7,                                ///< AV1 Level 7
+    LEVEL_AV1_7_1,                              ///< AV1 Level 7.1
+    LEVEL_AV1_7_2,                              ///< AV1 Level 7.2
+    LEVEL_AV1_7_3,                              ///< AV1 Level 7.3
 };
 
 struct C2ProfileLevelStruct {
diff --git a/media/codec2/core/include/C2Param.h b/media/codec2/core/include/C2Param.h
index 40be3b3..efc5c89 100644
--- a/media/codec2/core/include/C2Param.h
+++ b/media/codec2/core/include/C2Param.h
@@ -988,7 +988,10 @@
     /** specialization for easy enums */
     template<typename E>
     inline static NamedValuesType namedValuesFor(const C2EasyEnum<E> &) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         return namedValuesFor(*(E*)nullptr);
+#pragma GCC diagnostic pop
     }
 
 private:
@@ -1104,7 +1107,10 @@
 template<typename B>
 struct C2FieldDescriptor::_NamedValuesGetter<B, true> {
     inline static C2FieldDescriptor::NamedValuesType getNamedValues() {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         return C2FieldDescriptor::namedValuesFor(*(B*)nullptr);
+#pragma GCC diagnostic pop
     }
 };
 
@@ -1599,11 +1605,13 @@
     /// \internal
     /// \todo: create separate values vs. flags initializer as for flags we want
     /// to list both allowed and required flags
-    template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
+    template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)nullptr))>
     C2FieldSupportedValues(bool flags, const T*)
         : type(flags ? FLAGS : VALUES),
           range{(T)0, (T)0, (T)0, (T)0, (T)0} {
-              C2FieldDescriptor::NamedValuesType named = C2FieldDescriptor::namedValuesFor(*(T*)0);
+              C2FieldDescriptor::NamedValuesType named = C2FieldDescriptor::namedValuesFor(*(T*)nullptr);
         if (flags) {
             values.emplace_back(0); // min-mask defaults to 0
         }
@@ -1612,6 +1620,7 @@
         }
     }
 };
+#pragma GCC diagnostic pop
 
 /**
  * Supported values for a specific field.
diff --git a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
index 1e87f38..d4b973f 100644
--- a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
@@ -330,57 +330,72 @@
     }
 }
 
+// number of elementary streams per component
+#define STREAM_COUNT 2
+
 // LookUpTable of clips and metadata for component testing
 void GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL,
-                        char* info) {
+                        char* info, size_t streamIndex = 0) {
     struct CompToURL {
         Codec2AudioDecHidlTest::standardComp comp;
-        const char* mURL;
-        const char* info;
+        const char mURL[STREAM_COUNT][512];
+        const char info[STREAM_COUNT][512];
     };
+    ASSERT_TRUE(streamIndex < STREAM_COUNT);
+
     static const CompToURL kCompToURL[] = {
         {Codec2AudioDecHidlTest::standardComp::xaac,
-         "bbb_aac_stereo_128kbps_48000hz.aac",
-         "bbb_aac_stereo_128kbps_48000hz.info"},
+         {"bbb_aac_stereo_128kbps_48000hz.aac",
+          "bbb_aac_stereo_128kbps_48000hz.aac"},
+         {"bbb_aac_stereo_128kbps_48000hz.info",
+          "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
         {Codec2AudioDecHidlTest::standardComp::mp3,
-         "bbb_mp3_stereo_192kbps_48000hz.mp3",
-         "bbb_mp3_stereo_192kbps_48000hz.info"},
+         {"bbb_mp3_stereo_192kbps_48000hz.mp3",
+          "bbb_mp3_stereo_192kbps_48000hz.mp3"},
+         {"bbb_mp3_stereo_192kbps_48000hz.info",
+          "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"}},
         {Codec2AudioDecHidlTest::standardComp::aac,
-         "bbb_aac_stereo_128kbps_48000hz.aac",
-         "bbb_aac_stereo_128kbps_48000hz.info"},
+         {"bbb_aac_stereo_128kbps_48000hz.aac",
+          "bbb_aac_stereo_128kbps_48000hz.aac"},
+         {"bbb_aac_stereo_128kbps_48000hz.info",
+          "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
         {Codec2AudioDecHidlTest::standardComp::amrnb,
-         "sine_amrnb_1ch_12kbps_8000hz.amrnb",
-         "sine_amrnb_1ch_12kbps_8000hz.info"},
+         {"sine_amrnb_1ch_12kbps_8000hz.amrnb",
+          "sine_amrnb_1ch_12kbps_8000hz.amrnb"},
+         {"sine_amrnb_1ch_12kbps_8000hz.info",
+          "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"}},
         {Codec2AudioDecHidlTest::standardComp::amrwb,
-         "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
-         "bbb_amrwb_1ch_14kbps_16000hz.info"},
+         {"bbb_amrwb_1ch_14kbps_16000hz.amrwb",
+          "bbb_amrwb_1ch_14kbps_16000hz.amrwb"},
+         {"bbb_amrwb_1ch_14kbps_16000hz.info",
+          "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"}},
         {Codec2AudioDecHidlTest::standardComp::vorbis,
-         "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
-         "bbb_vorbis_stereo_128kbps_48000hz.info"},
+         {"bbb_vorbis_stereo_128kbps_48000hz.vorbis", ""},
+         {"bbb_vorbis_stereo_128kbps_48000hz.info", ""}},
         {Codec2AudioDecHidlTest::standardComp::opus,
-         "bbb_opus_stereo_128kbps_48000hz.opus",
-         "bbb_opus_stereo_128kbps_48000hz.info"},
+         {"bbb_opus_stereo_128kbps_48000hz.opus", ""},
+         {"bbb_opus_stereo_128kbps_48000hz.info", ""}},
         {Codec2AudioDecHidlTest::standardComp::g711alaw,
-        "bbb_g711alaw_1ch_8khz.raw",
-         "bbb_g711alaw_1ch_8khz.info"},
+         {"bbb_g711alaw_1ch_8khz.raw", ""},
+         {"bbb_g711alaw_1ch_8khz.info", ""}},
         {Codec2AudioDecHidlTest::standardComp::g711mlaw,
-        "bbb_g711mulaw_1ch_8khz.raw",
-         "bbb_g711mulaw_1ch_8khz.info"},
+         {"bbb_g711mulaw_1ch_8khz.raw", ""},
+         {"bbb_g711mulaw_1ch_8khz.info", ""}},
         {Codec2AudioDecHidlTest::standardComp::gsm,
-        "bbb_gsm_1ch_8khz_13kbps.raw",
-         "bbb_gsm_1ch_8khz_13kbps.info"},
+         {"bbb_gsm_1ch_8khz_13kbps.raw", ""},
+         {"bbb_gsm_1ch_8khz_13kbps.info", ""}},
         {Codec2AudioDecHidlTest::standardComp::raw,
-        "bbb_raw_1ch_8khz_s32le.raw",
-         "bbb_raw_1ch_8khz_s32le.info"},
+         {"bbb_raw_1ch_8khz_s32le.raw", ""},
+         {"bbb_raw_1ch_8khz_s32le.info", ""}},
         {Codec2AudioDecHidlTest::standardComp::flac,
-         "bbb_flac_stereo_680kbps_48000hz.flac",
-         "bbb_flac_stereo_680kbps_48000hz.info"},
+         {"bbb_flac_stereo_680kbps_48000hz.flac", ""},
+         {"bbb_flac_stereo_680kbps_48000hz.info", ""}},
     };
 
     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
         if (kCompToURL[i].comp == comp) {
-            strcat(mURL, kCompToURL[i].mURL);
-            strcat(info, kCompToURL[i].info);
+            strcat(mURL, kCompToURL[i].mURL[streamIndex]);
+            strcat(info, kCompToURL[i].info[streamIndex]);
             return;
         }
     }
@@ -491,10 +506,15 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-TEST_F(Codec2AudioDecHidlTest, DecodeTest) {
+class Codec2AudioDecDecodeTest : public Codec2AudioDecHidlTest,
+                                 public ::testing::WithParamInterface<int32_t> {
+};
+
+TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
     description("Decodes input file");
     if (mDisableTest) return;
 
+    uint32_t streamIndex = GetParam();
     ASSERT_EQ(mComponent->start(), C2_OK);
     mTimestampDevTest = true;
     char mURL[512], info[512];
@@ -502,7 +522,12 @@
 
     strcpy(mURL, gEnv->getRes().c_str());
     strcpy(info, gEnv->getRes().c_str());
-    GetURLForComponent(mCompName, mURL, info);
+    GetURLForComponent(mCompName, mURL, info, streamIndex);
+    if (!strcmp(mURL, gEnv->getRes().c_str())) {
+        ALOGV("EMPTY INPUT gEnv->getRes().c_str() %s mURL  %s ",
+              gEnv->getRes().c_str(), mURL);
+        return;
+    }
 
     eleInfo.open(info);
     ASSERT_EQ(eleInfo.is_open(), true);
@@ -521,6 +546,9 @@
         Info.push_back({bytesCount, flags, timestamp});
     }
     eleInfo.close();
+    // Reset total no of frames received
+    mFramesReceived = 0;
+    mTimestampUs = 0;
     int32_t bitStreamInfo[2] = {0};
     if (mCompName == raw) {
         bitStreamInfo[0] = 8000;
@@ -577,6 +605,9 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
+INSTANTIATE_TEST_CASE_P(StreamIndexes, Codec2AudioDecDecodeTest,
+                        ::testing::Values(0, 1));
+
 // thumbnail test
 TEST_F(Codec2AudioDecHidlTest, ThumbnailTest) {
     description("Test Request for thumbnail");
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
new file mode 100644
index 0000000..182af20
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
@@ -0,0 +1,443 @@
+5 32 0
+5 32 0
+337 1 0
+322 1 21333
+279 1 42666
+563 1 64000
+635 1 106666
+634 1 149333
+629 1 192000
+680 1 234666
+688 1 277333
+1036 1 320000
+1040 1 384000
+1009 1 448000
+1020 1 512000
+1357 1 576000
+1353 1 661333
+1351 1 746666
+1351 1 832000
+343 1 917333
+335 1 938666
+339 1 960000
+342 1 981333
+348 1 1002666
+350 1 1024000
+351 1 1045333
+342 1 1066666
+366 1 1088000
+340 1 1109333
+354 1 1130666
+340 1 1152000
+334 1 1173333
+338 1 1194666
+340 1 1216000
+351 1 1237333
+346 1 1258666
+331 1 1280000
+321 1 1301333
+343 1 1322666
+342 1 1344000
+345 1 1365333
+326 1 1386666
+342 1 1408000
+356 1 1429333
+351 1 1450666
+343 1 1472000
+347 1 1493333
+349 1 1514666
+350 1 1536000
+330 1 1557333
+341 1 1578666
+340 1 1600000
+330 1 1621333
+340 1 1642666
+335 1 1664000
+344 1 1685333
+359 1 1706666
+337 1 1728000
+346 1 1749333
+330 1 1770666
+351 1 1792000
+355 1 1813333
+352 1 1834666
+325 1 1856000
+342 1 1877333
+327 1 1898666
+349 1 1920000
+326 1 1941333
+337 1 1962666
+378 1 1984000
+321 1 2005333
+319 1 2026666
+346 1 2048000
+352 1 2069333
+349 1 2090666
+331 1 2112000
+330 1 2133333
+329 1 2154666
+333 1 2176000
+367 1 2197333
+362 1 2218666
+337 1 2240000
+337 1 2261333
+360 1 2282666
+333 1 2304000
+317 1 2325333
+344 1 2346666
+335 1 2368000
+337 1 2389333
+349 1 2410666
+336 1 2432000
+348 1 2453333
+349 1 2474666
+342 1 2496000
+359 1 2517333
+340 1 2538666
+340 1 2560000
+348 1 2581333
+334 1 2602666
+328 1 2624000
+341 1 2645333
+339 1 2666666
+337 1 2688000
+350 1 2709333
+326 1 2730666
+360 1 2752000
+344 1 2773333
+340 1 2794666
+343 1 2816000
+361 1 2837333
+329 1 2858666
+345 1 2880000
+345 1 2901333
+330 1 2922666
+342 1 2944000
+344 1 2965333
+330 1 2986666
+329 1 3008000
+335 1 3029333
+366 1 3050666
+328 1 3072000
+349 1 3093333
+339 1 3114666
+340 1 3136000
+335 1 3157333
+327 1 3178666
+348 1 3200000
+339 1 3221333
+334 1 3242666
+350 1 3264000
+325 1 3285333
+361 1 3306666
+338 1 3328000
+350 1 3349333
+353 1 3370666
+327 1 3392000
+346 1 3413333
+348 1 3434666
+339 1 3456000
+342 1 3477333
+334 1 3498666
+350 1 3520000
+354 1 3541333
+363 1 3562666
+322 1 3584000
+337 1 3605333
+355 1 3626666
+329 1 3648000
+324 1 3669333
+338 1 3690666
+356 1 3712000
+330 1 3733333
+321 1 3754666
+337 1 3776000
+345 1 3797333
+335 1 3818666
+348 1 3840000
+342 1 3861333
+348 1 3882666
+335 1 3904000
+344 1 3925333
+357 1 3946666
+368 1 3968000
+324 1 3989333
+343 1 4010666
+341 1 4032000
+329 1 4053333
+356 1 4074666
+317 1 4096000
+351 1 4117333
+340 1 4138666
+340 1 4160000
+332 1 4181333
+355 1 4202666
+357 1 4224000
+327 1 4245333
+338 1 4266666
+323 1 4288000
+346 1 4309333
+352 1 4330666
+347 1 4352000
+343 1 4373333
+311 1 4394666
+338 1 4416000
+365 1 4437333
+349 1 4458666
+327 1 4480000
+355 1 4501333
+319 1 4522666
+349 1 4544000
+351 1 4565333
+337 1 4586666
+340 1 4608000
+349 1 4629333
+316 1 4650666
+344 1 4672000
+334 1 4693333
+344 1 4714666
+347 1 4736000
+348 1 4757333
+334 1 4778666
+338 1 4800000
+331 1 4821333
+344 1 4842666
+342 1 4864000
+336 1 4885333
+326 1 4906666
+364 1 4928000
+350 1 4949333
+350 1 4970666
+363 1 4992000
+358 1 5013333
+305 1 5034666
+344 1 5056000
+346 1 5077333
+342 1 5098666
+330 1 5120000
+318 1 5141333
+361 1 5162666
+354 1 5184000
+313 1 5205333
+330 1 5226666
+350 1 5248000
+347 1 5269333
+346 1 5290666
+357 1 5312000
+325 1 5333333
+335 1 5354666
+331 1 5376000
+366 1 5397333
+329 1 5418666
+349 1 5440000
+371 1 5461333
+326 1 5482666
+333 1 5504000
+319 1 5525333
+327 1 5546666
+353 1 5568000
+356 1 5589333
+348 1 5610666
+338 1 5632000
+331 1 5653333
+341 1 5674666
+362 1 5696000
+326 1 5717333
+359 1 5738666
+315 1 5760000
+376 1 5781333
+343 1 5802666
+354 1 5824000
+353 1 5845333
+344 1 5866666
+334 1 5888000
+345 1 5909333
+355 1 5930666
+322 1 5952000
+334 1 5973333
+353 1 5994666
+338 1 6016000
+351 1 6037333
+334 1 6058666
+339 1 6080000
+345 1 6101333
+347 1 6122666
+355 1 6144000
+312 1 6165333
+352 1 6186666
+354 1 6208000
+318 1 6229333
+344 1 6250666
+363 1 6272000
+321 1 6293333
+339 1 6314666
+356 1 6336000
+334 1 6357333
+354 1 6378666
+325 1 6400000
+321 1 6421333
+341 1 6442666
+337 1 6464000
+351 1 6485333
+343 1 6506666
+341 1 6528000
+344 1 6549333
+341 1 6570666
+364 1 6592000
+319 1 6613333
+348 1 6634666
+332 1 6656000
+333 1 6677333
+343 1 6698666
+348 1 6720000
+347 1 6741333
+350 1 6762666
+342 1 6784000
+341 1 6805333
+326 1 6826666
+351 1 6848000
+329 1 6869333
+323 1 6890666
+350 1 6912000
+361 1 6933333
+326 1 6954666
+345 1 6976000
+345 1 6997333
+311 1 7018666
+349 1 7040000
+358 1 7061333
+352 1 7082666
+347 1 7104000
+364 1 7125333
+328 1 7146666
+318 1 7168000
+351 1 7189333
+340 1 7210666
+341 1 7232000
+355 1 7253333
+336 1 7274666
+352 1 7296000
+341 1 7317333
+334 1 7338666
+348 1 7360000
+342 1 7381333
+335 1 7402666
+342 1 7424000
+359 1 7445333
+349 1 7466666
+329 1 7488000
+356 1 7509333
+292 1 7530666
+316 1 7552000
+318 1 7573333
+320 1 7594666
+342 1 7616000
+285 1 7637333
+326 1 7658666
+352 1 7680000
+392 1 7701333
+364 1 7722666
+384 1 7744000
+334 1 7765333
+317 1 7786666
+326 1 7808000
+373 1 7829333
+354 1 7850666
+329 1 7872000
+347 1 7893333
+353 1 7914666
+338 1 7936000
+317 1 7957333
+354 1 7978666
+345 1 8000000
+350 1 8021333
+351 1 8042666
+332 1 8064000
+358 1 8085333
+315 1 8106666
+336 1 8128000
+358 1 8149333
+343 1 8170666
+319 1 8192000
+370 1 8213333
+344 1 8234666
+361 1 8256000
+343 1 8277333
+337 1 8298666
+354 1 8320000
+332 1 8341333
+348 1 8362666
+328 1 8384000
+345 1 8405333
+340 1 8426666
+346 1 8448000
+341 1 8469333
+344 1 8490666
+342 1 8512000
+341 1 8533333
+345 1 8554666
+337 1 8576000
+335 1 8597333
+335 1 8618666
+340 1 8640000
+345 1 8661333
+341 1 8682666
+342 1 8704000
+338 1 8725333
+343 1 8746666
+336 1 8768000
+338 1 8789333
+353 1 8810666
+339 1 8832000
+329 1 8853333
+349 1 8874666
+323 1 8896000
+351 1 8917333
+359 1 8938666
+357 1 8960000
+341 1 8981333
+333 1 9002666
+335 1 9024000
+328 1 9045333
+347 1 9066666
+343 1 9088000
+369 1 9109333
+331 1 9130666
+344 1 9152000
+330 1 9173333
+346 1 9194666
+337 1 9216000
+341 1 9237333
+338 1 9258666
+329 1 9280000
+360 1 9301333
+336 1 9322666
+341 1 9344000
+341 1 9365333
+345 1 9386666
+351 1 9408000
+349 1 9429333
+336 1 9450666
+326 1 9472000
+349 1 9493333
+343 1 9514666
+357 1 9536000
+342 1 9557333
+325 1 9578666
+346 1 9600000
+326 1 9621333
+402 1 9642666
+331 1 9664000
+339 1 9685333
+371 1 9706666
+314 1 9728000
+310 1 9749333
+364 1 9770666
+338 1 9792000
+339 1 9813333
+337 1 9834666
+355 1 9856000
+351 1 9877333
+332 1 9898666
+316 1 9920000
+474 1 9941333
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
new file mode 100644
index 0000000..c420009
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
@@ -0,0 +1,460 @@
+41 1 0
+41 1 20000
+82 1 40000
+82 1 80000
+82 1 120000
+82 1 160000
+82 1 200000
+82 1 240000
+82 1 280000
+82 1 320000
+82 1 360000
+123 1 400000
+123 1 460000
+123 1 520000
+123 1 580000
+123 1 640000
+164 1 700000
+164 1 780000
+164 1 860000
+164 1 940000
+164 1 1020000
+41 1 1100000
+41 1 1120000
+41 1 1140000
+41 1 1160000
+41 1 1180000
+41 1 1200000
+41 1 1220000
+41 1 1240000
+41 1 1260000
+41 1 1280000
+41 1 1300000
+41 1 1320000
+41 1 1340000
+41 1 1360000
+41 1 1380000
+41 1 1400000
+41 1 1420000
+41 1 1440000
+41 1 1460000
+41 1 1480000
+41 1 1500000
+41 1 1520000
+41 1 1540000
+41 1 1560000
+41 1 1580000
+41 1 1600000
+41 1 1620000
+41 1 1640000
+41 1 1660000
+41 1 1680000
+41 1 1700000
+41 1 1720000
+41 1 1740000
+41 1 1760000
+41 1 1780000
+41 1 1800000
+41 1 1820000
+41 1 1840000
+41 1 1860000
+41 1 1880000
+41 1 1900000
+41 1 1920000
+41 1 1940000
+41 1 1960000
+41 1 1980000
+41 1 2000000
+41 1 2020000
+41 1 2040000
+41 1 2060000
+41 1 2080000
+41 1 2100000
+41 1 2120000
+41 1 2140000
+41 1 2160000
+41 1 2180000
+41 1 2200000
+41 1 2220000
+41 1 2240000
+41 1 2260000
+41 1 2280000
+41 1 2300000
+41 1 2320000
+41 1 2340000
+41 1 2360000
+41 1 2380000
+41 1 2400000
+41 1 2420000
+41 1 2440000
+41 1 2460000
+41 1 2480000
+41 1 2500000
+41 1 2520000
+41 1 2540000
+41 1 2560000
+41 1 2580000
+41 1 2600000
+41 1 2620000
+41 1 2640000
+41 1 2660000
+41 1 2680000
+41 1 2700000
+41 1 2720000
+41 1 2740000
+41 1 2760000
+41 1 2780000
+41 1 2800000
+41 1 2820000
+41 1 2840000
+41 1 2860000
+41 1 2880000
+41 1 2900000
+41 1 2920000
+41 1 2940000
+41 1 2960000
+41 1 2980000
+41 1 3000000
+41 1 3020000
+41 1 3040000
+41 1 3060000
+41 1 3080000
+41 1 3100000
+41 1 3120000
+41 1 3140000
+41 1 3160000
+41 1 3180000
+41 1 3200000
+41 1 3220000
+41 1 3240000
+41 1 3260000
+41 1 3280000
+41 1 3300000
+41 1 3320000
+41 1 3340000
+41 1 3360000
+41 1 3380000
+41 1 3400000
+41 1 3420000
+41 1 3440000
+41 1 3460000
+41 1 3480000
+41 1 3500000
+41 1 3520000
+41 1 3540000
+41 1 3560000
+41 1 3580000
+41 1 3600000
+41 1 3620000
+41 1 3640000
+41 1 3660000
+41 1 3680000
+41 1 3700000
+41 1 3720000
+41 1 3740000
+41 1 3760000
+41 1 3780000
+41 1 3800000
+41 1 3820000
+41 1 3840000
+41 1 3860000
+41 1 3880000
+41 1 3900000
+41 1 3920000
+41 1 3940000
+41 1 3960000
+41 1 3980000
+41 1 4000000
+41 1 4020000
+41 1 4040000
+41 1 4060000
+41 1 4080000
+41 1 4100000
+41 1 4120000
+41 1 4140000
+41 1 4160000
+41 1 4180000
+41 1 4200000
+41 1 4220000
+41 1 4240000
+41 1 4260000
+41 1 4280000
+41 1 4300000
+41 1 4320000
+41 1 4340000
+41 1 4360000
+41 1 4380000
+41 1 4400000
+41 1 4420000
+41 1 4440000
+41 1 4460000
+41 1 4480000
+41 1 4500000
+41 1 4520000
+41 1 4540000
+41 1 4560000
+41 1 4580000
+41 1 4600000
+41 1 4620000
+41 1 4640000
+41 1 4660000
+41 1 4680000
+41 1 4700000
+41 1 4720000
+41 1 4740000
+41 1 4760000
+41 1 4780000
+41 1 4800000
+41 1 4820000
+41 1 4840000
+41 1 4860000
+41 1 4880000
+41 1 4900000
+41 1 4920000
+41 1 4940000
+41 1 4960000
+41 1 4980000
+41 1 5000000
+41 1 5020000
+41 1 5040000
+41 1 5060000
+41 1 5080000
+41 1 5100000
+41 1 5120000
+41 1 5140000
+41 1 5160000
+41 1 5180000
+41 1 5200000
+41 1 5220000
+41 1 5240000
+41 1 5260000
+41 1 5280000
+41 1 5300000
+41 1 5320000
+41 1 5340000
+41 1 5360000
+41 1 5380000
+41 1 5400000
+41 1 5420000
+41 1 5440000
+41 1 5460000
+41 1 5480000
+41 1 5500000
+41 1 5520000
+41 1 5540000
+41 1 5560000
+41 1 5580000
+41 1 5600000
+41 1 5620000
+41 1 5640000
+41 1 5660000
+41 1 5680000
+41 1 5700000
+41 1 5720000
+41 1 5740000
+41 1 5760000
+41 1 5780000
+41 1 5800000
+41 1 5820000
+41 1 5840000
+41 1 5860000
+41 1 5880000
+41 1 5900000
+41 1 5920000
+41 1 5940000
+41 1 5960000
+41 1 5980000
+41 1 6000000
+41 1 6020000
+41 1 6040000
+41 1 6060000
+41 1 6080000
+41 1 6100000
+41 1 6120000
+41 1 6140000
+41 1 6160000
+41 1 6180000
+41 1 6200000
+41 1 6220000
+41 1 6240000
+41 1 6260000
+41 1 6280000
+41 1 6300000
+41 1 6320000
+41 1 6340000
+41 1 6360000
+41 1 6380000
+41 1 6400000
+41 1 6420000
+41 1 6440000
+41 1 6460000
+41 1 6480000
+41 1 6500000
+41 1 6520000
+41 1 6540000
+41 1 6560000
+41 1 6580000
+41 1 6600000
+41 1 6620000
+41 1 6640000
+41 1 6660000
+41 1 6680000
+41 1 6700000
+41 1 6720000
+41 1 6740000
+41 1 6760000
+41 1 6780000
+41 1 6800000
+41 1 6820000
+41 1 6840000
+41 1 6860000
+41 1 6880000
+41 1 6900000
+41 1 6920000
+41 1 6940000
+41 1 6960000
+41 1 6980000
+41 1 7000000
+41 1 7020000
+41 1 7040000
+41 1 7060000
+41 1 7080000
+41 1 7100000
+41 1 7120000
+41 1 7140000
+41 1 7160000
+41 1 7180000
+41 1 7200000
+41 1 7220000
+41 1 7240000
+41 1 7260000
+41 1 7280000
+41 1 7300000
+41 1 7320000
+41 1 7340000
+41 1 7360000
+41 1 7380000
+41 1 7400000
+41 1 7420000
+41 1 7440000
+41 1 7460000
+41 1 7480000
+41 1 7500000
+41 1 7520000
+41 1 7540000
+41 1 7560000
+41 1 7580000
+41 1 7600000
+41 1 7620000
+41 1 7640000
+41 1 7660000
+41 1 7680000
+41 1 7700000
+41 1 7720000
+41 1 7740000
+41 1 7760000
+41 1 7780000
+41 1 7800000
+41 1 7820000
+41 1 7840000
+41 1 7860000
+41 1 7880000
+41 1 7900000
+41 1 7920000
+41 1 7940000
+41 1 7960000
+41 1 7980000
+41 1 8000000
+41 1 8020000
+41 1 8040000
+41 1 8060000
+41 1 8080000
+41 1 8100000
+41 1 8120000
+41 1 8140000
+41 1 8160000
+41 1 8180000
+41 1 8200000
+41 1 8220000
+41 1 8240000
+41 1 8260000
+41 1 8280000
+41 1 8300000
+41 1 8320000
+41 1 8340000
+41 1 8360000
+41 1 8380000
+41 1 8400000
+41 1 8420000
+41 1 8440000
+41 1 8460000
+41 1 8480000
+41 1 8500000
+41 1 8520000
+41 1 8540000
+41 1 8560000
+41 1 8580000
+41 1 8600000
+41 1 8620000
+41 1 8640000
+41 1 8660000
+41 1 8680000
+41 1 8700000
+41 1 8720000
+41 1 8740000
+41 1 8760000
+41 1 8780000
+41 1 8800000
+41 1 8820000
+41 1 8840000
+41 1 8860000
+41 1 8880000
+41 1 8900000
+41 1 8920000
+41 1 8940000
+41 1 8960000
+41 1 8980000
+41 1 9000000
+41 1 9020000
+41 1 9040000
+41 1 9060000
+41 1 9080000
+41 1 9100000
+41 1 9120000
+41 1 9140000
+41 1 9160000
+41 1 9180000
+41 1 9200000
+41 1 9220000
+41 1 9240000
+41 1 9260000
+41 1 9280000
+41 1 9300000
+41 1 9320000
+41 1 9340000
+41 1 9360000
+41 1 9380000
+41 1 9400000
+41 1 9420000
+41 1 9440000
+41 1 9460000
+41 1 9480000
+41 1 9500000
+41 1 9520000
+41 1 9540000
+41 1 9560000
+41 1 9580000
+41 1 9600000
+41 1 9620000
+41 1 9640000
+41 1 9660000
+41 1 9680000
+41 1 9700000
+41 1 9720000
+41 1 9740000
+41 1 9760000
+41 1 9780000
+41 1 9800000
+41 1 9820000
+41 1 9840000
+41 1 9860000
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
new file mode 100644
index 0000000..575c75f
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
@@ -0,0 +1,385 @@
+576 1 0
+576 1 24000
+1152 1 48000
+1152 1 96000
+1152 1 144000
+1152 1 192000
+1728 1 240000
+1728 1 312000
+1728 1 384000
+1728 1 456000
+1728 1 528000
+2304 1 600000
+2304 1 696000
+2304 1 792000
+2304 1 888000
+2304 1 984000
+576 1 1080000
+576 1 1104000
+576 1 1128000
+576 1 1152000
+576 1 1176000
+576 1 1200000
+576 1 1224000
+576 1 1248000
+576 1 1272000
+576 1 1296000
+576 1 1320000
+576 1 1344000
+576 1 1368000
+576 1 1392000
+576 1 1416000
+576 1 1440000
+576 1 1464000
+576 1 1488000
+576 1 1512000
+576 1 1536000
+576 1 1560000
+576 1 1584000
+576 1 1608000
+576 1 1632000
+576 1 1656000
+576 1 1680000
+576 1 1704000
+576 1 1728000
+576 1 1752000
+576 1 1776000
+576 1 1800000
+576 1 1824000
+576 1 1848000
+576 1 1872000
+576 1 1896000
+576 1 1920000
+576 1 1944000
+576 1 1968000
+576 1 1992000
+576 1 2016000
+576 1 2040000
+576 1 2064000
+576 1 2088000
+576 1 2112000
+576 1 2136000
+576 1 2160000
+576 1 2184000
+576 1 2208000
+576 1 2232000
+576 1 2256000
+576 1 2280000
+576 1 2304000
+576 1 2328000
+576 1 2352000
+576 1 2376000
+576 1 2400000
+576 1 2424000
+576 1 2448000
+576 1 2472000
+576 1 2496000
+576 1 2520000
+576 1 2544000
+576 1 2568000
+576 1 2592000
+576 1 2616000
+576 1 2640000
+576 1 2664000
+576 1 2688000
+576 1 2712000
+576 1 2736000
+576 1 2760000
+576 1 2784000
+576 1 2808000
+576 1 2832000
+576 1 2856000
+576 1 2880000
+576 1 2904000
+576 1 2928000
+576 1 2952000
+576 1 2976000
+576 1 3000000
+576 1 3024000
+576 1 3048000
+576 1 3072000
+576 1 3096000
+576 1 3120000
+576 1 3144000
+576 1 3168000
+576 1 3192000
+576 1 3216000
+576 1 3240000
+576 1 3264000
+576 1 3288000
+576 1 3312000
+576 1 3336000
+576 1 3360000
+576 1 3384000
+576 1 3408000
+576 1 3432000
+576 1 3456000
+576 1 3480000
+576 1 3504000
+576 1 3528000
+576 1 3552000
+576 1 3576000
+576 1 3600000
+576 1 3624000
+576 1 3648000
+576 1 3672000
+576 1 3696000
+576 1 3720000
+576 1 3744000
+576 1 3768000
+576 1 3792000
+576 1 3816000
+576 1 3840000
+576 1 3864000
+576 1 3888000
+576 1 3912000
+576 1 3936000
+576 1 3960000
+576 1 3984000
+576 1 4008000
+576 1 4032000
+576 1 4056000
+576 1 4080000
+576 1 4104000
+576 1 4128000
+576 1 4152000
+576 1 4176000
+576 1 4200000
+576 1 4224000
+576 1 4248000
+576 1 4272000
+576 1 4296000
+576 1 4320000
+576 1 4344000
+576 1 4368000
+576 1 4392000
+576 1 4416000
+576 1 4440000
+576 1 4464000
+576 1 4488000
+576 1 4512000
+576 1 4536000
+576 1 4560000
+576 1 4584000
+576 1 4608000
+576 1 4632000
+576 1 4656000
+576 1 4680000
+576 1 4704000
+576 1 4728000
+576 1 4752000
+576 1 4776000
+576 1 4800000
+576 1 4824000
+576 1 4848000
+576 1 4872000
+576 1 4896000
+576 1 4920000
+576 1 4944000
+576 1 4968000
+576 1 4992000
+576 1 5016000
+576 1 5040000
+576 1 5064000
+576 1 5088000
+576 1 5112000
+576 1 5136000
+576 1 5160000
+576 1 5184000
+576 1 5208000
+576 1 5232000
+576 1 5256000
+576 1 5280000
+576 1 5304000
+576 1 5328000
+576 1 5352000
+576 1 5376000
+576 1 5400000
+576 1 5424000
+576 1 5448000
+576 1 5472000
+576 1 5496000
+576 1 5520000
+576 1 5544000
+576 1 5568000
+576 1 5592000
+576 1 5616000
+576 1 5640000
+576 1 5664000
+576 1 5688000
+576 1 5712000
+576 1 5736000
+576 1 5760000
+576 1 5784000
+576 1 5808000
+576 1 5832000
+576 1 5856000
+576 1 5880000
+576 1 5904000
+576 1 5928000
+576 1 5952000
+576 1 5976000
+576 1 6000000
+576 1 6024000
+576 1 6048000
+576 1 6072000
+576 1 6096000
+576 1 6120000
+576 1 6144000
+576 1 6168000
+576 1 6192000
+576 1 6216000
+576 1 6240000
+576 1 6264000
+576 1 6288000
+576 1 6312000
+576 1 6336000
+576 1 6360000
+576 1 6384000
+576 1 6408000
+576 1 6432000
+576 1 6456000
+576 1 6480000
+576 1 6504000
+576 1 6528000
+576 1 6552000
+576 1 6576000
+576 1 6600000
+576 1 6624000
+576 1 6648000
+576 1 6672000
+576 1 6696000
+576 1 6720000
+576 1 6744000
+576 1 6768000
+576 1 6792000
+576 1 6816000
+576 1 6840000
+576 1 6864000
+576 1 6888000
+576 1 6912000
+576 1 6936000
+576 1 6960000
+576 1 6984000
+576 1 7008000
+576 1 7032000
+576 1 7056000
+576 1 7080000
+576 1 7104000
+576 1 7128000
+576 1 7152000
+576 1 7176000
+576 1 7200000
+576 1 7224000
+576 1 7248000
+576 1 7272000
+576 1 7296000
+576 1 7320000
+576 1 7344000
+576 1 7368000
+576 1 7392000
+576 1 7416000
+576 1 7440000
+576 1 7464000
+576 1 7488000
+576 1 7512000
+576 1 7536000
+576 1 7560000
+576 1 7584000
+576 1 7608000
+576 1 7632000
+576 1 7656000
+576 1 7680000
+576 1 7704000
+576 1 7728000
+576 1 7752000
+576 1 7776000
+576 1 7800000
+576 1 7824000
+576 1 7848000
+576 1 7872000
+576 1 7896000
+576 1 7920000
+576 1 7944000
+576 1 7968000
+576 1 7992000
+576 1 8016000
+576 1 8040000
+576 1 8064000
+576 1 8088000
+576 1 8112000
+576 1 8136000
+576 1 8160000
+576 1 8184000
+576 1 8208000
+576 1 8232000
+576 1 8256000
+576 1 8280000
+576 1 8304000
+576 1 8328000
+576 1 8352000
+576 1 8376000
+576 1 8400000
+576 1 8424000
+576 1 8448000
+576 1 8472000
+576 1 8496000
+576 1 8520000
+576 1 8544000
+576 1 8568000
+576 1 8592000
+576 1 8616000
+576 1 8640000
+576 1 8664000
+576 1 8688000
+576 1 8712000
+576 1 8736000
+576 1 8760000
+576 1 8784000
+576 1 8808000
+576 1 8832000
+576 1 8856000
+576 1 8880000
+576 1 8904000
+576 1 8928000
+576 1 8952000
+576 1 8976000
+576 1 9000000
+576 1 9024000
+576 1 9048000
+576 1 9072000
+576 1 9096000
+576 1 9120000
+576 1 9144000
+576 1 9168000
+576 1 9192000
+576 1 9216000
+576 1 9240000
+576 1 9264000
+576 1 9288000
+576 1 9312000
+576 1 9336000
+576 1 9360000
+576 1 9384000
+576 1 9408000
+576 1 9432000
+576 1 9456000
+576 1 9480000
+576 1 9504000
+576 1 9528000
+576 1 9552000
+576 1 9576000
+576 1 9600000
+576 1 9624000
+576 1 9648000
+576 1 9672000
+576 1 9696000
+576 1 9720000
+576 1 9744000
+576 1 9768000
+576 1 9792000
+576 1 9816000
+576 1 9840000
+576 1 9864000
+576 1 9888000
+576 1 9912000
diff --git a/media/codec2/hidl/1.0/vts/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
new file mode 100644
index 0000000..0176eaf4
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
@@ -0,0 +1,807 @@
+32 1 0
+32 1 20000
+64 1 40000
+64 1 80000
+64 1 120000
+96 1 160000
+96 1 220000
+96 1 280000
+96 1 340000
+128 1 400000
+128 1 480000
+128 1 560000
+128 1 640000
+128 1 720000
+32 1 800000
+32 1 820000
+32 1 840000
+32 1 860000
+32 1 880000
+32 1 900000
+32 1 920000
+32 1 940000
+32 1 960000
+32 1 980000
+32 1 1000000
+32 1 1020000
+32 1 1040000
+32 1 1060000
+32 1 1080000
+32 1 1100000
+32 1 1120000
+32 1 1140000
+32 1 1160000
+32 1 1180000
+32 1 1200000
+32 1 1220000
+32 1 1240000
+32 1 1260000
+32 1 1280000
+32 1 1300000
+32 1 1320000
+32 1 1340000
+32 1 1360000
+32 1 1380000
+32 1 1400000
+32 1 1420000
+32 1 1440000
+32 1 1460000
+32 1 1480000
+32 1 1500000
+32 1 1520000
+32 1 1540000
+32 1 1560000
+32 1 1580000
+32 1 1600000
+32 1 1620000
+32 1 1640000
+32 1 1660000
+32 1 1680000
+32 1 1700000
+32 1 1720000
+32 1 1740000
+32 1 1760000
+32 1 1780000
+32 1 1800000
+32 1 1820000
+32 1 1840000
+32 1 1860000
+32 1 1880000
+32 1 1900000
+32 1 1920000
+32 1 1940000
+32 1 1960000
+32 1 1980000
+32 1 2000000
+32 1 2020000
+32 1 2040000
+32 1 2060000
+32 1 2080000
+32 1 2100000
+32 1 2120000
+32 1 2140000
+32 1 2160000
+32 1 2180000
+32 1 2200000
+32 1 2220000
+32 1 2240000
+32 1 2260000
+32 1 2280000
+32 1 2300000
+32 1 2320000
+32 1 2340000
+32 1 2360000
+32 1 2380000
+32 1 2400000
+32 1 2420000
+32 1 2440000
+32 1 2460000
+32 1 2480000
+32 1 2500000
+32 1 2520000
+32 1 2540000
+32 1 2560000
+32 1 2580000
+32 1 2600000
+32 1 2620000
+32 1 2640000
+32 1 2660000
+32 1 2680000
+32 1 2700000
+32 1 2720000
+32 1 2740000
+32 1 2760000
+32 1 2780000
+32 1 2800000
+32 1 2820000
+32 1 2840000
+32 1 2860000
+32 1 2880000
+32 1 2900000
+32 1 2920000
+32 1 2940000
+32 1 2960000
+32 1 2980000
+32 1 3000000
+32 1 3020000
+32 1 3040000
+32 1 3060000
+32 1 3080000
+32 1 3100000
+32 1 3120000
+32 1 3140000
+32 1 3160000
+32 1 3180000
+32 1 3200000
+32 1 3220000
+32 1 3240000
+32 1 3260000
+32 1 3280000
+32 1 3300000
+32 1 3320000
+32 1 3340000
+32 1 3360000
+32 1 3380000
+32 1 3400000
+32 1 3420000
+32 1 3440000
+32 1 3460000
+32 1 3480000
+32 1 3500000
+32 1 3520000
+32 1 3540000
+32 1 3560000
+32 1 3580000
+32 1 3600000
+32 1 3620000
+32 1 3640000
+32 1 3660000
+32 1 3680000
+32 1 3700000
+32 1 3720000
+32 1 3740000
+32 1 3760000
+32 1 3780000
+32 1 3800000
+32 1 3820000
+32 1 3840000
+32 1 3860000
+32 1 3880000
+32 1 3900000
+32 1 3920000
+32 1 3940000
+32 1 3960000
+32 1 3980000
+32 1 4000000
+32 1 4020000
+32 1 4040000
+32 1 4060000
+32 1 4080000
+32 1 4100000
+32 1 4120000
+32 1 4140000
+32 1 4160000
+32 1 4180000
+32 1 4200000
+32 1 4220000
+32 1 4240000
+32 1 4260000
+32 1 4280000
+32 1 4300000
+32 1 4320000
+32 1 4340000
+32 1 4360000
+32 1 4380000
+32 1 4400000
+32 1 4420000
+32 1 4440000
+32 1 4460000
+32 1 4480000
+32 1 4500000
+32 1 4520000
+32 1 4540000
+32 1 4560000
+32 1 4580000
+32 1 4600000
+32 1 4620000
+32 1 4640000
+32 1 4660000
+32 1 4680000
+32 1 4700000
+32 1 4720000
+32 1 4740000
+32 1 4760000
+32 1 4780000
+32 1 4800000
+32 1 4820000
+32 1 4840000
+32 1 4860000
+32 1 4880000
+32 1 4900000
+32 1 4920000
+32 1 4940000
+32 1 4960000
+32 1 4980000
+32 1 5000000
+32 1 5020000
+32 1 5040000
+32 1 5060000
+32 1 5080000
+32 1 5100000
+32 1 5120000
+32 1 5140000
+32 1 5160000
+32 1 5180000
+32 1 5200000
+32 1 5220000
+32 1 5240000
+32 1 5260000
+32 1 5280000
+32 1 5300000
+32 1 5320000
+32 1 5340000
+32 1 5360000
+32 1 5380000
+32 1 5400000
+32 1 5420000
+32 1 5440000
+32 1 5460000
+32 1 5480000
+32 1 5500000
+32 1 5520000
+32 1 5540000
+32 1 5560000
+32 1 5580000
+32 1 5600000
+32 1 5620000
+32 1 5640000
+32 1 5660000
+32 1 5680000
+32 1 5700000
+32 1 5720000
+32 1 5740000
+32 1 5760000
+32 1 5780000
+32 1 5800000
+32 1 5820000
+32 1 5840000
+32 1 5860000
+32 1 5880000
+32 1 5900000
+32 1 5920000
+32 1 5940000
+32 1 5960000
+32 1 5980000
+32 1 6000000
+32 1 6020000
+32 1 6040000
+32 1 6060000
+32 1 6080000
+32 1 6100000
+32 1 6120000
+32 1 6140000
+32 1 6160000
+32 1 6180000
+32 1 6200000
+32 1 6220000
+32 1 6240000
+32 1 6260000
+32 1 6280000
+32 1 6300000
+32 1 6320000
+32 1 6340000
+32 1 6360000
+32 1 6380000
+32 1 6400000
+32 1 6420000
+32 1 6440000
+32 1 6460000
+32 1 6480000
+32 1 6500000
+32 1 6520000
+32 1 6540000
+32 1 6560000
+32 1 6580000
+32 1 6600000
+32 1 6620000
+32 1 6640000
+32 1 6660000
+32 1 6680000
+32 1 6700000
+32 1 6720000
+32 1 6740000
+32 1 6760000
+32 1 6780000
+32 1 6800000
+32 1 6820000
+32 1 6840000
+32 1 6860000
+32 1 6880000
+32 1 6900000
+32 1 6920000
+32 1 6940000
+32 1 6960000
+32 1 6980000
+32 1 7000000
+32 1 7020000
+32 1 7040000
+32 1 7060000
+32 1 7080000
+32 1 7100000
+32 1 7120000
+32 1 7140000
+32 1 7160000
+32 1 7180000
+32 1 7200000
+32 1 7220000
+32 1 7240000
+32 1 7260000
+32 1 7280000
+32 1 7300000
+32 1 7320000
+32 1 7340000
+32 1 7360000
+32 1 7380000
+32 1 7400000
+32 1 7420000
+32 1 7440000
+32 1 7460000
+32 1 7480000
+32 1 7500000
+32 1 7520000
+32 1 7540000
+32 1 7560000
+32 1 7580000
+32 1 7600000
+32 1 7620000
+32 1 7640000
+32 1 7660000
+32 1 7680000
+32 1 7700000
+32 1 7720000
+32 1 7740000
+32 1 7760000
+32 1 7780000
+32 1 7800000
+32 1 7820000
+32 1 7840000
+32 1 7860000
+32 1 7880000
+32 1 7900000
+32 1 7920000
+32 1 7940000
+32 1 7960000
+32 1 7980000
+32 1 8000000
+32 1 8020000
+32 1 8040000
+32 1 8060000
+32 1 8080000
+32 1 8100000
+32 1 8120000
+32 1 8140000
+32 1 8160000
+32 1 8180000
+32 1 8200000
+32 1 8220000
+32 1 8240000
+32 1 8260000
+32 1 8280000
+32 1 8300000
+32 1 8320000
+32 1 8340000
+32 1 8360000
+32 1 8380000
+32 1 8400000
+32 1 8420000
+32 1 8440000
+32 1 8460000
+32 1 8480000
+32 1 8500000
+32 1 8520000
+32 1 8540000
+32 1 8560000
+32 1 8580000
+32 1 8600000
+32 1 8620000
+32 1 8640000
+32 1 8660000
+32 1 8680000
+32 1 8700000
+32 1 8720000
+32 1 8740000
+32 1 8760000
+32 1 8780000
+32 1 8800000
+32 1 8820000
+32 1 8840000
+32 1 8860000
+32 1 8880000
+32 1 8900000
+32 1 8920000
+32 1 8940000
+32 1 8960000
+32 1 8980000
+32 1 9000000
+32 1 9020000
+32 1 9040000
+32 1 9060000
+32 1 9080000
+32 1 9100000
+32 1 9120000
+32 1 9140000
+32 1 9160000
+32 1 9180000
+32 1 9200000
+32 1 9220000
+32 1 9240000
+32 1 9260000
+32 1 9280000
+32 1 9300000
+32 1 9320000
+32 1 9340000
+32 1 9360000
+32 1 9380000
+32 1 9400000
+32 1 9420000
+32 1 9440000
+32 1 9460000
+32 1 9480000
+32 1 9500000
+32 1 9520000
+32 1 9540000
+32 1 9560000
+32 1 9580000
+32 1 9600000
+32 1 9620000
+32 1 9640000
+32 1 9660000
+32 1 9680000
+32 1 9700000
+32 1 9720000
+32 1 9740000
+32 1 9760000
+32 1 9780000
+32 1 9800000
+32 1 9820000
+32 1 9840000
+32 1 9860000
+32 1 9880000
+32 1 9900000
+32 1 9920000
+32 1 9940000
+32 1 9960000
+32 1 9980000
+32 1 10000000
+32 1 10020000
+32 1 10040000
+32 1 10060000
+32 1 10080000
+32 1 10100000
+32 1 10120000
+32 1 10140000
+32 1 10160000
+32 1 10180000
+32 1 10200000
+32 1 10220000
+32 1 10240000
+32 1 10260000
+32 1 10280000
+32 1 10300000
+32 1 10320000
+32 1 10340000
+32 1 10360000
+32 1 10380000
+32 1 10400000
+32 1 10420000
+32 1 10440000
+32 1 10460000
+32 1 10480000
+32 1 10500000
+32 1 10520000
+32 1 10540000
+32 1 10560000
+32 1 10580000
+32 1 10600000
+32 1 10620000
+32 1 10640000
+32 1 10660000
+32 1 10680000
+32 1 10700000
+32 1 10720000
+32 1 10740000
+32 1 10760000
+32 1 10780000
+32 1 10800000
+32 1 10820000
+32 1 10840000
+32 1 10860000
+32 1 10880000
+32 1 10900000
+32 1 10920000
+32 1 10940000
+32 1 10960000
+32 1 10980000
+32 1 11000000
+32 1 11020000
+32 1 11040000
+32 1 11060000
+32 1 11080000
+32 1 11100000
+32 1 11120000
+32 1 11140000
+32 1 11160000
+32 1 11180000
+32 1 11200000
+32 1 11220000
+32 1 11240000
+32 1 11260000
+32 1 11280000
+32 1 11300000
+32 1 11320000
+32 1 11340000
+32 1 11360000
+32 1 11380000
+32 1 11400000
+32 1 11420000
+32 1 11440000
+32 1 11460000
+32 1 11480000
+32 1 11500000
+32 1 11520000
+32 1 11540000
+32 1 11560000
+32 1 11580000
+32 1 11600000
+32 1 11620000
+32 1 11640000
+32 1 11660000
+32 1 11680000
+32 1 11700000
+32 1 11720000
+32 1 11740000
+32 1 11760000
+32 1 11780000
+32 1 11800000
+32 1 11820000
+32 1 11840000
+32 1 11860000
+32 1 11880000
+32 1 11900000
+32 1 11920000
+32 1 11940000
+32 1 11960000
+32 1 11980000
+32 1 12000000
+32 1 12020000
+32 1 12040000
+32 1 12060000
+32 1 12080000
+32 1 12100000
+32 1 12120000
+32 1 12140000
+32 1 12160000
+32 1 12180000
+32 1 12200000
+32 1 12220000
+32 1 12240000
+32 1 12260000
+32 1 12280000
+32 1 12300000
+32 1 12320000
+32 1 12340000
+32 1 12360000
+32 1 12380000
+32 1 12400000
+32 1 12420000
+32 1 12440000
+32 1 12460000
+32 1 12480000
+32 1 12500000
+32 1 12520000
+32 1 12540000
+32 1 12560000
+32 1 12580000
+32 1 12600000
+32 1 12620000
+32 1 12640000
+32 1 12660000
+32 1 12680000
+32 1 12700000
+32 1 12720000
+32 1 12740000
+32 1 12760000
+32 1 12780000
+32 1 12800000
+32 1 12820000
+32 1 12840000
+32 1 12860000
+32 1 12880000
+32 1 12900000
+32 1 12920000
+32 1 12940000
+32 1 12960000
+32 1 12980000
+32 1 13000000
+32 1 13020000
+32 1 13040000
+32 1 13060000
+32 1 13080000
+32 1 13100000
+32 1 13120000
+32 1 13140000
+32 1 13160000
+32 1 13180000
+32 1 13200000
+32 1 13220000
+32 1 13240000
+32 1 13260000
+32 1 13280000
+32 1 13300000
+32 1 13320000
+32 1 13340000
+32 1 13360000
+32 1 13380000
+32 1 13400000
+32 1 13420000
+32 1 13440000
+32 1 13460000
+32 1 13480000
+32 1 13500000
+32 1 13520000
+32 1 13540000
+32 1 13560000
+32 1 13580000
+32 1 13600000
+32 1 13620000
+32 1 13640000
+32 1 13660000
+32 1 13680000
+32 1 13700000
+32 1 13720000
+32 1 13740000
+32 1 13760000
+32 1 13780000
+32 1 13800000
+32 1 13820000
+32 1 13840000
+32 1 13860000
+32 1 13880000
+32 1 13900000
+32 1 13920000
+32 1 13940000
+32 1 13960000
+32 1 13980000
+32 1 14000000
+32 1 14020000
+32 1 14040000
+32 1 14060000
+32 1 14080000
+32 1 14100000
+32 1 14120000
+32 1 14140000
+32 1 14160000
+32 1 14180000
+32 1 14200000
+32 1 14220000
+32 1 14240000
+32 1 14260000
+32 1 14280000
+32 1 14300000
+32 1 14320000
+32 1 14340000
+32 1 14360000
+32 1 14380000
+32 1 14400000
+32 1 14420000
+32 1 14440000
+32 1 14460000
+32 1 14480000
+32 1 14500000
+32 1 14520000
+32 1 14540000
+32 1 14560000
+32 1 14580000
+32 1 14600000
+32 1 14620000
+32 1 14640000
+32 1 14660000
+32 1 14680000
+32 1 14700000
+32 1 14720000
+32 1 14740000
+32 1 14760000
+32 1 14780000
+32 1 14800000
+32 1 14820000
+32 1 14840000
+32 1 14860000
+32 1 14880000
+32 1 14900000
+32 1 14920000
+32 1 14940000
+32 1 14960000
+32 1 14980000
+32 1 15000000
+32 1 15020000
+32 1 15040000
+32 1 15060000
+32 1 15080000
+32 1 15100000
+32 1 15120000
+32 1 15140000
+32 1 15160000
+32 1 15180000
+32 1 15200000
+32 1 15220000
+32 1 15240000
+32 1 15260000
+32 1 15280000
+32 1 15300000
+32 1 15320000
+32 1 15340000
+32 1 15360000
+32 1 15380000
+32 1 15400000
+32 1 15420000
+32 1 15440000
+32 1 15460000
+32 1 15480000
+32 1 15500000
+32 1 15520000
+32 1 15540000
+32 1 15560000
+32 1 15580000
+32 1 15600000
+32 1 15620000
+32 1 15640000
+32 1 15660000
+32 1 15680000
+32 1 15700000
+32 1 15720000
+32 1 15740000
+32 1 15760000
+32 1 15780000
+32 1 15800000
+32 1 15820000
+32 1 15840000
+32 1 15860000
+32 1 15880000
+32 1 15900000
+32 1 15920000
+32 1 15940000
+32 1 15960000
+32 1 15980000
+32 1 16000000
+32 1 16020000
+32 1 16040000
+32 1 16060000
+32 1 16080000
+32 1 16100000
+32 1 16120000
+32 1 16140000
+32 1 16160000
+32 1 16180000
+32 1 16200000
+32 1 16220000
+32 1 16240000
+32 1 16260000
+32 1 16280000
+32 1 16300000
+32 1 16320000
+32 1 16340000
+32 1 16360000
+32 1 16380000
+32 1 16400000
+32 1 16420000
+32 1 16440000
+32 1 16460000
+32 1 16480000
+32 1 16500000
+32 1 16520000
+32 1 16540000
+32 1 16560000
+32 1 16580000
+32 1 16600000
+32 1 16620000
+32 1 16640000
diff --git a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
index 9a42d72..8cbb7a7 100644
--- a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
@@ -421,17 +421,21 @@
     ASSERT_EQ(mDisableTest, false);
 }
 
+class Codec2VideoDecDecodeTest : public Codec2VideoDecHidlTest,
+                                 public ::testing::WithParamInterface<int32_t> {
+};
+
 // Bitstream Test
-TEST_F(Codec2VideoDecHidlTest, DecodeTest) {
+TEST_P(Codec2VideoDecDecodeTest, DecodeTest) {
     description("Decodes input file");
     if (mDisableTest) return;
 
+    uint32_t streamIndex = GetParam();
     char mURL[512], info[512];
     std::ifstream eleStream, eleInfo;
-
     strcpy(mURL, gEnv->getRes().c_str());
     strcpy(info, gEnv->getRes().c_str());
-    GetURLForComponent(mCompName, mURL, info);
+    GetURLForComponent(mCompName, mURL, info, streamIndex);
 
     eleInfo.open(info);
     ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
@@ -452,6 +456,9 @@
     eleInfo.close();
 
     ASSERT_EQ(mComponent->start(), C2_OK);
+    // Reset total no of frames received
+    mFramesReceived = 0;
+    mTimestampUs = 0;
     ALOGV("mURL : %s", mURL);
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
@@ -476,8 +483,11 @@
     }
 
     if (mTimestampDevTest) EXPECT_EQ(mTimestampUslist.empty(), true);
+    ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
+INSTANTIATE_TEST_CASE_P(StreamIndexes, Codec2VideoDecDecodeTest,
+                        ::testing::Values(0, 1));
 
 // Adaptive Test
 TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index f36027e..5d0ccd2 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -517,6 +517,13 @@
                         caps->addProfileLevel(VP9Profile2,    VP9Level5);
                         caps->addProfileLevel(VP9Profile2HDR, VP9Level5);
                     }
+                } else if (mediaType == MIMETYPE_VIDEO_AV1 && !encoder) {
+                    caps->addProfileLevel(AV1Profile0,      AV1Level2);
+                    caps->addProfileLevel(AV1Profile0,      AV1Level21);
+                    caps->addProfileLevel(AV1Profile1,      AV1Level22);
+                    caps->addProfileLevel(AV1Profile1,      AV1Level3);
+                    caps->addProfileLevel(AV1Profile2,      AV1Level31);
+                    caps->addProfileLevel(AV1Profile2,      AV1Level32);
                 } else if (mediaType == MIMETYPE_VIDEO_HEVC && !encoder) {
                     caps->addProfileLevel(HEVCProfileMain,      HEVCMainTierLevel51);
                     caps->addProfileLevel(HEVCProfileMainStill, HEVCMainTierLevel51);
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index 97e17e8..b1b33e1 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -326,6 +326,41 @@
     { C2Config::PROFILE_VP9_3, VP9Profile3 },
 };
 
+ALookup<C2Config::level_t, int32_t> sAv1Levels = {
+    { C2Config::LEVEL_AV1_2,    AV1Level2  },
+    { C2Config::LEVEL_AV1_2_1,  AV1Level21 },
+    { C2Config::LEVEL_AV1_2_2,  AV1Level22 },
+    { C2Config::LEVEL_AV1_2_3,  AV1Level23 },
+    { C2Config::LEVEL_AV1_3,    AV1Level3  },
+    { C2Config::LEVEL_AV1_3_1,  AV1Level31 },
+    { C2Config::LEVEL_AV1_3_2,  AV1Level32 },
+    { C2Config::LEVEL_AV1_3_3,  AV1Level33 },
+    { C2Config::LEVEL_AV1_4,    AV1Level4  },
+    { C2Config::LEVEL_AV1_4_1,  AV1Level41 },
+    { C2Config::LEVEL_AV1_4_2,  AV1Level42 },
+    { C2Config::LEVEL_AV1_4_3,  AV1Level43 },
+    { C2Config::LEVEL_AV1_5,    AV1Level5  },
+    { C2Config::LEVEL_AV1_5_1,  AV1Level51 },
+    { C2Config::LEVEL_AV1_5_2,  AV1Level52 },
+    { C2Config::LEVEL_AV1_5_3,  AV1Level53 },
+    { C2Config::LEVEL_AV1_6,    AV1Level6  },
+    { C2Config::LEVEL_AV1_6_1,  AV1Level61 },
+    { C2Config::LEVEL_AV1_6_2,  AV1Level62 },
+    { C2Config::LEVEL_AV1_6_3,  AV1Level63 },
+    { C2Config::LEVEL_AV1_7,    AV1Level7  },
+    { C2Config::LEVEL_AV1_7_1,  AV1Level71 },
+    { C2Config::LEVEL_AV1_7_2,  AV1Level72 },
+    { C2Config::LEVEL_AV1_7_3,  AV1Level73 },
+};
+
+
+ALookup<C2Config::profile_t, int32_t> sAv1Profiles = {
+    { C2Config::PROFILE_AV1_0, AV1Profile0 },
+    { C2Config::PROFILE_AV1_1, AV1Profile1 },
+    { C2Config::PROFILE_AV1_2, AV1Profile2 },
+};
+
+
 /**
  * A helper that passes through vendor extension profile and level values.
  */
diff --git a/media/codec2/vndk/C2Config.cpp b/media/codec2/vndk/C2Config.cpp
index da12903..782bec5 100644
--- a/media/codec2/vndk/C2Config.cpp
+++ b/media/codec2/vndk/C2Config.cpp
@@ -139,6 +139,9 @@
         { "vp9-1", C2Config::PROFILE_VP9_1 },
         { "vp9-2", C2Config::PROFILE_VP9_2 },
         { "vp9-3", C2Config::PROFILE_VP9_3 },
+        { "av1-0", C2Config::PROFILE_AV1_0 },
+        { "av1-1", C2Config::PROFILE_AV1_1 },
+        { "av1-2", C2Config::PROFILE_AV1_2 },
 }))
 
 DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(C2Config::level_t, ({
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 2d4e19e..a5dd203 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -821,6 +821,7 @@
     emplace("c2.android.vp9.decoder", "libcodec2_soft_vp9dec.so");
     emplace("c2.android.vp8.encoder", "libcodec2_soft_vp8enc.so");
     emplace("c2.android.vp9.encoder", "libcodec2_soft_vp9enc.so");
+    emplace("c2.android.av1.decoder", "libcodec2_soft_av1dec.so");
     emplace("c2.android.raw.decoder", "libcodec2_soft_rawdec.so");
     emplace("c2.android.flac.decoder", "libcodec2_soft_flacdec.so");
     emplace("c2.android.flac.encoder", "libcodec2_soft_flacenc.so");
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 4e9ac6e..beddad0 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -377,6 +377,10 @@
     return NULL;
 }
 
+static const char *extensions[] = {
+    "aac",
+    NULL
+};
 
 extern "C" {
 // This is the only symbol that needs to be exported
@@ -387,7 +391,7 @@
         UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
         1, // version
         "AAC Extractor",
-        { .v2 = Sniff }
+        { .v3 = {Sniff, extensions} },
     };
 }
 
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 00d2a92..ffeff42 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -199,7 +199,7 @@
 
     if (mInitCheck == OK) {
         AMediaFormat_setString(meta,
-                AMEDIAFORMAT_KEY_MIME, mIsWide ? "audio/amr-wb" : "audio/amr");
+                AMEDIAFORMAT_KEY_MIME, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB : "audio/amr");
     }
 
     return AMEDIA_OK;
@@ -280,8 +280,8 @@
     ReadOptions::SeekMode mode;
     if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) {
         size_t size;
-        int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
-        mCurrentTimeUs = seekFrame * 20000ll;
+        int64_t seekFrame = seekTimeUs / 20000LL;  // 20ms per frame.
+        mCurrentTimeUs = seekFrame * 20000LL;
 
         size_t index = seekFrame < 0 ? 0 : seekFrame / 50;
         if (index >= mOffsetTableLength) {
@@ -358,6 +358,12 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+static const char *extensions[] = {
+    "amr",
+    "awb",
+    NULL
+};
+
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
@@ -368,21 +374,24 @@
         1,
         "AMR Extractor",
         {
-           .v2 = [](
-                    CDataSource *source,
-                    float *confidence,
-                    void **,
-                    FreeMetaFunc *) -> CreatorFunc {
-                DataSourceHelper helper(source);
-                if (SniffAMR(&helper, nullptr, confidence)) {
-                    return [](
-                            CDataSource *source,
-                            void *) -> CMediaExtractor* {
-                        return wrap(new AMRExtractor(new DataSourceHelper(source)));};
-                }
-                return NULL;
-            }
-        }
+           .v3 = {
+               [](
+                   CDataSource *source,
+                   float *confidence,
+                   void **,
+                   FreeMetaFunc *) -> CreatorFunc {
+                   DataSourceHelper helper(source);
+                   if (SniffAMR(&helper, nullptr, confidence)) {
+                       return [](
+                               CDataSource *source,
+                               void *) -> CMediaExtractor* {
+                           return wrap(new AMRExtractor(new DataSourceHelper(source)));};
+                   }
+                   return NULL;
+               },
+               extensions
+           },
+        },
     };
 }
 
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index b5eaf9b..e4bbc07 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -822,6 +822,11 @@
     return true;
 }
 
+static const char *extensions[] = {
+    "flac",
+    "fl",
+    NULL
+};
 
 extern "C" {
 // This is the only symbol that needs to be exported
@@ -833,21 +838,24 @@
             1,
             "FLAC Extractor",
             {
-                .v2 = [](
+                .v3 = {
+                    [](
                         CDataSource *source,
                         float *confidence,
                         void **,
                         FreeMetaFunc *) -> CreatorFunc {
-                    DataSourceHelper helper(source);
-                    if (SniffFLAC(&helper, confidence)) {
-                        return [](
-                                CDataSource *source,
-                                void *) -> CMediaExtractor* {
-                            return wrap(new FLACExtractor(new DataSourceHelper(source)));};
-                    }
-                    return NULL;
+                        DataSourceHelper helper(source);
+                        if (SniffFLAC(&helper, confidence)) {
+                            return [](
+                                    CDataSource *source,
+                                    void *) -> CMediaExtractor* {
+                                return wrap(new FLACExtractor(new DataSourceHelper(source)));};
+                        }
+                        return NULL;
+                    },
+                    extensions
                 }
-            }
+            },
      };
 }
 
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index 0c74376..9f4f9e6 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -326,6 +326,18 @@
 
 }
 
+static const char *extensions[] = {
+    "imy",
+    "mid",
+    "midi",
+    "mxmf",
+    "ota",
+    "rtttl",
+    "rtx",
+    "smf",
+    "xmf",
+    NULL
+};
 
 extern "C" {
 // This is the only symbol that needs to be exported
@@ -337,20 +349,23 @@
         1,
         "MIDI Extractor",
         {
-            .v2 = [](
+            .v3 = {
+                [](
                 CDataSource *source,
                 float *confidence,
                 void **,
                 FreeMetaFunc *) -> CreatorFunc {
-                if (SniffMidi(source, confidence)) {
-                    return [](
-                            CDataSource *source,
-                            void *) -> CMediaExtractor* {
-                        return wrap(new MidiExtractor(source));};
-                }
-                return NULL;
+                    if (SniffMidi(source, confidence)) {
+                        return [](
+                                CDataSource *source,
+                                void *) -> CMediaExtractor* {
+                            return wrap(new MidiExtractor(source));};
+                    }
+                    return NULL;
+                },
+                extensions
             }
-        }
+        },
     };
 }
 
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 42a9c42..4200a46 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -1463,6 +1463,8 @@
                       AMediaFormat_setBuffer(meta,
                              AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
                     }
+                } else if (!strcmp("V_AV1", codecID)) {
+                    AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
                 } else {
                     ALOGW("%s is not supported.", codecID);
                     continue;
@@ -1667,6 +1669,12 @@
     return true;
 }
 
+static const char *extensions[] = {
+    "mka",
+    "mkv",
+    "webm",
+    NULL
+};
 
 extern "C" {
 // This is the only symbol that needs to be exported
@@ -1678,19 +1686,22 @@
         1,
         "Matroska Extractor",
         {
-            .v2 = [](
+            .v3 = {
+                [](
                     CDataSource *source,
                     float *confidence,
                     void **,
                     FreeMetaFunc *) -> CreatorFunc {
-                DataSourceHelper helper(source);
-                if (SniffMatroska(&helper, confidence)) {
-                    return [](
-                            CDataSource *source,
-                            void *) -> CMediaExtractor* {
-                        return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
-                }
-                return NULL;
+                    DataSourceHelper helper(source);
+                    if (SniffMatroska(&helper, confidence)) {
+                        return [](
+                                CDataSource *source,
+                                void *) -> CMediaExtractor* {
+                            return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
+                    }
+                    return NULL;
+                },
+                extensions
             }
         }
     };
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 20bcda8..61838f6 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -609,7 +609,7 @@
     if (mInitCheck != OK) {
         return AMEDIA_ERROR_UNKNOWN;
     }
-    AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, "audio/mpeg");
+    AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
 
     DataSourceHelper helper(mDataSource);
     ID3 id3(&helper);
@@ -707,6 +707,14 @@
     return CreateExtractor;
 }
 
+static const char *extensions[] = {
+    "mp3",
+    "mpeg",
+    "mpg",
+    "mpga",
+    NULL
+};
+
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
@@ -716,7 +724,7 @@
         UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
         1, // version
         "MP3 Extractor",
-        { .v2 = Sniff }
+        { .v3 = {Sniff, extensions} }
     };
 }
 
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/extractors/mp3/VBRISeeker.cpp
index 9eb72a7..ca51b88 100644
--- a/media/extractors/mp3/VBRISeeker.cpp
+++ b/media/extractors/mp3/VBRISeeker.cpp
@@ -71,7 +71,7 @@
     size_t numFrames = U32_AT(&vbriHeader[14]);
 
     int64_t durationUs =
-        numFrames * 1000000ll * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;
+        numFrames * 1000000LL * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;
 
     ALOGV("duration = %.2f secs", durationUs / 1E6);
 
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 2909a50..0441359 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -80,7 +80,8 @@
                 Vector<SidxEntry> &sidx,
                 const Trex *trex,
                 off64_t firstMoofOffset,
-                const sp<ItemTable> &itemTable);
+                const sp<ItemTable> &itemTable,
+                int32_t elstShiftStartTicks);
     virtual status_t init();
 
     virtual media_status_t start();
@@ -109,7 +110,7 @@
     off64_t mFirstMoofOffset;
     off64_t mCurrentMoofOffset;
     off64_t mNextMoofOffset;
-    uint32_t mCurrentTime;
+    uint32_t mCurrentTime; // in media timescale ticks
     int32_t mLastParsedTrackId;
     int32_t mTrackId;
 
@@ -143,6 +144,10 @@
     bool mIsHeif;
     sp<ItemTable> mItemTable;
 
+    // Start offset from composition time to presentation time.
+    // Support shift only for video tracks through mElstShiftStartTicks for now.
+    int32_t mElstShiftStartTicks;
+
     size_t parseNALSize(const uint8_t *data) const;
     status_t parseChunk(off64_t *offset);
     status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
@@ -338,6 +343,8 @@
         case FOURCC('a', 'l', 'a', 'c'):
             return MEDIA_MIMETYPE_AUDIO_ALAC;
 
+        case FOURCC('a', 'v', '0', '1'):
+            return MEDIA_MIMETYPE_VIDEO_AV1;
         default:
             ALOGW("Unknown fourcc: %c%c%c%c",
                    (fourcc >> 24) & 0xff,
@@ -459,11 +466,12 @@
     [=] {
         int64_t duration;
         int32_t samplerate;
+        // Only for audio track.
         if (track->has_elst && mHeaderTimescale != 0 &&
                 AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) &&
                 AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) {
 
-            // elst has to be processed only the first time this function is called
+            // Elst has to be processed only the first time this function is called.
             track->has_elst = false;
 
             if (track->elst_segment_duration > INT64_MAX) {
@@ -479,67 +487,72 @@
                   halfscale, mHeaderTimescale, track->timescale);
 
             if ((uint32_t)samplerate != track->timescale){
-                ALOGV("samplerate:%" PRId32 ", track->timescale and samplerate are different!", samplerate);
+                ALOGV("samplerate:%" PRId32 ", track->timescale and samplerate are different!",
+                    samplerate);
             }
-
-            int64_t delay;
-            // delay = ((media_time * samplerate) + halfscale) / track->timescale;
-            if (__builtin_mul_overflow(media_time, samplerate, &delay) ||
-                    __builtin_add_overflow(delay, halfscale, &delay) ||
-                    (delay /= track->timescale, false) ||
-                    delay > INT32_MAX ||
-                    delay < INT32_MIN) {
-                ALOGW("ignoring edit list with bogus values");
-                return;
+            // Both delay and paddingsamples have to be set inorder for either to be
+            // effective in the lower layers.
+            int64_t delay = 0;
+            if (media_time > 0) { // Gapless playback
+                // delay = ((media_time * samplerate) + halfscale) / track->timescale;
+                if (__builtin_mul_overflow(media_time, samplerate, &delay) ||
+                        __builtin_add_overflow(delay, halfscale, &delay) ||
+                        (delay /= track->timescale, false) ||
+                        delay > INT32_MAX ||
+                        delay < INT32_MIN) {
+                    ALOGW("ignoring edit list with bogus values");
+                    return;
+                }
             }
             ALOGV("delay = %" PRId64, delay);
             AMediaFormat_setInt32(track->meta, AMEDIAFORMAT_KEY_ENCODER_DELAY, delay);
 
-            int64_t scaled_duration;
-            // scaled_duration = duration * mHeaderTimescale;
-            if (__builtin_mul_overflow(duration, mHeaderTimescale, &scaled_duration)) {
-                return;
-            }
-            ALOGV("scaled_duration = %" PRId64, scaled_duration);
-
-            int64_t segment_end;
-            int64_t padding;
-            int64_t segment_duration_e6;
-            int64_t media_time_scaled_e6;
-            int64_t media_time_scaled;
-            // padding = scaled_duration - ((segment_duration * 1000000) +
-            //                  ((media_time * mHeaderTimeScale * 1000000)/track->timescale) )
-            // segment_duration is based on timescale in movie header box(mdhd)
-            // media_time is based on timescale track header/media timescale
-            if (__builtin_mul_overflow(segment_duration, 1000000, &segment_duration_e6) ||
-                __builtin_mul_overflow(media_time, mHeaderTimescale, &media_time_scaled) ||
-                __builtin_mul_overflow(media_time_scaled, 1000000, &media_time_scaled_e6)) {
-                return;
-            }
-            media_time_scaled_e6 /= track->timescale;
-            if(__builtin_add_overflow(segment_duration_e6, media_time_scaled_e6, &segment_end) ||
-                __builtin_sub_overflow(scaled_duration, segment_end, &padding)) {
-                return;
-            }
-            ALOGV("segment_end = %" PRId64 ", padding = %" PRId64, segment_end, padding);
             int64_t paddingsamples = 0;
-            if (padding < 0) {
+            if (segment_duration > 0) {
+                int64_t scaled_duration;
+                // scaled_duration = duration * mHeaderTimescale;
+                if (__builtin_mul_overflow(duration, mHeaderTimescale, &scaled_duration)) {
+                    return;
+                }
+                ALOGV("scaled_duration = %" PRId64, scaled_duration);
+
+                int64_t segment_end;
+                int64_t padding;
+                int64_t segment_duration_e6;
+                int64_t media_time_scaled_e6;
+                int64_t media_time_scaled;
+                // padding = scaled_duration - ((segment_duration * 1000000) +
+                //                  ((media_time * mHeaderTimescale * 1000000)/track->timescale) )
+                // segment_duration is based on timescale in movie header box(mdhd)
+                // media_time is based on timescale track header/media timescale
+                if (__builtin_mul_overflow(segment_duration, 1000000, &segment_duration_e6) ||
+                    __builtin_mul_overflow(media_time, mHeaderTimescale, &media_time_scaled) ||
+                    __builtin_mul_overflow(media_time_scaled, 1000000, &media_time_scaled_e6)) {
+                    return;
+                }
+                media_time_scaled_e6 /= track->timescale;
+                if (__builtin_add_overflow(segment_duration_e6, media_time_scaled_e6, &segment_end)
+                    || __builtin_sub_overflow(scaled_duration, segment_end, &padding)) {
+                    return;
+                }
+                ALOGV("segment_end = %" PRId64 ", padding = %" PRId64, segment_end, padding);
                 // track duration from media header (which is what AMEDIAFORMAT_KEY_DURATION is)
                 // might be slightly shorter than the segment duration, which would make the
                 // padding negative. Clamp to zero.
-                padding = 0;
-            } else {
-                int64_t halfscale_e6;
-                int64_t timescale_e6;
-                // paddingsamples = ((padding * samplerate) + (halfscale * 1000000))
-                //                / (mHeaderTimescale * 1000000);
-                if (__builtin_mul_overflow(padding, samplerate, &paddingsamples) ||
-                        __builtin_mul_overflow(halfscale, 1000000, &halfscale_e6) ||
-                        __builtin_mul_overflow(mHeaderTimescale, 1000000, &timescale_e6) ||
-                        __builtin_add_overflow(paddingsamples, halfscale_e6, &paddingsamples) ||
-                        (paddingsamples /= timescale_e6, false) ||
-                        paddingsamples > INT32_MAX) {
-                    return;
+                if (padding > 0) {
+                    int64_t halfscale_mht = mHeaderTimescale / 2;
+                    int64_t halfscale_e6;
+                    int64_t timescale_e6;
+                    // paddingsamples = ((padding * samplerate) + (halfscale_mht * 1000000))
+                    //                / (mHeaderTimescale * 1000000);
+                    if (__builtin_mul_overflow(padding, samplerate, &paddingsamples) ||
+                            __builtin_mul_overflow(halfscale_mht, 1000000, &halfscale_e6) ||
+                            __builtin_mul_overflow(mHeaderTimescale, 1000000, &timescale_e6) ||
+                            __builtin_add_overflow(paddingsamples, halfscale_e6, &paddingsamples) ||
+                            (paddingsamples /= timescale_e6, false) ||
+                            paddingsamples > INT32_MAX) {
+                        return;
+                    }
                 }
             }
             ALOGV("paddingsamples = %" PRId64, paddingsamples);
@@ -668,6 +681,7 @@
             track->includes_expensive_metadata = false;
             track->skipTrack = false;
             track->timescale = 1000000;
+            track->elstShiftStartTicks = 0;
         }
     }
 
@@ -965,6 +979,7 @@
                         AMEDIAFORMAT_KEY_MIME, "application/octet-stream");
                 track->has_elst = false;
                 track->subsample_encryption = false;
+                track->elstShiftStartTicks = 0;
             }
 
             off64_t stop_offset = *offset + chunk_size;
@@ -1092,6 +1107,7 @@
 
             if (entry_count != 1) {
                 // we only support a single entry at the moment, for gapless playback
+                // or start offset
                 ALOGW("ignoring edit list with %d entries", entry_count);
             } else {
                 off64_t entriesoffset = data_offset + 8;
@@ -1740,6 +1756,7 @@
         case FOURCC('a', 'v', 'c', '1'):
         case FOURCC('h', 'v', 'c', '1'):
         case FOURCC('h', 'e', 'v', '1'):
+        case FOURCC('a', 'v', '0', '1'):
         {
             uint8_t buffer[78];
             if (chunk_data_size < (ssize_t)sizeof(buffer)) {
@@ -3929,9 +3946,15 @@
         }
     }
 
+    if (track->has_elst and !strncasecmp("video/", mime, 6) and track->elst_media_time > 0) {
+        track->elstShiftStartTicks = track->elst_media_time;
+        ALOGV("video track->elstShiftStartTicks :%" PRId64, track->elst_media_time);
+    }
+
     MPEG4Source *source =  new MPEG4Source(
             track->meta, mDataSource, track->timescale, track->sampleTable,
-            mSidxEntries, trex, mMoofOffset, itemTable);
+            mSidxEntries, trex, mMoofOffset, itemTable,
+            track->elstShiftStartTicks);
     if (source->init() != OK) {
         delete source;
         return NULL;
@@ -4332,7 +4355,8 @@
         Vector<SidxEntry> &sidx,
         const Trex *trex,
         off64_t firstMoofOffset,
-        const sp<ItemTable> &itemTable)
+        const sp<ItemTable> &itemTable,
+        int32_t elstShiftStartTicks)
     : mFormat(format),
       mDataSource(dataSource),
       mTimescale(timeScale),
@@ -4360,7 +4384,8 @@
       mBuffer(NULL),
       mSrcBuffer(NULL),
       mIsHeif(itemTable != NULL),
-      mItemTable(itemTable) {
+      mItemTable(itemTable),
+      mElstShiftStartTicks(elstShiftStartTicks) {
 
     memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
 
@@ -4445,11 +4470,31 @@
 }
 
 status_t MPEG4Source::init() {
+    status_t err = OK;
+    const char *mime;
+    CHECK(AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime));
     if (mFirstMoofOffset != 0) {
         off64_t offset = mFirstMoofOffset;
-        return parseChunk(&offset);
+        err = parseChunk(&offset);
+        if(err == OK && !strncasecmp("video/", mime, 6)
+            && !mCurrentSamples.isEmpty()) {
+            // Start offset should be less or equal to composition time of first sample.
+            // ISO : sample_composition_time_offset, version 0 (unsigned) for major brands.
+            mElstShiftStartTicks = std::min(mElstShiftStartTicks,
+                (*mCurrentSamples.begin()).compositionOffset);
+        }
+        return err;
     }
-    return OK;
+
+    if (!strncasecmp("video/", mime, 6)) {
+        uint32_t firstSampleCTS = 0;
+        err = mSampleTable->getMetaDataForSample(0, NULL, NULL, &firstSampleCTS);
+        // Start offset should be less or equal to composition time of first sample.
+        // Composition time stamp of first sample cannot be negative.
+        mElstShiftStartTicks = std::min(mElstShiftStartTicks, (int32_t)firstSampleCTS);
+    }
+
+    return err;
 }
 
 MPEG4Source::~MPEG4Source() {
@@ -4990,7 +5035,7 @@
 
 status_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
 
-    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
+    ALOGV("MPEG4Source::parseTrackFragmentRun");
     if (size < 8) {
         return -EINVAL;
     }
@@ -5132,10 +5177,10 @@
         }
 
         ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, "
-              " flags 0x%08x", i + 1,
+              " flags 0x%08x ctsOffset %" PRIu32, i + 1,
                 dataOffset, sampleSize, sampleDuration,
                 (flags & kFirstSampleFlagsPresent) && i == 0
-                    ? firstSampleFlags : sampleFlags);
+                    ? firstSampleFlags : sampleFlags, sampleCtsOffset);
         tmp.offset = dataOffset;
         tmp.size = sampleSize;
         tmp.duration = sampleDuration;
@@ -5227,6 +5272,7 @@
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+
         if (mIsHeif) {
             CHECK(mSampleTable == NULL);
             CHECK(mItemTable != NULL);
@@ -5264,6 +5310,9 @@
                     CHECK(!"Should not be here.");
                     break;
             }
+            if( mode != ReadOptions::SEEK_FRAME_INDEX) {
+                seekTimeUs += ((int64_t)mElstShiftStartTicks * 1000000) / mTimescale;
+            }
 
             uint32_t sampleIndex;
             status_t err = mSampleTable->findSampleAtTime(
@@ -5305,6 +5354,7 @@
 
             if (mode == ReadOptions::SEEK_CLOSEST
                 || mode == ReadOptions::SEEK_FRAME_INDEX) {
+                sampleTime -= mElstShiftStartTicks;
                 targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
             }
 
@@ -5343,6 +5393,10 @@
         if (!mIsHeif) {
             err = mSampleTable->getMetaDataForSample(
                     mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
+            if(err == OK) {
+                cts -= mElstShiftStartTicks;
+            }
+
         } else {
             err = mItemTable->getImageOffsetAndSize(
                     options && options->getSeekTo(&seekTimeUs, &mode) ?
@@ -5623,6 +5677,10 @@
     ReadOptions::SeekMode mode;
     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
 
+        seekTimeUs += ((int64_t)mElstShiftStartTicks * 1000000) / mTimescale;
+        ALOGV("shifted seekTimeUs :%" PRId64 ", mElstShiftStartTicks:%" PRId32, seekTimeUs,
+                mElstShiftStartTicks);
+
         int numSidxEntries = mSegments.size();
         if (numSidxEntries != 0) {
             int64_t totalTime = 0;
@@ -5709,6 +5767,8 @@
         offset = smpl->offset;
         size = smpl->size;
         cts = mCurrentTime + smpl->compositionOffset;
+        cts -= mElstShiftStartTicks;
+
         mCurrentTime += smpl->duration;
         isSyncSample = (mCurrentSampleIndex == 0);
 
@@ -5960,6 +6020,7 @@
         FOURCC('a', 'v', 'c', '1'),
         FOURCC('h', 'v', 'c', '1'),
         FOURCC('h', 'e', 'v', '1'),
+        FOURCC('a', 'v', '0', '1'),
         FOURCC('3', 'g', 'p', '4'),
         FOURCC('m', 'p', '4', '1'),
         FOURCC('m', 'p', '4', '2'),
@@ -6122,6 +6183,19 @@
     return NULL;
 }
 
+static const char *extensions[] = {
+    "3g2",
+    "3gp",
+    "3gpp",
+    "3gpp2",
+    "m4a",
+    "m4r",
+    "m4v",
+    "mov",
+    "mp4",
+    NULL
+};
+
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
@@ -6131,7 +6205,7 @@
         UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
         2, // version
         "MP4 Extractor",
-        { .v2 = Sniff }
+        { .v3 = {Sniff, extensions} },
     };
 }
 
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 79d5ff6dd..fadfb50 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -85,6 +85,7 @@
         bool has_elst;
         int64_t elst_media_time;
         uint64_t elst_segment_duration;
+        int32_t elstShiftStartTicks;
         bool subsample_encryption;
     };
 
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/extractors/mpeg2/ExtractorBundle.cpp
index 2f4196c..946a2a9 100644
--- a/media/extractors/mpeg2/ExtractorBundle.cpp
+++ b/media/extractors/mpeg2/ExtractorBundle.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <media/MediaExtractorPluginHelper.h>
+#include <media/stagefright/MediaDefs.h>
 #include "MPEG2PSExtractor.h"
 #include "MPEG2TSExtractor.h"
 
@@ -26,6 +27,12 @@
 
 struct CDataSource;
 
+static const char *extensions[] = {
+   "m2p",
+   "ts",
+   NULL
+};
+
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
@@ -36,26 +43,29 @@
         1,
         "MPEG2-PS/TS Extractor",
         {
-            .v2 = [](
+            .v3 = {
+                [](
                     CDataSource *source,
                     float *confidence,
                     void **,
                     FreeMetaFunc *) -> CreatorFunc {
-                DataSourceHelper helper(source);
-                if (SniffMPEG2TS(&helper, confidence)) {
-                    return [](
-                            CDataSource *source,
-                            void *) -> CMediaExtractor* {
-                        return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
-                } else if (SniffMPEG2PS(&helper, confidence)) {
-                            return [](
-                                    CDataSource *source,
-                                    void *) -> CMediaExtractor* {
-                                return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
-                }
-                return NULL;
+                    DataSourceHelper helper(source);
+                    if (SniffMPEG2TS(&helper, confidence)) {
+                        return [](
+                                CDataSource *source,
+                                void *) -> CMediaExtractor* {
+                            return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
+                    } else if (SniffMPEG2PS(&helper, confidence)) {
+                        return [](
+                                CDataSource *source,
+                                void *) -> CMediaExtractor* {
+                            return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
+                    }
+                    return NULL;
+                },
+                extensions
             }
-        }
+        },
     };
 }
 
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index 554d252..731584d 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -734,6 +734,9 @@
     if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
         AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
     }
+    if (inMeta.findData(kKeyAudioPresentationInfo, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, bufData, bufSize);
+    }
     mbuf->release();
     return AMEDIA_OK;
 }
@@ -790,6 +793,7 @@
 }
 
 media_status_t MPEG2PSExtractor::WrappedTrack::start() {
+    mTrack->mBufferGroup = mBufferGroup;
     return mTrack->start();
 }
 
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 3bb2af7..e1509ee 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -224,6 +224,9 @@
     if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
         AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
     }
+    if (inMeta.findData(kKeyAudioPresentationInfo, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, bufData, bufSize);
+    }
     mbuf->release();
     return AMEDIA_OK;
 }
@@ -373,7 +376,7 @@
         }
 
         // Wait only for 2 seconds to detect audio/video streams.
-        if (ALooper::GetNowUs() - startTime > 2000000ll) {
+        if (ALooper::GetNowUs() - startTime > 2000000LL) {
             break;
         }
     }
@@ -385,7 +388,7 @@
         List<int64_t> durations;
         // Estimate duration --- stabilize until you get <500ms deviation.
         while (feedMore() == OK
-                && ALooper::GetNowUs() - startTime <= 2000000ll) {
+                && ALooper::GetNowUs() - startTime <= 2000000LL) {
             if (mSeekSyncPoints->size() > prevSyncSize) {
                 prevSyncSize = mSeekSyncPoints->size();
                 int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1)
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index c3914f1..6efbfee 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -872,7 +872,7 @@
 
             ALOGV("readPage returned %zd", n);
 
-            return n < 0 ? (media_status_t) n : AMEDIA_ERROR_END_OF_STREAM;
+            return n == ERROR_END_OF_STREAM ? AMEDIA_ERROR_END_OF_STREAM : AMEDIA_ERROR_UNKNOWN;
         }
 
         // Prevent a harmless unsigned integer overflow by clamping to 0
@@ -1379,6 +1379,12 @@
     return CreateExtractor;
 }
 
+static const char *extensions[] = {
+    "oga",
+    "ogg",
+    NULL
+};
+
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
@@ -1388,7 +1394,7 @@
         UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
         1, // version
         "Ogg Extractor",
-        { .v2 = Sniff }
+        { .v3 = {Sniff, extensions} },
     };
 }
 
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 6f9f689..e58bd1f 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -616,6 +616,11 @@
     return CreateExtractor;
 }
 
+static const char *extensions[] = {
+    "wav",
+    NULL
+};
+
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
@@ -625,7 +630,7 @@
         UUID("7d613858-5837-4a38-84c5-332d1cddee27"),
         1, // version
         "WAV Extractor",
-        { .v2 = Sniff }
+        { .v3 = {Sniff, extensions} },
     };
 }
 
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index d1f7525..9601d6d 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -22,6 +22,22 @@
 namespace android {
 
 //
+//  AudioDeviceTypeAddr implementation
+//
+status_t AudioDeviceTypeAddr::readFromParcel(Parcel *parcel) {
+    mType = (audio_devices_t) parcel->readInt32();
+    mAddress = parcel->readString8();
+    return NO_ERROR;
+}
+
+status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
+    parcel->writeInt32((int32_t) mType);
+    parcel->writeString8(mAddress);
+    return NO_ERROR;
+}
+
+
+//
 //  AudioMixMatchCriterion implementation
 //
 AudioMixMatchCriterion::AudioMixMatchCriterion(audio_usage_t usage,
@@ -40,11 +56,22 @@
 status_t AudioMixMatchCriterion::readFromParcel(Parcel *parcel)
 {
     mRule = parcel->readInt32();
-    if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
-            mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
-        mValue.mUsage = (audio_usage_t)parcel->readInt32();
-    } else {
-        mValue.mSource = (audio_source_t)parcel->readInt32();
+    switch (mRule) {
+    case RULE_MATCH_ATTRIBUTE_USAGE:
+    case RULE_EXCLUDE_ATTRIBUTE_USAGE:
+        mValue.mUsage = (audio_usage_t) parcel->readInt32();
+        break;
+    case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+    case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
+        mValue.mSource = (audio_source_t) parcel->readInt32();
+        break;
+    case RULE_MATCH_UID:
+    case RULE_EXCLUDE_UID:
+        mValue.mUid = (uid_t) parcel->readInt32();
+        break;
+    default:
+        ALOGE("Trying to build AudioMixMatchCriterion from unknown rule %d", mRule);
+        return BAD_VALUE;
     }
     return NO_ERROR;
 }
@@ -116,4 +143,11 @@
     return NO_ERROR;
 }
 
+void AudioMix::excludeUid(uid_t uid) const {
+    AudioMixMatchCriterion crit;
+    crit.mRule = RULE_EXCLUDE_UID;
+    crit.mValue.mUid = uid;
+    mCriteria.add(crit);
+}
+
 } // namespace android
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index dc7531c..baeae8b 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1236,6 +1236,19 @@
     return aps->registerPolicyMixes(mixes, registration);
 }
 
+status_t AudioSystem::setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->setUidDeviceAffinities(uid, devices);
+}
+
+status_t AudioSystem::removeUidDeviceAffinities(uid_t uid) {
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->removeUidDeviceAffinities(uid);
+}
+
 status_t AudioSystem::startAudioSource(const struct audio_port_config *source,
                                        const audio_attributes_t *attributes,
                                        audio_port_handle_t *portId)
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 0ce8b16..272415c 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -90,6 +90,8 @@
     SET_ASSISTANT_UID,
     SET_A11Y_SERVICES_UIDS,
     IS_HAPTIC_PLAYBACK_SUPPORTED,
+    SET_UID_DEVICE_AFFINITY,
+    REMOVE_UID_DEVICE_AFFINITY,
 };
 
 #define MAX_ITEMS_PER_LIST 1024
@@ -990,6 +992,50 @@
         return reply.readBool();
     }
 
+    virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+        data.writeInt32((int32_t) uid);
+        size_t size = devices.size();
+        size_t sizePosition = data.dataPosition();
+        data.writeInt32((int32_t) size);
+        size_t finalSize = size;
+        for (size_t i = 0; i < size; i++) {
+            size_t position = data.dataPosition();
+            if (devices[i].writeToParcel(&data) != NO_ERROR) {
+                data.setDataPosition(position);
+                finalSize--;
+            }
+        }
+        if (size != finalSize) {
+            size_t position = data.dataPosition();
+            data.setDataPosition(sizePosition);
+            data.writeInt32(finalSize);
+            data.setDataPosition(position);
+        }
+
+        status_t status = remote()->transact(SET_UID_DEVICE_AFFINITY, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t removeUidDeviceAffinities(uid_t uid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+        data.writeInt32((int32_t) uid);
+
+        status_t status = remote()->transact(REMOVE_UID_DEVICE_AFFINITY, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1048,7 +1094,9 @@
         case GET_SURROUND_FORMATS:
         case SET_SURROUND_FORMAT_ENABLED:
         case SET_ASSISTANT_UID:
-        case SET_A11Y_SERVICES_UIDS: {
+        case SET_A11Y_SERVICES_UIDS:
+        case SET_UID_DEVICE_AFFINITY:
+        case REMOVE_UID_DEVICE_AFFINITY: {
             if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                 ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                       __func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1811,6 +1859,30 @@
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             bool isSupported = isHapticPlaybackSupported();
             reply->writeBool(isSupported);
+            return NO_ERROR;    
+        }
+
+        case SET_UID_DEVICE_AFFINITY: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            const uid_t uid = (uid_t) data.readInt32();
+            Vector<AudioDeviceTypeAddr> devices;
+            size_t size = (size_t)data.readInt32();
+            for (size_t i = 0; i < size; i++) {
+                AudioDeviceTypeAddr device;
+                if (device.readFromParcel((Parcel*)&data) == NO_ERROR) {
+                    devices.add(device);
+                }
+            }
+            status_t status = setUidDeviceAffinities(uid, devices);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+
+        case REMOVE_UID_DEVICE_AFFINITY: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            const uid_t uid = (uid_t) data.readInt32();
+            status_t status = removeUidDeviceAffinities(uid);
+            reply->writeInt32(status);
             return NO_ERROR;
         }
 
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 8da0069..96e1235 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -56,6 +56,19 @@
 #define MAX_MIXES_PER_POLICY 10
 #define MAX_CRITERIA_PER_MIX 20
 
+class AudioDeviceTypeAddr {
+public:
+    AudioDeviceTypeAddr() {}
+    AudioDeviceTypeAddr(audio_devices_t type, String8 address) :
+        mType(type), mAddress(address) {}
+
+    status_t readFromParcel(Parcel *parcel);
+    status_t writeToParcel(Parcel *parcel) const;
+
+    audio_devices_t mType;
+    String8 mAddress;
+};
+
 class AudioMixMatchCriterion {
 public:
     AudioMixMatchCriterion() {}
@@ -87,7 +100,9 @@
     status_t readFromParcel(Parcel *parcel);
     status_t writeToParcel(Parcel *parcel) const;
 
-    Vector<AudioMixMatchCriterion> mCriteria;
+    void excludeUid(uid_t uid) const;
+
+    mutable Vector<AudioMixMatchCriterion> mCriteria;
     uint32_t        mMixType;
     audio_config_t  mFormat;
     uint32_t        mRouteFlags;
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index b0da5b8..781e9df 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -325,6 +325,10 @@
 
     static status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
 
+    static status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+
+    static status_t removeUidDeviceAffinities(uid_t uid);
+
     static status_t startAudioSource(const struct audio_port_config *source,
                                      const audio_attributes_t *attributes,
                                      audio_port_handle_t *portId);
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 61f3b27..fb4fe93 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -167,6 +167,11 @@
 
     virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration) = 0;
 
+    virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+            = 0;
+
+    virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
+
     virtual status_t startAudioSource(const struct audio_port_config *source,
                                       const audio_attributes_t *attributes,
                                       audio_port_handle_t *portId) = 0;
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 2567b3b..86711de 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -302,14 +302,19 @@
     if (audio_channel_mask_get_representation(channelMask)
                 == AUDIO_CHANNEL_REPRESENTATION_POSITION
             && DownmixerBufferProvider::isMultichannelCapable()) {
-        mDownmixerBufferProvider.reset(new DownmixerBufferProvider(channelMask,
-                mMixerChannelMask,
-                AUDIO_FORMAT_PCM_16_BIT /* TODO: use mMixerInFormat, now only PCM 16 */,
-                sampleRate, sessionId, kCopyBufferFrameCount));
-        if (static_cast<DownmixerBufferProvider *>(mDownmixerBufferProvider.get())->isValid()) {
-            mDownmixRequiresFormat = AUDIO_FORMAT_PCM_16_BIT; // PCM 16 bit required for downmix
-            reconfigureBufferProviders();
-            return NO_ERROR;
+
+        // Check if we have a float or int16 downmixer, in that order.
+        for (const audio_format_t format : { AUDIO_FORMAT_PCM_FLOAT, AUDIO_FORMAT_PCM_16_BIT }) {
+            mDownmixerBufferProvider.reset(new DownmixerBufferProvider(
+                    channelMask, mMixerChannelMask,
+                    format,
+                    sampleRate, sessionId, kCopyBufferFrameCount));
+            if (static_cast<DownmixerBufferProvider *>(mDownmixerBufferProvider.get())
+                    ->isValid()) {
+                mDownmixRequiresFormat = format;
+                reconfigureBufferProviders();
+                return NO_ERROR;
+            }
         }
         // mDownmixerBufferProvider reset below.
     }
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index 227f2a1..9c82b1d 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -13,7 +13,7 @@
     relative_install_path: "soundfx",
 
     cflags: [
-        //"-DBUILD_FLOAT",
+        "-DBUILD_FLOAT",
         "-fvisibility=hidden",
         "-Wall",
         "-Werror",
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index b4a1d77..99ac4f5 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -31,10 +31,12 @@
 // Do not submit with DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER defined, strictly for testing
 //#define DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER 0
 
-#define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
-
 #ifdef BUILD_FLOAT
 #define MINUS_3_DB_IN_FLOAT 0.70710678f // -3dB = 0.70710678f
+const audio_format_t gTargetFormat = AUDIO_FORMAT_PCM_FLOAT;
+#else
+#define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
+const audio_format_t gTargetFormat = AUDIO_FORMAT_PCM_16_BIT;
 #endif
 
 // subset of possible audio_channel_mask_t values, and AUDIO_CHANNEL_OUT_* renamed to CHANNEL_MASK_*
@@ -703,7 +705,7 @@
     memset(&pDwmModule->context, 0, sizeof(downmix_object_t));
 
     pDwmModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
-    pDwmModule->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+    pDwmModule->config.inputCfg.format = gTargetFormat;
     pDwmModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_7POINT1;
     pDwmModule->config.inputCfg.bufferProvider.getBuffer = NULL;
     pDwmModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
@@ -715,7 +717,7 @@
 
     // set a default value for the access mode, but should be overwritten by caller
     pDwmModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
-    pDwmModule->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+    pDwmModule->config.outputCfg.format = gTargetFormat;
     pDwmModule->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
     pDwmModule->config.outputCfg.bufferProvider.getBuffer = NULL;
     pDwmModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
@@ -762,8 +764,8 @@
     // Check configuration compatibility with build options, and effect capabilities
     if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate
         || pConfig->outputCfg.channels != DOWNMIX_OUTPUT_CHANNELS
-        || pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT
-        || pConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+        || pConfig->inputCfg.format != gTargetFormat
+        || pConfig->outputCfg.format != gTargetFormat) {
         ALOGE("Downmix_Configure error: invalid config");
         return -EINVAL;
     }
@@ -1185,8 +1187,8 @@
     if (accumulate) {
         while (numFrames) {
             // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
-            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
-                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_FLOAT)
+                    + (pSrc[3] * MINUS_3_DB_IN_FLOAT);
             // FL + centerPlusLfeContrib + SL + RL
             lt = pSrc[0] + centerPlusLfeContrib + pSrc[6] + pSrc[4];
             // FR + centerPlusLfeContrib + SR + RR
@@ -1427,4 +1429,4 @@
     }
     return true;
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index b5860de..0c6f8de 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1544,7 +1544,7 @@
 int VirtualizerIsConfigurationSupported(audio_channel_mask_t channelMask,
         audio_devices_t deviceType) {
     uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
-    if (channelCount < 1 || channelCount > LVM_MAX_CHANNELS) {
+    if (channelCount < 1 || channelCount > FCC_2) { // TODO: update to 8 channels when supported.
         return -EINVAL;
     }
     return VirtualizerIsDeviceSupported(deviceType);
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 6002e95..7d759e0 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -216,8 +216,7 @@
         "libutils",
         "libbinder",
         "libsonivox",
-        "libicuuc",
-        "libicui18n",
+        "libandroidicu",
         "libexpat",
         "libcamera_client",
         "libstagefright_foundation",
@@ -232,8 +231,7 @@
     export_shared_lib_headers: [
         "libaudioclient",
         "libbinder",
-        "libicuuc",
-        "libicui18n",
+        "libandroidicu",
         "libsonivox",
         "libmedia_omx",
     ],
diff --git a/media/libmedia/IMediaExtractorService.cpp b/media/libmedia/IMediaExtractorService.cpp
index 0295abc..243b09d 100644
--- a/media/libmedia/IMediaExtractorService.cpp
+++ b/media/libmedia/IMediaExtractorService.cpp
@@ -29,6 +29,7 @@
 enum {
     MAKE_EXTRACTOR = IBinder::FIRST_CALL_TRANSACTION,
     MAKE_IDATA_SOURCE_FD,
+    GET_SUPPORTED_TYPES,
 };
 
 class BpMediaExtractorService : public BpInterface<IMediaExtractorService>
@@ -68,6 +69,24 @@
         }
         return nullptr;
     }
+
+    virtual std::unordered_set<std::string> getSupportedTypes() {
+        std::unordered_set<std::string> supportedTypes;
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
+        status_t ret = remote()->transact(GET_SUPPORTED_TYPES, data, &reply);
+        if (ret == NO_ERROR) {
+            // process reply
+            while(true) {
+                const char *ext = reply.readCString();
+                if (!ext) {
+                    break;
+                }
+                supportedTypes.insert(std::string(ext));
+            }
+        }
+        return supportedTypes;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaExtractorService, "android.media.IMediaExtractorService");
@@ -113,6 +132,15 @@
             return NO_ERROR;
         }
 
+        case GET_SUPPORTED_TYPES:
+        {
+            CHECK_INTERFACE(IMediaExtractorService, data, reply);
+            std::unordered_set<std::string> supportedTypes = getSupportedTypes();
+            for (auto it = supportedTypes.begin(); it != supportedTypes.end(); ++it) {
+                reply->writeCString((*it).c_str());
+            }
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index eed96e7..6dbc9b8 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -57,6 +57,10 @@
     AMEDIAFORMAT_KEY_COLOR_STANDARD,
     AMEDIAFORMAT_KEY_COLOR_TRANSFER,
     AMEDIAFORMAT_KEY_COMPLEXITY,
+    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,
@@ -102,6 +106,8 @@
 };
 
 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,
@@ -1243,7 +1249,11 @@
     if (mAMediaExtractor == NULL) {
         return NULL;
     }
-    return new AMediaCodecCryptoInfoWrapper(AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor));
+    AMediaCodecCryptoInfo *cryptoInfo = AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor);
+    if (cryptoInfo == NULL) {
+        return NULL;
+    }
+    return new AMediaCodecCryptoInfoWrapper(cryptoInfo);
 }
 
 AMediaDataSourceWrapper::AMediaDataSourceWrapper(const sp<DataSource> &dataSource)
diff --git a/media/libmedia/include/media/IMediaExtractorService.h b/media/libmedia/include/media/IMediaExtractorService.h
index 45e9620..5ce2cdb 100644
--- a/media/libmedia/include/media/IMediaExtractorService.h
+++ b/media/libmedia/include/media/IMediaExtractorService.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_IMEDIAEXTRACTORSERVICE_H
 #define ANDROID_IMEDIAEXTRACTORSERVICE_H
 
+#include <unordered_set>
+
 #include <binder/IInterface.h>
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
@@ -33,6 +35,8 @@
     virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime) = 0;
 
     virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length) = 0;
+
+    virtual std::unordered_set<std::string> getSupportedTypes() = 0;
 };
 
 class BnMediaExtractorService: public BnInterface<IMediaExtractorService>
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index caa0186..33be559 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -115,9 +115,6 @@
  * The state machine of the media_recorder.
  */
 enum media_recorder_states {
-    // Error state.
-    MEDIA_RECORDER_ERROR                 =      0,
-
     // Recorder was just created.
     MEDIA_RECORDER_IDLE                  = 1 << 0,
 
@@ -132,6 +129,9 @@
 
     // Recording is in progress.
     MEDIA_RECORDER_RECORDING             = 1 << 4,
+
+    // Error state.
+    MEDIA_RECORDER_ERROR                 = 1 << 5,
 };
 
 // The "msg" code passed to the listener in notify.
diff --git a/media/libmediaplayer2/Android.bp b/media/libmediaplayer2/Android.bp
index 6b43375..38f42dc 100644
--- a/media/libmediaplayer2/Android.bp
+++ b/media/libmediaplayer2/Android.bp
@@ -16,6 +16,7 @@
         "libandroid_runtime",
         "libaudioclient",
         "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libgui",
         "liblog",
@@ -91,18 +92,15 @@
         "JMedia2HTTPConnection.cpp",
     ],
 
+    header_libs: [
+        "libbinder_headers",
+        "libnativehelper_header_only",
+    ],
+
     shared_libs: [
-        "android.hidl.token@1.0-utils",
         "liblog",
-        "libcutils",
         "libutils",
-        "libbinder",
-        "libstagefright_foundation",
-        "libmediaextractor",
         "libdl",
-        "libaudioutils",
-        "libaudioclient",
-        "libnativehelper",
     ],
 
     include_dirs: [
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
index 5e98589..0c8d016 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
@@ -30,7 +30,6 @@
 #include <media/AudioSystem.h>
 #include <media/AudioTimestamp.h>
 #include <media/BufferingSettings.h>
-#include <media/Metadata.h>
 #include <media/stagefright/foundation/AHandler.h>
 #include <mediaplayer2/MediaPlayer2Types.h>
 
@@ -224,18 +223,6 @@
     // @return OK if the call was successful.
     virtual status_t invoke(const PlayerMessage &request, PlayerMessage *reply) = 0;
 
-    // The Client in the MetadataPlayerService calls this method on
-    // the native player to retrieve all or a subset of metadata.
-    //
-    // @param ids SortedList of metadata ID to be fetch. If empty, all
-    //            the known metadata should be returned.
-    // @param[inout] records Parcel where the player appends its metadata.
-    // @return OK if the call was successful.
-    virtual status_t getMetadata(const media::Metadata::Filter& /* ids */,
-                                 Parcel* /* records */) {
-        return INVALID_OPERATION;
-    };
-
     void setListener(const sp<MediaPlayer2InterfaceListener> &listener) {
         Mutex::Autolock autoLock(mListenerLock);
         mListener = listener;
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
index a945ffd..78865c4 100644
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
@@ -20,7 +20,6 @@
 #include <media/AVSyncSettings.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/BufferingSettings.h>
-#include <media/Metadata.h>
 #include <media/mediaplayer_common.h>
 #include <mediaplayer2/MediaPlayer2Interface.h>
 #include <mediaplayer2/MediaPlayer2Types.h>
@@ -55,7 +54,7 @@
 public:
     ~MediaPlayer2();
 
-    static sp<MediaPlayer2> Create(int32_t sessionId);
+    static sp<MediaPlayer2> Create(int32_t sessionId, jobject context);
     static status_t DumpAll(int fd, const Vector<String16>& args);
 
             void            disconnect();
@@ -118,7 +117,7 @@
             status_t        dump(int fd, const Vector<String16>& args);
 
 private:
-    MediaPlayer2(int32_t sessionId);
+    MediaPlayer2(int32_t sessionId, jobject context);
     bool init();
 
     // Disconnect from the currently connected ANativeWindow.
@@ -154,6 +153,7 @@
     int                         mVideoHeight;
     int32_t                     mAudioSessionId;
     sp<JObjectHolder>           mAudioAttributes;
+    sp<JObjectHolder>           mContext;
     float                       mSendLevel;
     sp<ANativeWindowWrapper>    mConnectedWindow;
 };
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index f432059..f75380c 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -18,14 +18,11 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaPlayer2Native"
 
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-
+#include <android/binder_ibinder.h>
 #include <media/AudioSystem.h>
 #include <media/DataSourceDesc.h>
 #include <media/MediaAnalyticsItem.h>
 #include <media/MemoryLeakTrackUtil.h>
-#include <media/Metadata.h>
 #include <media/NdkWrapper.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooperRoster.h>
@@ -103,114 +100,110 @@
     String8 result;
     SortedVector< sp<MediaPlayer2> > players; //to serialise the mutex unlock & client destruction.
 
-    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
-        snprintf(buffer, SIZE, "Permission Denial: can't dump MediaPlayer2\n");
-        result.append(buffer);
+    {
+        Mutex::Autolock lock(sRecordLock);
+        ensureInit_l();
+        for (int i = 0, n = sPlayers->size(); i < n; ++i) {
+            sp<MediaPlayer2> p = (*sPlayers)[i].promote();
+            if (p != 0) {
+                p->dump(fd, args);
+            }
+            players.add(p);
+        }
+    }
+
+    result.append(" Files opened and/or mapped:\n");
+    snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
+    FILE *f = fopen(buffer, "r");
+    if (f) {
+        while (!feof(f)) {
+            fgets(buffer, SIZE, f);
+            if (strstr(buffer, " /storage/") ||
+                strstr(buffer, " /system/sounds/") ||
+                strstr(buffer, " /data/") ||
+                strstr(buffer, " /system/media/")) {
+                result.append("  ");
+                result.append(buffer);
+            }
+        }
+        fclose(f);
     } else {
-        {
-            Mutex::Autolock lock(sRecordLock);
-            ensureInit_l();
-            for (int i = 0, n = sPlayers->size(); i < n; ++i) {
-                sp<MediaPlayer2> p = (*sPlayers)[i].promote();
-                if (p != 0) {
-                    p->dump(fd, args);
-                }
-                players.add(p);
-            }
-        }
+        result.append("couldn't open ");
+        result.append(buffer);
+        result.append("\n");
+    }
 
-        result.append(" Files opened and/or mapped:\n");
-        snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
-        FILE *f = fopen(buffer, "r");
-        if (f) {
-            while (!feof(f)) {
-                fgets(buffer, SIZE, f);
-                if (strstr(buffer, " /storage/") ||
-                    strstr(buffer, " /system/sounds/") ||
-                    strstr(buffer, " /data/") ||
-                    strstr(buffer, " /system/media/")) {
-                    result.append("  ");
-                    result.append(buffer);
-                }
-            }
-            fclose(f);
-        } else {
-            result.append("couldn't open ");
-            result.append(buffer);
-            result.append("\n");
-        }
-
-        snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
-        DIR *d = opendir(buffer);
-        if (d) {
-            struct dirent *ent;
-            while((ent = readdir(d)) != NULL) {
-                if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
-                    snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
-                    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;
-                                }
-                                if (strstr(linkto, "/storage/") == linkto ||
-                                    strstr(linkto, "/system/sounds/") == linkto ||
-                                    strstr(linkto, "/data/") == linkto ||
-                                    strstr(linkto, "/system/media/") == linkto) {
-                                    result.append("  ");
-                                    result.append(buffer);
-                                    result.append(" -> ");
-                                    result.append(linkto);
-                                    result.append("\n");
-                                }
+    snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
+    DIR *d = opendir(buffer);
+    if (d) {
+        struct dirent *ent;
+        while((ent = readdir(d)) != NULL) {
+            if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
+                snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
+                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;
                             }
-                        } else {
-                            result.append("  unexpected type for ");
-                            result.append(buffer);
-                            result.append("\n");
+                            if (strstr(linkto, "/storage/") == linkto ||
+                                strstr(linkto, "/system/sounds/") == linkto ||
+                                strstr(linkto, "/data/") == linkto ||
+                                strstr(linkto, "/system/media/") == linkto) {
+                                result.append("  ");
+                                result.append(buffer);
+                                result.append(" -> ");
+                                result.append(linkto);
+                                result.append("\n");
+                            }
                         }
+                    } else {
+                        result.append("  unexpected type for ");
+                        result.append(buffer);
+                        result.append("\n");
                     }
                 }
             }
-            closedir(d);
-        } else {
-            result.append("couldn't open ");
-            result.append(buffer);
-            result.append("\n");
         }
+        closedir(d);
+    } else {
+        result.append("couldn't open ");
+        result.append(buffer);
+        result.append("\n");
+    }
 
-        gLooperRoster.dump(fd, args);
+    gLooperRoster.dump(fd, args);
 
-        bool dumpMem = false;
-        bool unreachableMemory = false;
-        for (size_t i = 0; i < args.size(); i++) {
-            if (args[i] == String16("-m")) {
-                dumpMem = true;
-            } else if (args[i] == String16("--unreachable")) {
-                unreachableMemory = true;
-            }
-        }
-        if (dumpMem) {
-            result.append("\nDumping memory:\n");
-            std::string s = dumpMemoryAddresses(100 /* limit */);
-            result.append(s.c_str(), s.size());
-        }
-        if (unreachableMemory) {
-            result.append("\nDumping unreachable memory:\n");
-            // TODO - should limit be an argument parameter?
-            // TODO: enable GetUnreachableMemoryString if it's part of stable API
-            //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
-            //result.append(s.c_str(), s.size());
+    bool dumpMem = false;
+    bool unreachableMemory = false;
+    for (size_t i = 0; i < args.size(); i++) {
+        if (args[i] == String16("-m")) {
+            dumpMem = true;
+        } else if (args[i] == String16("--unreachable")) {
+            unreachableMemory = true;
         }
     }
+    if (dumpMem) {
+        result.append("\nDumping memory:\n");
+        std::string s = dumpMemoryAddresses(100 /* limit */);
+        result.append(s.c_str(), s.size());
+    }
+    if (unreachableMemory) {
+        result.append("\nDumping unreachable memory:\n");
+        // TODO - should limit be an argument parameter?
+        // TODO: enable GetUnreachableMemoryString if it's part of stable API
+        //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
+        //result.append(s.c_str(), s.size());
+    }
+
     write(fd, result.string(), result.size());
     return NO_ERROR;
 }
@@ -218,8 +211,8 @@
 }  // anonymous namespace
 
 //static
-sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId) {
-    sp<MediaPlayer2> player = new MediaPlayer2(sessionId);
+sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId, jobject context) {
+    sp<MediaPlayer2> player = new MediaPlayer2(sessionId, context);
 
     if (!player->init()) {
         return NULL;
@@ -236,13 +229,14 @@
     return dumpPlayers(fd, args);
 }
 
-MediaPlayer2::MediaPlayer2(int32_t sessionId) {
+MediaPlayer2::MediaPlayer2(int32_t sessionId, jobject context) {
     ALOGV("constructor");
     mSrcId = 0;
     mLockThreadId = 0;
     mListener = NULL;
     mStreamType = AUDIO_STREAM_MUSIC;
     mAudioAttributes = NULL;
+    mContext = new JObjectHolder(context);
     mCurrentPosition = -1;
     mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
     mSeekPosition = -1;
@@ -253,9 +247,8 @@
     mVideoWidth = mVideoHeight = 0;
     mSendLevel = 0;
 
-    // TODO: get pid and uid from JAVA
-    mPid = IPCThreadState::self()->getCallingPid();
-    mUid = IPCThreadState::self()->getCallingUid();
+    mPid = AIBinder_getCallingPid();
+    mUid = AIBinder_getCallingUid();
 
     mAudioOutput = new MediaPlayer2AudioOutput(sessionId, mUid, mPid, NULL /*attributes*/);
 }
@@ -334,15 +327,15 @@
 
     sp<MediaPlayer2Interface> oldPlayer;
 
-    Mutex::Autolock _l(mLock);
     {
+        Mutex::Autolock _l(mLock);
         if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
               || mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
             ALOGE("setDataSource called in wrong state %d", mCurrentState);
             return INVALID_OPERATION;
         }
 
-        sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
+        sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid, mContext);
         status_t err = player->initCheck();
         if (err != NO_ERROR) {
             ALOGE("Failed to create player object, initCheck failed(%d)", err);
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
index f01361b..9552580 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
@@ -1286,6 +1286,11 @@
             mVideoTimeUs = timeUs;
         }
 
+        sp<AMediaCodecCryptoInfoWrapper> cryptInfo = extractor->getSampleCryptoInfo();
+        if (cryptInfo != NULL) {
+            meta->setObject("cryptInfo", cryptInfo);
+        }
+
         queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
 
         if (numBuffers == 0 && actualTimeUs != nullptr) {
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp b/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
index c9a1071..983d77e 100644
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
+++ b/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
@@ -20,55 +20,50 @@
 
 #include "JWakeLock.h"
 
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
 #include <media/stagefright/foundation/ADebug.h>
-#include <powermanager/PowerManager.h>
-
 
 namespace android {
 
-//TODO: use JAVA PowerManager, instead of binder
-JWakeLock::JWakeLock() :
-    mPowerManager(NULL),
-    mWakeLockToken(NULL),
+JWakeLock::JWakeLock(const sp<JObjectHolder> &context) :
     mWakeLockCount(0),
-    mDeathRecipient(new PMDeathRecipient(this)) {}
+    mWakeLock(NULL),
+    mContext(context) {}
 
 JWakeLock::~JWakeLock() {
-    if (mPowerManager != NULL) {
-        sp<IBinder> binder = IInterface::asBinder(mPowerManager);
-        binder->unlinkToDeath(mDeathRecipient);
-    }
-    clearPowerManager();
+    clearJavaWakeLock();
 }
 
 bool JWakeLock::acquire() {
     if (mWakeLockCount == 0) {
-        CHECK(mWakeLockToken == NULL);
-        if (mPowerManager == NULL) {
-            // use checkService() to avoid blocking if power service is not up yet
-            sp<IBinder> binder =
-                defaultServiceManager()->checkService(String16("power"));
-            if (binder == NULL) {
-                ALOGW("could not get the power manager service");
-            } else {
-                mPowerManager = interface_cast<IPowerManager>(binder);
-                binder->linkToDeath(mDeathRecipient);
-            }
+        if (mWakeLock == NULL) {
+            JNIEnv *env = JavaVMHelper::getJNIEnv();
+            jclass jContextCls = env->FindClass("android/content/Context");
+            jclass jPowerManagerCls = env->FindClass("android/os/PowerManager");
+
+            jmethodID jGetSystemService = env->GetMethodID(jContextCls,
+                    "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
+            jobject javaPowerManagerObj = env->CallObjectMethod(mContext->getJObject(),
+                    jGetSystemService, env->NewStringUTF("power"));
+
+            jfieldID jPARTIAL_WAKE_LOCK = env->GetStaticFieldID(jPowerManagerCls,
+                    "PARTIAL_WAKE_LOCK", "I");
+            jint PARTIAL_WAKE_LOCK = env->GetStaticIntField(jPowerManagerCls, jPARTIAL_WAKE_LOCK);
+
+            jmethodID jNewWakeLock = env->GetMethodID(jPowerManagerCls,
+                    "newWakeLock", "(ILjava/lang/String;)Landroid/os/PowerManager$WakeLock;");
+            jobject javaWakeLock = env->CallObjectMethod(javaPowerManagerObj,
+                    jNewWakeLock, PARTIAL_WAKE_LOCK, env->NewStringUTF("JWakeLock"));
+            mWakeLock = new JObjectHolder(javaWakeLock);
+            env->DeleteLocalRef(javaPowerManagerObj);
+            env->DeleteLocalRef(javaWakeLock);
         }
-        if (mPowerManager != NULL) {
-            sp<IBinder> binder = new BBinder();
-            int64_t token = IPCThreadState::self()->clearCallingIdentity();
-            status_t status = mPowerManager->acquireWakeLock(
-                    POWERMANAGER_PARTIAL_WAKE_LOCK,
-                    binder, String16("JWakeLock"), String16("media"));
-            IPCThreadState::self()->restoreCallingIdentity(token);
-            if (status == NO_ERROR) {
-                mWakeLockToken = binder;
-                mWakeLockCount++;
-                return true;
-            }
+        if (mWakeLock != NULL) {
+            JNIEnv *env = JavaVMHelper::getJNIEnv();
+            jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
+            jmethodID jAcquire = env->GetMethodID(wakeLockCls, "acquire", "()V");
+            env->CallVoidMethod(mWakeLock->getJObject(), jAcquire);
+            mWakeLockCount++;
+            return true;
         }
     } else {
         mWakeLockCount++;
@@ -86,25 +81,17 @@
         mWakeLockCount = 1;
     }
     if (--mWakeLockCount == 0) {
-        CHECK(mWakeLockToken != NULL);
-        if (mPowerManager != NULL) {
-            int64_t token = IPCThreadState::self()->clearCallingIdentity();
-            mPowerManager->releaseWakeLock(mWakeLockToken, 0 /* flags */);
-            IPCThreadState::self()->restoreCallingIdentity(token);
+        if (mWakeLock != NULL) {
+            JNIEnv *env = JavaVMHelper::getJNIEnv();
+            jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
+            jmethodID jRelease = env->GetMethodID(wakeLockCls, "release", "()V");
+            env->CallVoidMethod(mWakeLock->getJObject(), jRelease);
         }
-        mWakeLockToken.clear();
     }
 }
 
-void JWakeLock::clearPowerManager() {
+void JWakeLock::clearJavaWakeLock() {
     release(true);
-    mPowerManager.clear();
-}
-
-void JWakeLock::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused) {
-    if (mWakeLock != NULL) {
-        mWakeLock->clearPowerManager();
-    }
 }
 
 }  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.h b/media/libmediaplayer2/nuplayer2/JWakeLock.h
index eace87e..36c542e 100644
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.h
+++ b/media/libmediaplayer2/nuplayer2/JWakeLock.h
@@ -18,7 +18,7 @@
 #define J_WAKELOCK_H_
 
 #include <media/stagefright/foundation/ABase.h>
-#include <powermanager/IPowerManager.h>
+#include <mediaplayer2/JObjectHolder.h>
 #include <utils/RefBase.h>
 
 namespace android {
@@ -26,7 +26,7 @@
 class JWakeLock : public RefBase {
 
 public:
-    JWakeLock();
+    JWakeLock(const sp<JObjectHolder> &context);
 
     // NOTE: acquire and release are not thread safe
 
@@ -37,28 +37,11 @@
     virtual ~JWakeLock();
 
 private:
-    sp<IPowerManager> mPowerManager;
-    sp<IBinder>       mWakeLockToken;
-    uint32_t          mWakeLockCount;
+    uint32_t                mWakeLockCount;
+    sp<JObjectHolder>       mWakeLock;
+    const sp<JObjectHolder> mContext;
 
-    class PMDeathRecipient : public IBinder::DeathRecipient {
-    public:
-        explicit PMDeathRecipient(JWakeLock *wakeLock) : mWakeLock(wakeLock) {}
-        virtual ~PMDeathRecipient() {}
-
-        // IBinder::DeathRecipient
-        virtual void binderDied(const wp<IBinder> &who);
-
-    private:
-        PMDeathRecipient(const PMDeathRecipient&);
-        PMDeathRecipient& operator= (const PMDeathRecipient&);
-
-        JWakeLock *mWakeLock;
-    };
-
-    const sp<PMDeathRecipient> mDeathRecipient;
-
-    void clearPowerManager();
+    void clearJavaWakeLock();
 
     DISALLOW_EVIL_CONSTRUCTORS(JWakeLock);
 };
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index 080d923..5da6e24 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -209,7 +209,8 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-NuPlayer2::NuPlayer2(pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock)
+NuPlayer2::NuPlayer2(
+        pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context)
     : mPID(pid),
       mUID(uid),
       mMediaClock(mediaClock),
@@ -240,7 +241,8 @@
       mVideoDecoderError(false),
       mPaused(false),
       mPausedByClient(true),
-      mPausedForBuffering(false) {
+      mPausedForBuffering(false),
+      mContext(context) {
     CHECK(mediaClock != NULL);
     clearFlushComplete();
 }
@@ -1738,7 +1740,7 @@
     sp<AMessage> notify = new AMessage(kWhatRendererNotify, this);
     ++mRendererGeneration;
     notify->setInt32("generation", mRendererGeneration);
-    mRenderer = new Renderer(mAudioSink, mMediaClock, notify, flags);
+    mRenderer = new Renderer(mAudioSink, mMediaClock, notify, mContext, flags);
     mRendererLooper = new ALooper;
     mRendererLooper->setName("NuPlayer2Renderer");
     mRendererLooper->start(false, true, ANDROID_PRIORITY_AUDIO);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
index fdc128f..798c725 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
@@ -22,6 +22,7 @@
 #include <media/stagefright/foundation/AHandler.h>
 
 #include <mediaplayer2/MediaPlayer2Interface.h>
+#include <mediaplayer2/JObjectHolder.h>
 
 #include "mediaplayer2.pb.h"
 
@@ -42,7 +43,8 @@
 struct NuPlayer2Driver;
 
 struct NuPlayer2 : public AHandler {
-    explicit NuPlayer2(pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock);
+    explicit NuPlayer2(pid_t pid, uid_t uid,
+            const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context);
 
     void setDriver(const wp<NuPlayer2Driver> &driver);
 
@@ -272,6 +274,9 @@
     // Pause state as requested by source (internally) due to buffering
     bool mPausedForBuffering;
 
+    // Passed from JAVA
+    const sp<JObjectHolder> mContext;
+
     inline const sp<DecoderBase> &getDecoder(bool audio) {
         return audio ? mAudioDecoder : mVideoDecoder;
     }
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
index 49e3e3b..a5bd62d 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
@@ -1108,6 +1108,11 @@
             } // buffer->data()
         } // needsCopy
 
+        sp<RefBase> cryptInfoObj;
+        if (buffer->meta()->findObject("cryptInfo", &cryptInfoObj)) {
+            cryptInfo = static_cast<AMediaCodecCryptoInfoWrapper *>(cryptInfoObj.get());
+        }
+
         status_t err;
         if (cryptInfo != NULL) {
             err = mCodec->queueSecureInputBuffer(
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
index 2dab2dd..56e9471 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
@@ -108,7 +108,7 @@
 static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
 
 
-NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid)
+NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context)
     : mState(STATE_IDLE),
       mAsyncResult(UNKNOWN_ERROR),
       mSrcId(0),
@@ -123,7 +123,7 @@
       mLooper(new ALooper),
       mNuPlayer2Looper(new ALooper),
       mMediaClock(new MediaClock),
-      mPlayer(new NuPlayer2(pid, uid, mMediaClock)),
+      mPlayer(new NuPlayer2(pid, uid, mMediaClock, context)),
       mPlayerFlags(0),
       mAnalyticsItem(NULL),
       mClientUid(uid),
@@ -662,33 +662,6 @@
     return INVALID_OPERATION;
 }
 
-status_t NuPlayer2Driver::getMetadata(
-        const media::Metadata::Filter& /* ids */, Parcel *records) {
-    Mutex::Autolock autoLock(mLock);
-
-    using media::Metadata;
-
-    Metadata meta(records);
-
-    meta.appendBool(
-            Metadata::kPauseAvailable,
-            mPlayerFlags & NuPlayer2::Source::FLAG_CAN_PAUSE);
-
-    meta.appendBool(
-            Metadata::kSeekBackwardAvailable,
-            mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_BACKWARD);
-
-    meta.appendBool(
-            Metadata::kSeekForwardAvailable,
-            mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_FORWARD);
-
-    meta.appendBool(
-            Metadata::kSeekAvailable,
-            mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK);
-
-    return OK;
-}
-
 void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
     ALOGD("notifyResetComplete(%p)", this);
     Mutex::Autolock autoLock(mLock);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
index bb30c76..0ec3a4b 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
@@ -18,6 +18,7 @@
 
 #include <media/MediaAnalyticsItem.h>
 #include <media/stagefright/foundation/ABase.h>
+#include <mediaplayer2/JObjectHolder.h>
 
 namespace android {
 
@@ -26,7 +27,7 @@
 struct NuPlayer2;
 
 struct NuPlayer2Driver : public MediaPlayer2Interface {
-    explicit NuPlayer2Driver(pid_t pid, uid_t uid);
+    explicit NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context);
 
     virtual status_t initCheck() override;
 
@@ -61,9 +62,6 @@
     virtual status_t setParameter(int key, const Parcel &request) override;
     virtual status_t getParameter(int key, Parcel *reply) override;
 
-    virtual status_t getMetadata(
-            const media::Metadata::Filter& ids, Parcel *records) override;
-
     virtual status_t dump(int fd, const Vector<String16> &args) const override;
 
     virtual void onMessageReceived(const sp<AMessage> &msg) override;
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
index e3c9b4b..3be7e36 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
@@ -26,6 +26,8 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaClock.h>
+#include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
 #include <media/stagefright/VideoFrameScheduler2.h>
@@ -86,10 +88,25 @@
 // static
 const int64_t NuPlayer2::Renderer::kMinPositionUpdateDelayUs = 100000LL;
 
+static audio_format_t constexpr audioFormatFromEncoding(int32_t pcmEncoding) {
+    switch (pcmEncoding) {
+    case kAudioEncodingPcmFloat:
+        return AUDIO_FORMAT_PCM_FLOAT;
+    case kAudioEncodingPcm16bit:
+        return AUDIO_FORMAT_PCM_16_BIT;
+    case kAudioEncodingPcm8bit:
+        return AUDIO_FORMAT_PCM_8_BIT;  // TODO: do we want to support this?
+    default:
+        ALOGE("%s: Invalid encoding: %d", __func__, pcmEncoding);
+        return AUDIO_FORMAT_INVALID;
+    }
+}
+
 NuPlayer2::Renderer::Renderer(
         const sp<MediaPlayer2Interface::AudioSink> &sink,
         const sp<MediaClock> &mediaClock,
         const sp<AMessage> &notify,
+        const sp<JObjectHolder> &context,
         uint32_t flags)
     : mAudioSink(sink),
       mUseVirtualAudioSink(false),
@@ -131,7 +148,7 @@
       mTotalBuffersQueued(0),
       mLastAudioBufferDrained(0),
       mUseAudioCallback(false),
-      mWakeLock(new JWakeLock()) {
+      mWakeLock(new JWakeLock(context)) {
     CHECK(mediaClock != NULL);
     mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
 }
@@ -1269,10 +1286,10 @@
             mAnchorTimeMediaUs = mediaTimeUs;
         }
     }
-    mNextVideoTimeMediaUs = mediaTimeUs + 100000;
+    mNextVideoTimeMediaUs = mediaTimeUs;
     if (!mHasAudio) {
         // smooth out videos >= 10fps
-        mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+        mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
     }
 
     if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
@@ -1406,9 +1423,15 @@
         mHasAudio = false;
         if (mNextVideoTimeMediaUs >= 0) {
             int64_t mediaUs = 0;
-            mMediaClock->getMediaTime(ALooper::GetNowUs(), &mediaUs);
-            if (mNextVideoTimeMediaUs > mediaUs) {
-                mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+            int64_t nowUs = ALooper::GetNowUs();
+            status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
+            if (result == OK) {
+                if (mNextVideoTimeMediaUs > mediaUs) {
+                    mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+                }
+            } else {
+                mMediaClock->updateAnchor(
+                        mNextVideoTimeMediaUs, nowUs, mNextVideoTimeMediaUs + 100000);
             }
         }
     }
@@ -1864,8 +1887,13 @@
     int32_t sampleRate;
     CHECK(format->findInt32("sample-rate", &sampleRate));
 
+    // read pcm encoding from MediaCodec output format, if available
+    int32_t pcmEncoding;
+    audio_format_t audioFormat =
+            format->findInt32(KEY_PCM_ENCODING, &pcmEncoding) ?
+                    audioFormatFromEncoding(pcmEncoding) : AUDIO_FORMAT_PCM_16_BIT;
+
     if (offloadingAudio()) {
-        audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
         AString mime;
         CHECK(format->findString("mime", &mime));
         status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
@@ -1966,7 +1994,7 @@
         const PcmInfo info = {
                 (audio_channel_mask_t)channelMask,
                 (audio_output_flags_t)pcmFlags,
-                AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
+                audioFormat,
                 numChannels,
                 sampleRate
         };
@@ -1998,7 +2026,7 @@
                     sampleRate,
                     numChannels,
                     (audio_channel_mask_t)channelMask,
-                    AUDIO_FORMAT_PCM_16_BIT,
+                    audioFormat,
                     mUseAudioCallback ? &NuPlayer2::Renderer::AudioSinkCallback : NULL,
                     mUseAudioCallback ? this : NULL,
                     (audio_output_flags_t)pcmFlags,
@@ -2054,4 +2082,3 @@
 }
 
 }  // namespace android
-
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
index 484d9b7..d065dee 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
@@ -20,6 +20,7 @@
 
 #include <media/AudioResamplerPublic.h>
 #include <media/AVSyncSettings.h>
+#include <mediaplayer2/JObjectHolder.h>
 
 #include "NuPlayer2.h"
 
@@ -38,6 +39,7 @@
     Renderer(const sp<MediaPlayer2Interface::AudioSink> &sink,
              const sp<MediaClock> &mediaClock,
              const sp<AMessage> &notify,
+             const sp<JObjectHolder> &context,
              uint32_t flags = 0);
 
     static size_t AudioSinkCallback(
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index e2aa8f8..1e85804 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -171,6 +171,7 @@
 
     if (extractor == NULL) {
         ALOGE("initFromDataSource, cannot create extractor!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
@@ -179,6 +180,7 @@
     size_t numtracks = extractor->countTracks();
     if (numtracks == 0) {
         ALOGE("initFromDataSource, source has no track!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index c8f6738..c990b2a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1299,10 +1299,10 @@
             mAnchorTimeMediaUs = mediaTimeUs;
         }
     }
-    mNextVideoTimeMediaUs = mediaTimeUs + 100000;
+    mNextVideoTimeMediaUs = mediaTimeUs;
     if (!mHasAudio) {
         // smooth out videos >= 10fps
-        mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+        mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
     }
 
     if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
@@ -1436,9 +1436,15 @@
         mHasAudio = false;
         if (mNextVideoTimeMediaUs >= 0) {
             int64_t mediaUs = 0;
-            mMediaClock->getMediaTime(ALooper::GetNowUs(), &mediaUs);
-            if (mNextVideoTimeMediaUs > mediaUs) {
-                mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+            int64_t nowUs = ALooper::GetNowUs();
+            status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
+            if (result == OK) {
+                if (mNextVideoTimeMediaUs > mediaUs) {
+                    mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+                }
+            } else {
+                mMediaClock->updateAnchor(
+                        mNextVideoTimeMediaUs, nowUs, mNextVideoTimeMediaUs + 100000);
             }
         }
     }
diff --git a/media/libnblog/Reader.cpp b/media/libnblog/Reader.cpp
index fd53090..f556e37 100644
--- a/media/libnblog/Reader.cpp
+++ b/media/libnblog/Reader.cpp
@@ -284,6 +284,15 @@
 EntryIterator DumpReader::handleFormat(const FormatEntry &fmtEntry,
         String8 *timestamp, String8 *body)
 {
+    String8 timestampLocal;
+    String8 bodyLocal;
+    if (timestamp == nullptr) {
+        timestamp = &timestampLocal;
+    }
+    if (body == nullptr) {
+        body = &bodyLocal;
+    }
+
     // log timestamp
     const int64_t ts = fmtEntry.timestamp();
     timestamp->clear();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 6ad0417..dadfe28 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -566,8 +566,8 @@
       mDequeueCounter(0),
       mMetadataBuffersToSubmit(0),
       mNumUndequeuedBuffers(0),
-      mRepeatFrameDelayUs(-1ll),
-      mMaxPtsGapUs(0ll),
+      mRepeatFrameDelayUs(-1LL),
+      mMaxPtsGapUs(0LL),
       mMaxFps(-1),
       mFps(-1.0),
       mCaptureFps(-1.0),
@@ -1822,15 +1822,15 @@
         if (!msg->findInt64(
                     "repeat-previous-frame-after",
                     &mRepeatFrameDelayUs)) {
-            mRepeatFrameDelayUs = -1ll;
+            mRepeatFrameDelayUs = -1LL;
         }
 
         // only allow 32-bit value, since we pass it as U32 to OMX.
         if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
-            mMaxPtsGapUs = 0ll;
+            mMaxPtsGapUs = 0LL;
         } else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < INT32_MIN) {
             ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
-            mMaxPtsGapUs = 0ll;
+            mMaxPtsGapUs = 0LL;
         }
 
         if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
@@ -1838,7 +1838,7 @@
         }
 
         // notify GraphicBufferSource to allow backward frames
-        if (mMaxPtsGapUs < 0ll) {
+        if (mMaxPtsGapUs < 0LL) {
             mMaxFps = -1;
         }
 
@@ -2183,7 +2183,8 @@
             err = setupG711Codec(encoder, sampleRate, numChannels);
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
-        int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
+        // numChannels needs to be set to properly communicate PCM values.
+        int32_t numChannels = 2, sampleRate = 44100, compressionLevel = -1;
         if (encoder &&
                 (!msg->findInt32("channel-count", &numChannels)
                         || !msg->findInt32("sample-rate", &sampleRate))) {
@@ -2209,7 +2210,7 @@
                 }
             }
             err = setupFlacCodec(
-                    encoder, numChannels, sampleRate, compressionLevel);
+                    encoder, numChannels, sampleRate, compressionLevel, pcmEncoding);
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
         int32_t numChannels, sampleRate;
@@ -2320,12 +2321,16 @@
             (void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
             mConverter[kPortIndexInput] = AudioConverter::Create(pcmEncoding, codecPcmEncoding);
             if (mConverter[kPortIndexInput] != NULL) {
+                ALOGD("%s: encoder %s input format pcm encoding converter from %d to %d",
+                        __func__, mComponentName.c_str(), pcmEncoding, codecPcmEncoding);
                 mInputFormat->setInt32("pcm-encoding", pcmEncoding);
             }
         } else {
             (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
             mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
             if (mConverter[kPortIndexOutput] != NULL) {
+                ALOGD("%s: decoder %s output format pcm encoding converter from %d to %d",
+                        __func__, mComponentName.c_str(), codecPcmEncoding, pcmEncoding);
                 mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
             }
         }
@@ -3029,8 +3034,8 @@
 }
 
 status_t ACodec::setupFlacCodec(
-        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
-
+        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel,
+        AudioEncoding encoding) {
     if (encoder) {
         OMX_AUDIO_PARAM_FLACTYPE def;
         InitOMXParams(&def);
@@ -3053,7 +3058,8 @@
     return setupRawAudioFormat(
             encoder ? kPortIndexInput : kPortIndexOutput,
             sampleRate,
-            numChannels);
+            numChannels,
+            encoding);
 }
 
 status_t ACodec::setupRawAudioFormat(
@@ -3111,6 +3117,7 @@
     pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
 
     if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
+        ALOGE("%s: incorrect numChannels: %d", __func__, numChannels);
         return OMX_ErrorNone;
     }
 
@@ -4421,8 +4428,8 @@
         h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
 
         // disable B-frames until MPEG4Writer can guarantee finalizing files with B-frames
-        h264type.nRefFrames = 1;
-        h264type.nBFrames = 0;
+        // h264type.nRefFrames = 1;
+        // h264type.nBFrames = 0;
 
         h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
         h264type.nAllowedPictureTypes =
@@ -6700,7 +6707,7 @@
 
     mCodec->mDequeueCounter = 0;
     mCodec->mMetadataBuffersToSubmit = 0;
-    mCodec->mRepeatFrameDelayUs = -1ll;
+    mCodec->mRepeatFrameDelayUs = -1LL;
     mCodec->mInputFormat.clear();
     mCodec->mOutputFormat.clear();
     mCodec->mBaseOutputFormat.clear();
@@ -6842,7 +6849,7 @@
         return err;
     }
 
-    if (mCodec->mRepeatFrameDelayUs > 0ll) {
+    if (mCodec->mRepeatFrameDelayUs > 0LL) {
         err = statusFromBinderStatus(
                 mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs(
                         mCodec->mRepeatFrameDelayUs));
@@ -6855,7 +6862,7 @@
         }
     }
 
-    if (mCodec->mMaxPtsGapUs != 0ll) {
+    if (mCodec->mMaxPtsGapUs != 0LL) {
         OMX_PARAM_U32TYPE maxPtsGapParams;
         InitOMXParams(&maxPtsGapParams);
         maxPtsGapParams.nPortIndex = kPortIndexInput;
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index a6f0a0b..199b57b 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -118,6 +118,13 @@
     }
 
     sp<MetaData> format = mSource->getFormat();
+
+    if (format == NULL) {
+        ALOGE("No metadata b/118620871");
+        android_errorWriteLog(0x534e4554, "118620871");
+        return BAD_VALUE;
+    }
+
     const char *mime;
     bool success = format->findCString(kKeyMIMEType, &mime);
     CHECK(success);
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 9de1e22..5027303 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -337,7 +337,7 @@
     } else {
         // This should not happen in normal case.
         ALOGW("Failed to get audio timestamp, fallback to use systemclock");
-        timeUs = systemTime() / 1000ll;
+        timeUs = systemTime() / 1000LL;
         // Estimate the real sampling time of the 1st sample in this buffer
         // from AudioRecord's latency. (Apply this adjustment first so that
         // the start time logic is not affected.)
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 3ad82d9..2a819ad 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -19,6 +19,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "CameraSourceTimeLapse"
 
+#include <media/hardware/HardwareAPI.h>
 #include <binder/IPCThreadState.h>
 #include <binder/MemoryBase.h>
 #include <binder/MemoryHeapBase.h>
@@ -172,8 +173,16 @@
     ALOGV("signalBufferReturned");
     Mutex::Autolock autoLock(mQuickStopLock);
     if (mQuickStop && (buffer == mLastReadBufferCopy)) {
+        if (metaDataStoredInVideoBuffers() == kMetadataBufferTypeNativeHandleSource) {
+            native_handle_t* handle = (
+                (VideoNativeHandleMetadata*)(mLastReadBufferCopy->data()))->pHandle;
+            native_handle_close(handle);
+            native_handle_delete(handle);
+        }
         buffer->setObserver(NULL);
         buffer->release();
+        mLastReadBufferCopy = NULL;
+        mForceRead = true;
     } else {
         return CameraSource::signalBufferReturned(buffer);
     }
@@ -182,7 +191,8 @@
 void createMediaBufferCopy(
         const MediaBufferBase& sourceBuffer,
         int64_t frameTime,
-        MediaBufferBase **newBuffer) {
+        MediaBufferBase **newBuffer,
+        int32_t videoBufferMode) {
 
     ALOGV("createMediaBufferCopy");
     size_t sourceSize = sourceBuffer.size();
@@ -192,13 +202,20 @@
     memcpy((*newBuffer)->data(), sourcePointer, sourceSize);
 
     (*newBuffer)->meta_data().setInt64(kKeyTime, frameTime);
+
+    if (videoBufferMode == kMetadataBufferTypeNativeHandleSource) {
+        ((VideoNativeHandleMetadata*)((*newBuffer)->data()))->pHandle =
+            native_handle_clone(
+                ((VideoNativeHandleMetadata*)(sourceBuffer.data()))->pHandle);
+    }
 }
 
 void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBufferBase& sourceBuffer) {
     ALOGV("fillLastReadBufferCopy");
     int64_t frameTime;
     CHECK(sourceBuffer.meta_data().findInt64(kKeyTime, &frameTime));
-    createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
+    createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy,
+        metaDataStoredInVideoBuffers());
     mLastReadBufferCopy->add_ref();
     mLastReadBufferCopy->setObserver(this);
 }
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index c62c05a..42b98b1 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -39,7 +39,7 @@
 
 namespace android {
 
-static const int64_t kBufferTimeOutUs = 10000ll; // 10 msec
+static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
 static const size_t kRetryCount = 50; // must be >0
 
 sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
@@ -274,7 +274,7 @@
     size_t retriesLeft = kRetryCount;
     do {
         size_t index;
-        int64_t ptsUs = 0ll;
+        int64_t ptsUs = 0LL;
         uint32_t flags = 0;
 
         // Queue as many inputs as we possibly can, then block on dequeuing
@@ -406,7 +406,7 @@
     : FrameDecoder(componentName, trackMeta, source),
       mIsAvcOrHevc(false),
       mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC),
-      mTargetTimeUs(-1ll),
+      mTargetTimeUs(-1LL),
       mNumFrames(0),
       mNumFramesDecoded(0) {
 }
@@ -487,7 +487,7 @@
         const sp<MediaCodecBuffer> &videoFrameBuffer,
         const sp<AMessage> &outputFormat,
         int64_t timeUs, bool *done) {
-    bool shouldOutput = (mTargetTimeUs < 0ll) || (timeUs >= mTargetTimeUs);
+    bool shouldOutput = (mTargetTimeUs < 0LL) || (timeUs >= mTargetTimeUs);
 
     // If this is not the target frame, skip color convert.
     if (!shouldOutput) {
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 770535c..a9715c9 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -240,7 +240,7 @@
         size -= length;
     }
 
-    out->meta()->setInt64("timeUs", 0ll);
+    out->meta()->setInt64("timeUs", 0LL);
 
     sp<AMessage> notify = mNotify->dup();
     notify->setInt32("what", kNotifyBuffer);
@@ -842,7 +842,7 @@
     int64_t timeUs;
     CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
 
-    uint32_t PTS = (timeUs * 9ll) / 100ll;
+    uint32_t PTS = (timeUs * 9LL) / 100LL;
 
     size_t PES_packet_length = accessUnit->size() + 8;
     bool padding = (accessUnit->size() < (188 - 18));
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a48466a..7df1a2d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -137,6 +137,8 @@
 
 private:
     enum {
+        // TODO: need to increase this considering the bug
+        // about camera app not sending video frames continuously?
         kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
         kSampleArraySize = 1000,
     };
@@ -317,6 +319,7 @@
     ListTableEntries<uint32_t, 1> *mStssTableEntries;
     ListTableEntries<uint32_t, 2> *mSttsTableEntries;
     ListTableEntries<uint32_t, 2> *mCttsTableEntries;
+    ListTableEntries<uint32_t, 3> *mElstTableEntries; // 3columns: segDuration, mediaTime, mediaRate
 
     int64_t mMinCttsOffsetTimeUs;
     int64_t mMinCttsOffsetTicks;
@@ -416,6 +419,8 @@
     // Duration is time scale based
     void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
     void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+    void addOneElstTableEntry(uint32_t segmentDuration, int32_t mediaTime,
+        int16_t mediaRate, int16_t mediaRateFraction);
 
     bool isTrackMalFormed() const;
     void sendTrackSummary(bool hasMultipleTracks);
@@ -448,6 +453,7 @@
     void writeVideoFourCCBox();
     void writeMetadataFourCCBox();
     void writeStblBox(bool use32BitOffset);
+    void writeEdtsBox();
 
     Track(const Track &);
     Track &operator=(const Track &);
@@ -481,8 +487,9 @@
 
     mInterleaveDurationUs = 1000000;
 
-    mStartTimestampUs = -1ll;
+    mStartTimestampUs = -1LL;
     mStartTimeOffsetMs = -1;
+    mStartTimeOffsetBFramesUs = 0;
     mPaused = false;
     mStarted = false;
     mWriterThreadStarted = false;
@@ -1272,6 +1279,10 @@
     // Adjust the global start time.
     mStartTimestampUs += minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
 
+    // Add mStartTimeOffsetBFramesUs(-ve or zero) to the duration of first entry in STTS.
+    mStartTimeOffsetBFramesUs = minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
+    ALOGV("mStartTimeOffsetBFramesUs :%" PRId32, mStartTimeOffsetBFramesUs);
+
     for (List<Track *>::iterator it = mTracks.begin();
         it != mTracks.end(); ++it) {
         if (!(*it)->isHeic()) {
@@ -1734,7 +1745,7 @@
 
 void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
     ALOGI("setStartTimestampUs: %" PRId64, timeUs);
-    CHECK_GE(timeUs, 0ll);
+    CHECK_GE(timeUs, 0LL);
     Mutex::Autolock autoLock(mLock);
     if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
         mStartTimestampUs = timeUs;
@@ -1747,6 +1758,11 @@
     return mStartTimestampUs;
 }
 
+int32_t MPEG4Writer::getStartTimeOffsetBFramesUs() {
+    Mutex::Autolock autoLock(mLock);
+    return mStartTimeOffsetBFramesUs;
+}
+
 size_t MPEG4Writer::numTracks() {
     Mutex::Autolock autolock(mLock);
     return mTracks.size();
@@ -1776,6 +1792,7 @@
       mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
       mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
       mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
+      mElstTableEntries(new ListTableEntries<uint32_t, 3>(3)), // Reserve 3 rows, a row has 3 items
       mMinCttsOffsetTimeUs(0),
       mMinCttsOffsetTicks(0),
       mMaxCttsOffsetTicks(0),
@@ -1842,46 +1859,48 @@
 
 // Clear all the internal states except the CSD data.
 void MPEG4Writer::Track::resetInternal() {
-      mDone = false;
-      mPaused = false;
-      mResumed = false;
-      mStarted = false;
-      mGotStartKeyFrame = false;
-      mIsMalformed = false;
-      mTrackDurationUs = 0;
-      mEstimatedTrackSizeBytes = 0;
-      mSamplesHaveSameSize = 0;
-      if (mStszTableEntries != NULL) {
-         delete mStszTableEntries;
-         mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
-      }
-
-      if (mStcoTableEntries != NULL) {
-         delete mStcoTableEntries;
-         mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
-      }
-      if (mCo64TableEntries != NULL) {
-         delete mCo64TableEntries;
-         mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
-      }
-
-      if (mStscTableEntries != NULL) {
-         delete mStscTableEntries;
-         mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000);
-      }
-      if (mStssTableEntries != NULL) {
-         delete mStssTableEntries;
-         mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000);
-      }
-      if (mSttsTableEntries != NULL) {
-         delete mSttsTableEntries;
-         mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
-      }
-      if (mCttsTableEntries != NULL) {
-         delete mCttsTableEntries;
-         mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
-      }
-      mReachedEOS = false;
+    mDone = false;
+    mPaused = false;
+    mResumed = false;
+    mStarted = false;
+    mGotStartKeyFrame = false;
+    mIsMalformed = false;
+    mTrackDurationUs = 0;
+    mEstimatedTrackSizeBytes = 0;
+    mSamplesHaveSameSize = 0;
+    if (mStszTableEntries != NULL) {
+        delete mStszTableEntries;
+        mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
+    }
+    if (mStcoTableEntries != NULL) {
+        delete mStcoTableEntries;
+        mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
+    }
+    if (mCo64TableEntries != NULL) {
+        delete mCo64TableEntries;
+        mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
+    }
+    if (mStscTableEntries != NULL) {
+        delete mStscTableEntries;
+        mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000);
+    }
+    if (mStssTableEntries != NULL) {
+        delete mStssTableEntries;
+        mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000);
+    }
+    if (mSttsTableEntries != NULL) {
+        delete mSttsTableEntries;
+        mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
+    }
+    if (mCttsTableEntries != NULL) {
+        delete mCttsTableEntries;
+        mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
+    }
+    if (mElstTableEntries != NULL) {
+        delete mElstTableEntries;
+        mElstTableEntries = new ListTableEntries<uint32_t, 3>(3);
+    }
+    mReachedEOS = false;
 }
 
 void MPEG4Writer::Track::updateTrackSizeEstimate() {
@@ -1900,6 +1919,7 @@
                                     mStssTableEntries->count() * 4 +   // stss box size
                                     mSttsTableEntries->count() * 8 +   // stts box size
                                     mCttsTableEntries->count() * 8 +   // ctts box size
+                                    mElstTableEntries->count() * 12 +   // elst box size
                                     stcoBoxSizeBytes +           // stco box size
                                     stszBoxSizeBytes;            // stsz box size
     }
@@ -1936,6 +1956,16 @@
     mCttsTableEntries->add(htonl(duration));
 }
 
+void MPEG4Writer::Track::addOneElstTableEntry(
+    uint32_t segmentDuration, int32_t mediaTime, int16_t mediaRate, int16_t mediaRateFraction) {
+    ALOGV("segmentDuration:%u, mediaTime:%d", segmentDuration, mediaTime);
+    ALOGV("mediaRate :%" PRId16 ", mediaRateFraction :%" PRId16 ", Ored %u", mediaRate,
+        mediaRateFraction, ((((uint32_t)mediaRate) << 16) | ((uint32_t)mediaRateFraction)));
+    mElstTableEntries->add(htonl(segmentDuration));
+    mElstTableEntries->add(htonl(mediaTime));
+    mElstTableEntries->add(htonl((((uint32_t)mediaRate) << 16) | (uint32_t)mediaRateFraction));
+}
+
 status_t MPEG4Writer::setNextFd(int fd) {
     ALOGV("addNextFd");
     Mutex::Autolock l(mLock);
@@ -2173,6 +2203,7 @@
     delete mSttsTableEntries;
     delete mStssTableEntries;
     delete mCttsTableEntries;
+    delete mElstTableEntries;
 
     mStszTableEntries = NULL;
     mStcoTableEntries = NULL;
@@ -2181,6 +2212,7 @@
     mSttsTableEntries = NULL;
     mStssTableEntries = NULL;
     mCttsTableEntries = NULL;
+    mElstTableEntries = NULL;
 
     if (mCodecSpecificData != NULL) {
         free(mCodecSpecificData);
@@ -3067,7 +3099,7 @@
 
             if (mResumed) {
                 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
-                if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
+                if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0LL, "for %s track", trackName)) {
                     copy->release();
                     mSource->stop();
                     mIsMalformed = true;
@@ -3088,7 +3120,7 @@
             TimestampDebugHelperEntry timestampDebugEntry;
             timestampUs -= previousPausedDurationUs;
             timestampDebugEntry.pts = timestampUs;
-            if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+            if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) {
                 copy->release();
                 mSource->stop();
                 mIsMalformed = true;
@@ -3127,7 +3159,7 @@
 
                 cttsOffsetTimeUs =
                         timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
-                if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
+                if (WARN_UNLESS(cttsOffsetTimeUs >= 0LL, "for %s track", trackName)) {
                     copy->release();
                     mSource->stop();
                     mIsMalformed = true;
@@ -3185,7 +3217,7 @@
                 }
             }
 
-            if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+            if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) {
                 copy->release();
                 mSource->stop();
                 mIsMalformed = true;
@@ -3206,7 +3238,7 @@
             currDurationTicks =
                 ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
-            if (currDurationTicks < 0ll) {
+            if (currDurationTicks < 0LL) {
                 ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
                         (long long)timestampUs, (long long)lastTimestampUs, trackName);
                 copy->release();
@@ -3612,6 +3644,7 @@
     uint32_t now = getMpeg4Time();
     mOwner->beginBox("trak");
         writeTkhdBox(now);
+        writeEdtsBox();
         mOwner->beginBox("mdia");
             writeMdhdBox(now);
             writeHdlrBox();
@@ -3982,6 +4015,33 @@
     mOwner->endBox();
 }
 
+void MPEG4Writer::Track::writeEdtsBox(){
+    ALOGV("%s : getStartTimeOffsetTimeUs of track:%" PRId64 " us", getTrackType(),
+        getStartTimeOffsetTimeUs());
+
+    // Prepone video playback.
+    if (mMinCttsOffsetTicks != mMaxCttsOffsetTicks) {
+        int32_t mvhdTimeScale = mOwner->getTimeScale();
+        uint32_t tkhdDuration = (mTrackDurationUs * mvhdTimeScale + 5E5) / 1E6;
+        int64_t mediaTime = ((kMaxCttsOffsetTimeUs - getMinCttsOffsetTimeUs())
+            * mTimeScale + 5E5) / 1E6;
+        if (tkhdDuration > 0 && mediaTime > 0) {
+            addOneElstTableEntry(tkhdDuration, mediaTime, 1, 0);
+        }
+    }
+
+    if (mElstTableEntries->count() == 0) {
+        return;
+    }
+
+    mOwner->beginBox("edts");
+        mOwner->beginBox("elst");
+            mOwner->writeInt32(0); // version=0, flags=0
+            mElstTableEntries->write(mOwner);
+        mOwner->endBox(); // elst;
+    mOwner->endBox(); // edts
+}
+
 void MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
     int64_t trakDurationUs = getDurationUs();
     int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
@@ -4118,7 +4178,9 @@
         uint32_t duration;
         CHECK(mSttsTableEntries->get(duration, 1));
         duration = htonl(duration);  // Back to host byte order
-        mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
+        int32_t startTimeOffsetScaled = (((getStartTimeOffsetTimeUs() +
+            mOwner->getStartTimeOffsetBFramesUs()) * mTimeScale) + 500000LL) / 1000000LL;
+        mSttsTableEntries->set(htonl((int32_t)duration + startTimeOffsetScaled), 1);
     }
     mSttsTableEntries->write(mOwner);
     mOwner->endBox();  // stts
diff --git a/media/libstagefright/MediaClock.cpp b/media/libstagefright/MediaClock.cpp
index 41dbfd4..8bff9f7 100644
--- a/media/libstagefright/MediaClock.cpp
+++ b/media/libstagefright/MediaClock.cpp
@@ -28,7 +28,7 @@
 
 // Maximum allowed time backwards from anchor change.
 // If larger than this threshold, it's treated as discontinuity.
-static const int64_t kAnchorFluctuationAllowedUs = 10000ll;
+static const int64_t kAnchorFluctuationAllowedUs = 10000LL;
 
 MediaClock::Timer::Timer(const sp<AMessage> &notify, int64_t mediaTimeUs, int64_t adjustRealUs)
     : mNotify(notify),
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index bd9e2bb..7816fae 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2699,7 +2699,7 @@
             int64_t timeoutUs;
             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
 
-            if (timeoutUs == 0ll) {
+            if (timeoutUs == 0LL) {
                 PostReplyWithError(replyID, -EAGAIN);
                 break;
             }
@@ -2707,7 +2707,7 @@
             mFlags |= kFlagDequeueInputPending;
             mDequeueInputReplyID = replyID;
 
-            if (timeoutUs > 0ll) {
+            if (timeoutUs > 0LL) {
                 sp<AMessage> timeoutMsg =
                     new AMessage(kWhatDequeueInputTimedOut, this);
                 timeoutMsg->setInt32(
@@ -2773,7 +2773,7 @@
             int64_t timeoutUs;
             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
 
-            if (timeoutUs == 0ll) {
+            if (timeoutUs == 0LL) {
                 PostReplyWithError(replyID, -EAGAIN);
                 break;
             }
@@ -2781,7 +2781,7 @@
             mFlags |= kFlagDequeueOutputPending;
             mDequeueOutputReplyID = replyID;
 
-            if (timeoutUs > 0ll) {
+            if (timeoutUs > 0LL) {
                 sp<AMessage> timeoutMsg =
                     new AMessage(kWhatDequeueOutputTimedOut, this);
                 timeoutMsg->setInt32(
@@ -3042,7 +3042,7 @@
     msg->setSize("index", bufferIndex);
     msg->setSize("offset", 0);
     msg->setSize("size", csd->size());
-    msg->setInt64("timeUs", 0ll);
+    msg->setInt64("timeUs", 0LL);
     msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
     msg->setPointer("errorDetailMsg", &errorDetailMsg);
 
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 20881a4..0f75822 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -372,7 +372,7 @@
     msg->postAndAwaitResponse(&response);
     int64_t timeUs;
     if (!response->findInt64("time-us", &timeUs)) {
-        timeUs = -1ll;
+        timeUs = -1LL;
     }
     return timeUs;
 }
@@ -452,9 +452,9 @@
       mEncoderDataSpace(0),
       mPersistentSurface(persistentSurface),
       mInputBufferTimeOffsetUs(0),
-      mFirstSampleSystemTimeUs(-1ll),
+      mFirstSampleSystemTimeUs(-1LL),
       mPausePending(false),
-      mFirstSampleTimeUs(-1ll),
+      mFirstSampleTimeUs(-1LL),
       mGeneration(0) {
     CHECK(mLooper != NULL);
 
@@ -687,13 +687,13 @@
         size_t bufferIndex = *mAvailEncoderInputIndices.begin();
         mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
 
-        int64_t timeUs = 0ll;
+        int64_t timeUs = 0LL;
         uint32_t flags = 0;
         size_t size = 0;
 
         if (mbuf != NULL) {
             CHECK(mbuf->meta_data().findInt64(kKeyTime, &timeUs));
-            if (mFirstSampleSystemTimeUs < 0ll) {
+            if (mFirstSampleSystemTimeUs < 0LL) {
                 mFirstSampleSystemTimeUs = systemTime() / 1000;
                 if (mPausePending) {
                     mPausePending = false;
@@ -767,7 +767,7 @@
     }
     int64_t startTimeUs;
     if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
-        startTimeUs = -1ll;
+        startTimeUs = -1LL;
     }
 
     if (mStarted) {
@@ -914,7 +914,7 @@
                 if (mIsVideo) {
                     int64_t decodingTimeUs;
                     if (mFlags & FLAG_USE_SURFACE_INPUT) {
-                        if (mFirstSampleSystemTimeUs < 0ll) {
+                        if (mFirstSampleSystemTimeUs < 0LL) {
                             mFirstSampleSystemTimeUs = systemTime() / 1000;
                             if (mPausePending) {
                                 mPausePending = false;
@@ -926,7 +926,7 @@
                         // Timestamp offset is already adjusted in GraphicBufferSource.
                         // GraphicBufferSource is supposed to discard samples
                         // queued before start, and offset timeUs by start time
-                        CHECK_GE(timeUs, 0ll);
+                        CHECK_GE(timeUs, 0LL);
                         // TODO:
                         // Decoding time for surface source is unavailable,
                         // use presentation time for now. May need to move
@@ -954,7 +954,7 @@
                 }
                 mbuf->meta_data().setInt64(kKeyTime, timeUs);
             } else {
-                mbuf->meta_data().setInt64(kKeyTime, 0ll);
+                mbuf->meta_data().setInt64(kKeyTime, 0LL);
                 mbuf->meta_data().setInt32(kKeyIsCodecConfig, true);
             }
             if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
@@ -1081,7 +1081,7 @@
             MetaData *params = static_cast<MetaData *>(obj.get());
             int64_t pauseStartTimeUs = -1;
             if (params == NULL || !params->findInt64(kKeyTime, &pauseStartTimeUs)) {
-                pauseStartTimeUs = -1ll;
+                pauseStartTimeUs = -1LL;
             }
             onPause(pauseStartTimeUs);
         }
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 2c7a4e5..86402ce 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -30,6 +30,7 @@
 #include <media/stagefright/MediaExtractorFactory.h>
 #include <media/IMediaExtractor.h>
 #include <media/IMediaExtractorService.h>
+#include <private/android_filesystem_config.h>
 #include <cutils/properties.h>
 #include <utils/String8.h>
 #include <ziparchive/zip_archive.h>
@@ -106,7 +107,8 @@
     }
 
     MediaExtractor *ex = nullptr;
-    if (creatorVersion == EXTRACTORDEF_VERSION_NDK_V1) {
+    if (creatorVersion == EXTRACTORDEF_VERSION_NDK_V1 ||
+            creatorVersion == EXTRACTORDEF_VERSION_NDK_V2) {
         CMediaExtractor *ret = ((CreatorFunc)creator)(source->wrap(), meta);
         if (meta != nullptr && freeMeta != nullptr) {
             freeMeta(meta);
@@ -184,7 +186,10 @@
 
         void *curCreator = NULL;
         if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V1) {
-            curCreator = (void*) (*it)->def.sniff.v2(
+            curCreator = (void*) (*it)->def.u.v2.sniff(
+                    source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
+        } else if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+            curCreator = (void*) (*it)->def.u.v3.sniff(
                     source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
         }
 
@@ -214,7 +219,8 @@
 void MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin,
         std::list<sp<ExtractorPlugin>> &pluginList) {
     // sanity check check struct version, uuid, name
-    if (plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V1) {
+    if (plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V1 &&
+            plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V2) {
         ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version);
         return;
     }
@@ -394,6 +400,8 @@
     return strcmp(first->def.extractor_name, second->def.extractor_name) < 0;
 }
 
+static std::unordered_set<std::string> gSupportedExtensions;
+
 // static
 void MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) {
     Mutex::Autolock autoLock(gPluginMutex);
@@ -426,9 +434,37 @@
 
     newList->sort(compareFunc);
     gPlugins = newList;
+
+    for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
+        if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+            for (size_t i = 0;; i++) {
+                const char* ext = (*it)->def.u.v3.supported_types[i];
+                if (ext == nullptr) {
+                    break;
+                }
+                gSupportedExtensions.insert(std::string(ext));
+            }
+        }
+    }
+
     gPluginsRegistered = true;
 }
 
+// static
+std::unordered_set<std::string> MediaExtractorFactory::getSupportedTypes() {
+    if (getuid() == AID_MEDIA_EX) {
+        return gSupportedExtensions;
+    }
+    ALOGV("get service manager");
+    sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
+
+    if (binder != 0) {
+        sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder));
+        return mediaExService->getSupportedTypes();
+    }
+    return std::unordered_set<std::string>();
+}
+
 status_t MediaExtractorFactory::dump(int fd, const Vector<String16>&) {
     Mutex::Autolock autoLock(gPluginMutex);
     String8 out;
@@ -445,13 +481,25 @@
         out.append("Available extractors:\n");
         if (gPluginsRegistered) {
             for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
-                out.appendFormat("  %25s: plugin_version(%d), uuid(%s), version(%u), path(%s)\n",
+                out.appendFormat("  %25s: plugin_version(%d), uuid(%s), version(%u), path(%s)",
                         (*it)->def.extractor_name,
                     (*it)->def.def_version,
                         (*it)->uuidString.c_str(),
                         (*it)->def.extractor_version,
                         (*it)->libPath.c_str());
+                if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+                    out.append(", supports: ");
+                    for (size_t i = 0;; i++) {
+                        const char* mime = (*it)->def.u.v3.supported_types[i];
+                        if (mime == nullptr) {
+                            break;
+                        }
+                        out.appendFormat("%s ", mime);
+                    }
+                }
+                out.append("\n");
             }
+            out.append("\n");
         } else {
             out.append("  (no plugins registered)\n");
         }
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index ba14e5d..a3f55da 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -36,7 +36,7 @@
 
 // Maximum late time allowed for a video frame to be rendered. When a video
 // frame arrives later than this number, it will be discarded without rendering.
-static const int64_t kMaxAllowedVideoLateTimeUs = 40000ll;
+static const int64_t kMaxAllowedVideoLateTimeUs = 40000LL;
 
 namespace android {
 
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index 1c1be30..036e79d 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -120,7 +120,7 @@
         if (format->mFormat->findInt64("timeUs", &val64)) {
             meta.setInt64(kKeyTime, val64);
         }
-        if (format->mFormat->findInt64("duration", &val64)) {
+        if (format->mFormat->findInt64("durationUs", &val64)) {
             meta.setInt64(kKeyDuration, val64);
         }
         if (format->mFormat->findInt64("target-time", &val64)) {
@@ -172,6 +172,10 @@
             meta.setData(kKeySEI,
                     MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
         }
+        if (format->mFormat->findBuffer("audio-presentation-info", &valbuf)) {
+            meta.setData(kKeyAudioPresentationInfo,
+                    MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+        }
     } else {
         *buffer = nullptr;
     }
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 7025af7..522c81d 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -440,12 +440,12 @@
     if (mFetching) {
         if (mFinalStatus != OK && mNumRetriesLeft > 0) {
             // We failed this time and will try again in 3 seconds.
-            delayUs = 3000000ll;
+            delayUs = 3000000LL;
         } else {
             delayUs = 0;
         }
     } else {
-        delayUs = 100000ll;
+        delayUs = 100000LL;
     }
 
     (new AMessage(kWhatFetchMore, mReflector))->post(delayUs);
@@ -740,7 +740,7 @@
     }
 
     if (keepAliveSecs >= 0) {
-        mKeepAliveIntervalUs = keepAliveSecs * 1000000ll;
+        mKeepAliveIntervalUs = keepAliveSecs * 1000000LL;
     } else {
         mKeepAliveIntervalUs = kDefaultKeepAliveIntervalUs;
     }
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index f5178dd..83b87d9 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -41,7 +41,7 @@
 
 NuMediaExtractor::Sample::Sample()
     : mBuffer(NULL),
-      mSampleTimeUs(-1ll) {
+      mSampleTimeUs(-1LL) {
 }
 
 NuMediaExtractor::Sample::Sample(MediaBufferBase *buffer, int64_t timeUs)
@@ -50,8 +50,8 @@
 }
 
 NuMediaExtractor::NuMediaExtractor()
-    : mTotalBitrate(-1ll),
-      mDurationUs(-1ll) {
+    : mTotalBitrate(-1LL),
+      mDurationUs(-1LL) {
 }
 
 NuMediaExtractor::~NuMediaExtractor() {
@@ -209,8 +209,8 @@
         return ERROR_UNSUPPORTED;
     }
 
-    mTotalBitrate = 0ll;
-    mDurationUs = -1ll;
+    mTotalBitrate = 0LL;
+    mDurationUs = -1LL;
 
     for (size_t i = 0; i < mImpl->countTracks(); ++i) {
         sp<MetaData> meta = mImpl->getTrackMetaData(i);
@@ -225,8 +225,8 @@
             CHECK(meta->findCString(kKeyMIMEType, &mime));
             ALOGV("track of type '%s' does not publish bitrate", mime);
 
-            mTotalBitrate = -1ll;
-        } else if (mTotalBitrate >= 0ll) {
+            mTotalBitrate = -1LL;
+        } else if (mTotalBitrate >= 0LL) {
             mTotalBitrate += bitrate;
         }
 
@@ -503,7 +503,7 @@
     }
 
     MediaSource::ReadOptions options;
-    if (seekTimeUs >= 0ll) {
+    if (seekTimeUs >= 0LL) {
         options.setSeekTo(seekTimeUs, mode);
         info->mFinalResult = OK;
         releaseTrackSamples(info);
@@ -768,7 +768,7 @@
 
     off64_t size;
     if (mDurationUs > 0 && mDataSource->getSize(&size) == OK) {
-        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
+        *bitrate = size * 8000000LL / mDurationUs;  // in bits/sec
         return true;
     }
 
@@ -795,30 +795,34 @@
 }
 
 // Return OK if we have received an audio presentation info.
+// Return ERROR_END_OF_STREAM if no tracks are available.
 // Return ERROR_UNSUPPORTED if the track has no audio presentation.
 // Return INVALID_OPERATION if audio presentation metadata version does not match.
 status_t NuMediaExtractor::getAudioPresentations(
-        size_t trackIndex, AudioPresentationCollection *presentations) const {
+        size_t trackIndex, AudioPresentationCollection *presentations) {
     Mutex::Autolock autoLock(mLock);
-
-    if (mImpl == NULL) {
-        return -EINVAL;
+    ssize_t minIndex = fetchAllTrackSamples();
+    if (minIndex < 0) {
+        return ERROR_END_OF_STREAM;
     }
+    for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
+        TrackInfo *info = &mSelectedTracks.editItemAt(i);
 
-    if (trackIndex >= mImpl->countTracks()) {
-        return -ERANGE;
+        if (info->mTrackIndex == trackIndex) {
+            sp<MetaData> meta = new MetaData(info->mSamples.begin()->mBuffer->meta_data());
+
+            uint32_t type;
+            const void *data;
+            size_t size;
+            if (meta != NULL && meta->findData(kKeyAudioPresentationInfo, &type, &data, &size)) {
+                std::istringstream inStream(std::string(static_cast<const char*>(data), size));
+                return deserializeAudioPresentations(&inStream, presentations);
+            }
+            ALOGV("Track %zu does not contain any audio presentation", trackIndex);
+            return ERROR_UNSUPPORTED;
+        }
     }
-
-    sp<MetaData> meta = mImpl->getTrackMetaData(trackIndex);
-
-    uint32_t type;
-    const void *data;
-    size_t size;
-    if (meta != NULL && meta->findData(kKeyAudioPresentationInfo, &type, &data, &size)) {
-        std::istringstream inStream(std::string(static_cast<const char*>(data), size));
-        return deserializeAudioPresentations(&inStream, presentations);
-    }
-    ALOGE("Source does not contain any audio presentation");
+    ALOGV("Source does not contain any audio presentation");
     return ERROR_UNSUPPORTED;
 }
 
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 17187a8..cf4edae 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -22,6 +22,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#include <media/stagefright/MediaExtractorFactory.h>
 #include <media/stagefright/StagefrightMediaScanner.h>
 
 #include <media/IMediaHTTPService.h>
@@ -34,25 +35,16 @@
 
 StagefrightMediaScanner::~StagefrightMediaScanner() {}
 
-static bool FileHasAcceptableExtension(const char *extension) {
-    static const char *kValidExtensions[] = {
-        ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
-        ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
-        ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
-        ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
-        ".avi", ".mpeg", ".mpg", ".awb", ".mpga", ".mov",
-        ".m4v", ".oga", ".m4r"
-    };
-    static const size_t kNumValidExtensions =
-        sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
+static std::unordered_set<std::string> gSupportedExtensions;
 
-    for (size_t i = 0; i < kNumValidExtensions; ++i) {
-        if (!strcasecmp(extension, kValidExtensions[i])) {
-            return true;
-        }
+static bool FileHasAcceptableExtension(const char *extension) {
+
+    if (gSupportedExtensions.empty()) {
+        // get the list from the service
+        gSupportedExtensions = MediaExtractorFactory::getSupportedTypes();
     }
 
-    return false;
+    return  gSupportedExtensions.count(std::string(extension + 1)) != 0;
 }
 
 MediaScanResult StagefrightMediaScanner::processFile(
@@ -135,6 +127,8 @@
         { "colorstandard", METADATA_KEY_COLOR_STANDARD },
         { "colortransfer", METADATA_KEY_COLOR_TRANSFER },
         { "colorrange", METADATA_KEY_COLOR_RANGE },
+        { "samplerate", METADATA_KEY_SAMPLERATE },
+        { "bitspersample", METADATA_KEY_BITS_PER_SAMPLE },
     };
     static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
 
diff --git a/media/libstagefright/ThrottledSource.cpp b/media/libstagefright/ThrottledSource.cpp
index 7496752..49cea9e 100644
--- a/media/libstagefright/ThrottledSource.cpp
+++ b/media/libstagefright/ThrottledSource.cpp
@@ -51,7 +51,7 @@
     // How long would it have taken to transfer everything we ever
     // transferred given the limited bandwidth.
     int64_t durationUs =
-        mTotalTransferred * 1000000ll / mBandwidthLimitBytesPerSecond;
+        mTotalTransferred * 1000000LL / mBandwidthLimitBytesPerSecond;
 
     int64_t whenUs = mStartTimeUs + durationUs;
 
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 163cd05..49e485a 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -2020,7 +2020,7 @@
 
 HLSTime::HLSTime(const sp<AMessage>& meta) :
     mSeq(-1),
-    mTimeUs(-1ll),
+    mTimeUs(-1LL),
     mMeta(meta) {
     if (meta != NULL) {
         CHECK(meta->findInt32("discontinuitySeq", &mSeq));
@@ -2029,7 +2029,7 @@
 }
 
 int64_t HLSTime::getSegmentTimeUs() const {
-    int64_t segmentStartTimeUs = -1ll;
+    int64_t segmentStartTimeUs = -1LL;
     if (mMeta != NULL) {
         CHECK(mMeta->findInt64("segmentStartTimeUs", &segmentStartTimeUs));
 
diff --git a/media/libstagefright/VideoFrameScheduler2.cpp b/media/libstagefright/VideoFrameScheduler2.cpp
index e02ae7d..fc76904 100644
--- a/media/libstagefright/VideoFrameScheduler2.cpp
+++ b/media/libstagefright/VideoFrameScheduler2.cpp
@@ -36,7 +36,7 @@
 
 namespace android {
 
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr);
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr);
 
 /* ======================================================================= */
 /*                               VsyncTracker                              */
@@ -46,19 +46,19 @@
 public:
     VsyncTracker();
     ~VsyncTracker() {}
-    long getVsyncPeriod();
-    long getVsyncTime(long periodOffset);
-    void addSample(long timestamp);
+    nsecs_t getVsyncPeriod();
+    nsecs_t getVsyncTime(nsecs_t periodOffset);
+    void addSample(nsecs_t timestamp);
 
 private:
     static const int kMaxSamples = 32;
     static const int kMinSamplesForUpdate = 6;
     int mNumSamples;
     int mFirstSample;
-    long mReferenceTime;
-    long mPhase;
-    long mPeriod;
-    long mTimestampSamples[kMaxSamples];
+    nsecs_t mReferenceTime;
+    nsecs_t mPhase;
+    nsecs_t mPeriod;
+    nsecs_t mTimestampSamples[kMaxSamples];
     Mutex mLock;
 
     void updateModelLocked();
@@ -75,19 +75,39 @@
     }
 }
 
-long VsyncTracker::getVsyncPeriod() {
+nsecs_t VsyncTracker::getVsyncPeriod() {
     Mutex::Autolock dataLock(mLock);
     return mPeriod;
 }
 
-long VsyncTracker::getVsyncTime(long periodOffset) {
+nsecs_t VsyncTracker::getVsyncTime(nsecs_t periodOffset) {
     Mutex::Autolock dataLock(mLock);
-    const long now = systemTime();
-    long phase = mReferenceTime + mPhase;
-    return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
+    const nsecs_t now = systemTime();
+    nsecs_t phase = mReferenceTime + mPhase;
+
+    // result = (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase
+    // prevent overflow
+    nsecs_t result = (now - phase) / mPeriod;
+    if (result > LONG_LONG_MAX - periodOffset - 1) {
+        return LONG_LONG_MAX;
+    } else {
+        result += periodOffset + 1;
+    }
+    if (result > LONG_LONG_MAX / mPeriod) {
+        return LONG_LONG_MAX;
+    } else {
+        result *= mPeriod;
+    }
+    if (result > LONG_LONG_MAX - phase) {
+        return LONG_LONG_MAX;
+    } else {
+        result += phase;
+    }
+
+    return result;
 }
 
-void VsyncTracker::addSample(long timestamp) {
+void VsyncTracker::addSample(nsecs_t timestamp) {
     Mutex::Autolock dataLock(mLock);
     if (mNumSamples == 0) {
         mPhase = 0;
@@ -107,17 +127,17 @@
     if (mNumSamples < kMinSamplesForUpdate) {
         return;
     }
-    long durationSum = 0;
-    long minDuration = LONG_MAX;
-    long maxDuration = 0;
+    nsecs_t durationSum = 0;
+    nsecs_t minDuration = LONG_MAX;
+    nsecs_t maxDuration = 0;
 
     for (int i = 1; i < mNumSamples; i++) {
         int idx = (mFirstSample + i) % kMaxSamples;
         int prev = (idx + kMaxSamples - 1) % kMaxSamples;
         long duration = mTimestampSamples[idx] - mTimestampSamples[prev];
         durationSum += duration;
-        minDuration = min(minDuration, duration);
-        maxDuration = max(maxDuration, duration);
+        if (minDuration > duration) { minDuration = duration; }
+        if (maxDuration < duration) { maxDuration = duration; }
     }
 
     durationSum -= (minDuration + maxDuration);
@@ -154,9 +174,9 @@
 /*                                   JNI                                   */
 /* ======================================================================= */
 
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr) {
-    static const long kOneMillisecInNanosec = 1000000;
-    static const long kOneSecInNanosec = kOneMillisecInNanosec * 1000;
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr) {
+    static const nsecs_t kOneMillisecInNanosec = 1000000;
+    static const nsecs_t kOneSecInNanosec = kOneMillisecInNanosec * 1000;
 
     JNIEnv *env = JavaVMHelper::getJNIEnv();
     jclass jDisplayManagerGlobalCls = env->FindClass(
@@ -178,19 +198,19 @@
 
     jmethodID jGetRefreshRate = env->GetMethodID(jDisplayCls, "getRefreshRate", "()F");
     jfloat javaRefreshRate = env->CallFloatMethod(javaDisplayObj, jGetRefreshRate);
-    long vsyncPeriod = (long) (kOneSecInNanosec / (float) javaRefreshRate);
+    nsecs_t vsyncPeriod = (nsecs_t) (kOneSecInNanosec / (float) javaRefreshRate);
 
     jmethodID jGetAppVsyncOffsetNanos = env->GetMethodID(
             jDisplayCls, "getAppVsyncOffsetNanos", "()J");
     jlong javaAppVsyncOffset = env->CallLongMethod(javaDisplayObj, jGetAppVsyncOffsetNanos);
-    *appVsyncOffsetPtr = (long) javaAppVsyncOffset;
+    *appVsyncOffsetPtr = (nsecs_t) javaAppVsyncOffset;
 
     jmethodID jGetPresentationDeadlineNanos = env->GetMethodID(
             jDisplayCls, "getPresentationDeadlineNanos", "()J");
     jlong javaPresentationDeadline = env->CallLongMethod(
             javaDisplayObj, jGetPresentationDeadlineNanos);
 
-    *sfVsyncOffsetPtr = vsyncPeriod - ((long) javaPresentationDeadline - kOneMillisecInNanosec);
+    *sfVsyncOffsetPtr = vsyncPeriod - ((nsecs_t) javaPresentationDeadline - kOneMillisecInNanosec);
 }
 
 /* ======================================================================= */
diff --git a/media/libstagefright/bqhelper/FrameDropper.cpp b/media/libstagefright/bqhelper/FrameDropper.cpp
index d2a2473..387ac5a 100644
--- a/media/libstagefright/bqhelper/FrameDropper.cpp
+++ b/media/libstagefright/bqhelper/FrameDropper.cpp
@@ -35,7 +35,7 @@
 
 status_t FrameDropper::setMaxFrameRate(float maxFrameRate) {
     if (maxFrameRate < 0) {
-        mMinIntervalUs = -1ll;
+        mMinIntervalUs = -1LL;
         return OK;
     }
 
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index 8c1da76..a4374c9 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -292,20 +292,20 @@
     mSuspended(false),
     mLastFrameTimestampUs(-1),
     mStopTimeUs(-1),
-    mLastActionTimeUs(-1ll),
-    mSkipFramesBeforeNs(-1ll),
-    mFrameRepeatIntervalUs(-1ll),
+    mLastActionTimeUs(-1LL),
+    mSkipFramesBeforeNs(-1LL),
+    mFrameRepeatIntervalUs(-1LL),
     mRepeatLastFrameGeneration(0),
     mOutstandingFrameRepeatCount(0),
     mFrameRepeatBlockedOnCodecBuffer(false),
     mFps(-1.0),
     mCaptureFps(-1.0),
-    mBaseCaptureUs(-1ll),
-    mBaseFrameUs(-1ll),
+    mBaseCaptureUs(-1LL),
+    mBaseFrameUs(-1LL),
     mFrameCount(0),
-    mPrevCaptureUs(-1ll),
-    mPrevFrameUs(-1ll),
-    mInputBufferTimeOffsetUs(0ll) {
+    mPrevCaptureUs(-1LL),
+    mPrevFrameUs(-1LL),
+    mInputBufferTimeOffsetUs(0LL) {
     ALOGV("GraphicBufferSource");
 
     String8 name("GraphicBufferSource");
@@ -392,7 +392,7 @@
         submitEndOfInputStream_l();
     }
 
-    if (mFrameRepeatIntervalUs > 0ll && mLooper == NULL) {
+    if (mFrameRepeatIntervalUs > 0LL && mLooper == NULL) {
         mReflector = new AHandlerReflector<GraphicBufferSource>(this);
 
         mLooper = new ALooper;
@@ -655,7 +655,7 @@
 
     // only submit sample if start time is unspecified, or sample
     // is queued after the specified start time
-    if (mSkipFramesBeforeNs < 0ll || item.mTimestampNs >= mSkipFramesBeforeNs) {
+    if (mSkipFramesBeforeNs < 0LL || item.mTimestampNs >= mSkipFramesBeforeNs) {
         // if start time is set, offset time stamp by start time
         if (mSkipFramesBeforeNs > 0) {
             item.mTimestampNs -= mSkipFramesBeforeNs;
@@ -677,7 +677,7 @@
     } else {
         // Don't set the last buffer id if we're not repeating,
         // we'll be holding on to the last buffer for nothing.
-        if (mFrameRepeatIntervalUs > 0ll) {
+        if (mFrameRepeatIntervalUs > 0LL) {
             setLatestBuffer_l(item);
         }
         ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d",
@@ -755,7 +755,7 @@
             && (mFps > 2 * mCaptureFps
             || mCaptureFps > 2 * mFps)) {
         // Time lapse or slow motion mode
-        if (mPrevCaptureUs < 0ll) {
+        if (mPrevCaptureUs < 0LL) {
             // first capture
             mPrevCaptureUs = mBaseCaptureUs = timeUs;
             // adjust the first sample timestamp.
@@ -1123,19 +1123,19 @@
         mSuspended = false;
         mEndOfStream = false;
         mEndOfStreamSent = false;
-        mSkipFramesBeforeNs = -1ll;
+        mSkipFramesBeforeNs = -1LL;
         mFrameDropper.clear();
-        mFrameRepeatIntervalUs = -1ll;
+        mFrameRepeatIntervalUs = -1LL;
         mRepeatLastFrameGeneration = 0;
         mOutstandingFrameRepeatCount = 0;
         mLatestBuffer.mBuffer.reset();
         mFrameRepeatBlockedOnCodecBuffer = false;
         mFps = -1.0;
         mCaptureFps = -1.0;
-        mBaseCaptureUs = -1ll;
-        mBaseFrameUs = -1ll;
-        mPrevCaptureUs = -1ll;
-        mPrevFrameUs = -1ll;
+        mBaseCaptureUs = -1LL;
+        mBaseFrameUs = -1LL;
+        mPrevCaptureUs = -1LL;
+        mPrevFrameUs = -1LL;
         mFrameCount = 0;
         mInputBufferTimeOffsetUs = 0;
         mStopTimeUs = -1;
@@ -1201,7 +1201,7 @@
 
     Mutex::Autolock autoLock(mMutex);
 
-    if (mExecuting || repeatAfterUs <= 0ll) {
+    if (mExecuting || repeatAfterUs <= 0LL) {
         return INVALID_OPERATION;
     }
 
@@ -1213,7 +1213,7 @@
     Mutex::Autolock autoLock(mMutex);
 
     // timeOffsetUs must be negative for adjustment.
-    if (timeOffsetUs >= 0ll) {
+    if (timeOffsetUs >= 0LL) {
         return INVALID_OPERATION;
     }
 
@@ -1247,7 +1247,7 @@
 
     mSkipFramesBeforeNs =
             (skipFramesBeforeUs > 0 && skipFramesBeforeUs <= INT64_MAX / 1000) ?
-            (skipFramesBeforeUs * 1000) : -1ll;
+            (skipFramesBeforeUs * 1000) : -1LL;
 
     return OK;
 }
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index d393c7a..41bc16c 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -738,7 +738,7 @@
                 } else {
                     int64_t currentTime = mBufferTimestamps.top();
                     currentTime += mStreamInfo->aacSamplesPerFrame *
-                            1000000ll / mStreamInfo->aacSampleRate;
+                            1000000LL / mStreamInfo->aacSampleRate;
                     mBufferTimestamps.add(currentTime);
                 }
             } else {
@@ -989,7 +989,7 @@
                         // adjust/interpolate next time stamp
                         *currentBufLeft -= decodedSize;
                         *nextTimeStamp += mStreamInfo->aacSamplesPerFrame *
-                                1000000ll / mStreamInfo->aacSampleRate;
+                                1000000LL / mStreamInfo->aacSampleRate;
                         ALOGV("adjusted nextTimeStamp/size to %lld/%d",
                                 (long long) *nextTimeStamp, *currentBufLeft);
                     } else {
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 96e668e..6e437cf 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -63,7 +63,7 @@
       mInputSize(0),
       mInputFrame(NULL),
       mAllocatedFrameSize(0),
-      mInputTimeUs(-1ll),
+      mInputTimeUs(-1LL),
       mSawInputEOS(false),
       mSignalledError(false) {
     initPorts();
@@ -587,7 +587,7 @@
             // "Time" on the input buffer has in effect advanced by the
             // number of audio frames we just advanced nOffset by.
             inHeader->nTimeStamp +=
-                (copy * 1000000ll / mSampleRate)
+                (copy * 1000000LL / mSampleRate)
                     / (mNumChannels * sizeof(int16_t));
 
             if (inHeader->nFilledLen == 0) {
@@ -725,7 +725,7 @@
     mAllocatedFrameSize = 0;
 
     mSentCodecSpecificData = false;
-    mInputTimeUs = -1ll;
+    mInputTimeUs = -1LL;
     mSawInputEOS = false;
     mSignalledError = false;
 }
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index b7e84ec..34dd011 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -505,7 +505,7 @@
 
             outHeader->nTimeStamp =
                 mAnchorTimeUs
-                    + (mNumSamplesOutput * 1000000ll) / kSampleRateNB;
+                    + (mNumSamplesOutput * 1000000LL) / kSampleRateNB;
 
             mNumSamplesOutput += kNumSamplesPerFrameNB;
         } else {
@@ -513,7 +513,7 @@
 
             outHeader->nTimeStamp =
                 mAnchorTimeUs
-                    + (mNumSamplesOutput * 1000000ll) / kSampleRateWB;
+                    + (mNumSamplesOutput * 1000000LL) / kSampleRateWB;
 
             mNumSamplesOutput += kNumSamplesPerFrameWB;
         }
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index f97c44f..85ab64e 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -49,7 +49,7 @@
       mBitRate(0),
       mMode(MR475),
       mInputSize(0),
-      mInputTimeUs(-1ll),
+      mInputTimeUs(-1LL),
       mSawInputEOS(false),
       mSignalledError(false) {
     initPorts();
@@ -340,7 +340,7 @@
             // "Time" on the input buffer has in effect advanced by the
             // number of audio frames we just advanced nOffset by.
             inHeader->nTimeStamp +=
-                (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+                (copy * 1000000LL / kSampleRate) / sizeof(int16_t);
 
             if (inHeader->nFilledLen == 0) {
                 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index a644b66..7fb8a4c 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -50,7 +50,7 @@
       mBitRate(0),
       mMode(VOAMRWB_MD66),
       mInputSize(0),
-      mInputTimeUs(-1ll),
+      mInputTimeUs(-1LL),
       mSawInputEOS(false),
       mSignalledError(false) {
     initPorts();
@@ -387,7 +387,7 @@
             // "Time" on the input buffer has in effect advanced by the
             // number of audio frames we just advanced nOffset by.
             inHeader->nTimeStamp +=
-                (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+                (copy * 1000000LL / kSampleRate) / sizeof(int16_t);
 
             if (inHeader->nFilledLen == 0) {
                 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 3924fc2..bf5e243 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -607,7 +607,7 @@
             timeTaken = mTimeEnd - mTimeStart;
 
             ALOGV("timeTaken=%6lldus delay=%6lldus numBytes=%6d",
-                    (long long) (timeTaken / 1000ll), (long long) (timeDelay / 1000ll),
+                    (long long) (timeTaken / 1000LL), (long long) (timeDelay / 1000LL),
                    s_dec_op.u4_num_bytes_consumed);
             if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
                 mFlushNeeded = true;
diff --git a/media/libstagefright/codecs/flac/dec/Android.bp b/media/libstagefright/codecs/flac/dec/Android.bp
index 1674cb2..3d4a44f 100644
--- a/media/libstagefright/codecs/flac/dec/Android.bp
+++ b/media/libstagefright/codecs/flac/dec/Android.bp
@@ -29,7 +29,6 @@
     },
 
     shared_libs: [
-        "libcutils",
         "liblog",
         "libstagefright_flacdec",
         "libstagefright_omx",
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
index 4db0060..842a7ce 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
@@ -89,12 +89,12 @@
     def.eDir = OMX_DirOutput;
     def.nBufferCountMin = kNumOutputBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = 4096 * FLACDecoder::kMaxChannels;
+    def.nBufferSize = kNumSamplesPerFrame * FLACDecoder::kMaxChannels * sizeof(float);
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
     def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 2;
+    def.nBufferAlignment = sizeof(float);
 
     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
     def.format.audio.pNativeRender = NULL;
@@ -173,7 +173,7 @@
                 flacParams->nChannels = mStreamInfo.channels;
                 flacParams->nSampleRate = mStreamInfo.sample_rate;
             } else {
-                flacParams->nChannels = 1;
+                flacParams->nChannels = 2;
                 flacParams->nSampleRate = 44100;
             }
 
@@ -195,10 +195,10 @@
                 return OMX_ErrorBadPortIndex;
             }
 
-            pcmParams->eNumData = OMX_NumericalDataSigned;
+            pcmParams->eNumData = mNumericalData;
             pcmParams->eEndian = OMX_EndianBig;
             pcmParams->bInterleaved = OMX_TRUE;
-            pcmParams->nBitPerSample = 16;
+            pcmParams->nBitPerSample = mBitsPerSample;
             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -211,7 +211,7 @@
                 pcmParams->nChannels = mStreamInfo.channels;
                 pcmParams->nSamplingRate = mStreamInfo.sample_rate;
             } else {
-                pcmParams->nChannels = 1;
+                pcmParams->nChannels = 2;
                 pcmParams->nSamplingRate = 44100;
             }
 
@@ -281,6 +281,19 @@
                 return OMX_ErrorBadPortIndex;
             }
 
+            if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
+                mNumericalData = OMX_NumericalDataFloat;
+                mBitsPerSample = 32;
+            } else if (pcmParams->eNumData == OMX_NumericalDataSigned
+                     && pcmParams->nBitPerSample == 16) {
+                mNumericalData = OMX_NumericalDataSigned;
+                mBitsPerSample = 16;
+            } else {
+                ALOGE("Invalid eNumData %d, nBitsPerSample %d",
+                        pcmParams->eNumData, pcmParams->nBitPerSample);
+                return OMX_ErrorUndefined;
+            }
+
             return OMX_ErrorNone;
         }
 
@@ -301,11 +314,13 @@
     List<BufferInfo *> &inQueue = getPortQueue(0);
     List<BufferInfo *> &outQueue = getPortQueue(1);
 
+    const bool outputFloat = mNumericalData == OMX_NumericalDataFloat;
+
     ALOGV("onQueueFilled %d/%d:", inQueue.empty(), outQueue.empty());
     while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mFinishedDecoder) {
         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
-        int16_t *outBuffer = reinterpret_cast<int16_t *>(outHeader->pBuffer + outHeader->nOffset);
+        void *outBuffer = reinterpret_cast<void *>(outHeader->pBuffer + outHeader->nOffset);
         size_t outBufferSize = outHeader->nAllocLen - outHeader->nOffset;
         int64_t timeStamp = 0;
 
@@ -374,7 +389,7 @@
             }
 
             status_t decoderErr = mFLACDecoder->decodeOneFrame(
-                    inBuffer, inBufferLength, outBuffer, &outBufferSize);
+                    inBuffer, inBufferLength, outBuffer, &outBufferSize, outputFloat);
             if (decoderErr != OK) {
                 ALOGE("onQueueFilled: FLACDecoder decodeOneFrame returns error %d", decoderErr);
                 mSignalledError = true;
@@ -393,7 +408,9 @@
                 continue;
             }
         } else if (mSawInputEOS) {
-            status_t decoderErr = mFLACDecoder->decodeOneFrame(NULL, 0, outBuffer, &outBufferSize);
+            status_t decoderErr = mFLACDecoder->decodeOneFrame(
+                    nullptr /* inBuffer */, 0 /* inBufferLen */,
+                    outBuffer, &outBufferSize, outputFloat);
             mFinishedDecoder = true;
             if (decoderErr != OK) {
                 ALOGE("onQueueFilled: FLACDecoder finish returns error %d", decoderErr);
@@ -456,7 +473,8 @@
             mOutputPortSettingsChange = AWAITING_ENABLED;
             PortInfo *info = editPortInfo(1 /* portIndex */);
             if (!info->mDef.bEnabled) {
-                info->mDef.nBufferSize = mStreamInfo.max_blocksize * mStreamInfo.channels * 2;
+                info->mDef.nBufferSize =
+                        mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(float);
             }
             break;
         }
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
index b63f7ad..ba02074 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
@@ -45,10 +45,14 @@
     virtual void onReset() override;
 
 private:
+    static constexpr unsigned int kNumSamplesPerFrame = 2048; // adjusted based on stream.
+
     enum {
         kNumInputBuffers   = 4,
         kNumOutputBuffers  = 4,
     };
+    OMX_NUMERICALDATATYPE mNumericalData = OMX_NumericalDataSigned;
+    OMX_U32 mBitsPerSample = 16;
 
     FLACDecoder *mFLACDecoder;
     FLAC__StreamMetadata_StreamInfo mStreamInfo;
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index 9b696da..b32ab08 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -28,7 +28,10 @@
     ],
 
     header_libs: ["libbase_headers"],
-    static_libs: ["libFLAC"],
+    static_libs: [
+        "libaudioutils",
+        "libFLAC",
+    ],
 
     name: "libstagefright_soft_flacenc",
     vendor_available: true,
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 955f211..3add006 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -20,7 +20,7 @@
 #include <utils/Log.h>
 
 #include "SoftFlacEncoder.h"
-
+#include <audio_utils/primitives.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaDefs.h>
 
@@ -75,7 +75,9 @@
     }
 
     if (!mSignalledError) { // no use allocating input buffer if we had an error above
-        mInputBufferPcm32 = (FLAC__int32*) malloc(sizeof(FLAC__int32) * 2 * kMaxNumSamplesPerFrame);
+        // 2x the pcm16 samples can exist with the same size as pcmFloat samples.
+        mInputBufferPcm32 = (FLAC__int32*) malloc(
+                sizeof(FLAC__int32) * kNumSamplesPerFrame * kMaxChannels * 2);
         if (mInputBufferPcm32 == NULL) {
             ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error allocating internal input buffer", name);
             mSignalledError = true;
@@ -115,14 +117,14 @@
     // configure input port of the encoder
     def.nPortIndex = 0;
     def.eDir = OMX_DirInput;
-    def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
+    def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
     def.nBufferSize = kMaxInputBufferSize;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
     def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 2;
+    def.nBufferAlignment = sizeof(float);
 
     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
     def.format.audio.pNativeRender = NULL;
@@ -134,7 +136,7 @@
     // configure output port of the encoder
     def.nPortIndex = 1;
     def.eDir = OMX_DirOutput;
-    def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
+    def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
     def.nBufferSize = kMaxOutputBufferSize;
     def.bEnabled = OMX_TRUE;
@@ -193,10 +195,10 @@
                 return OMX_ErrorUndefined;
             }
 
-            pcmParams->eNumData = OMX_NumericalDataSigned;
+            pcmParams->eNumData = mNumericalData;
             pcmParams->eEndian = OMX_EndianBig;
             pcmParams->bInterleaved = OMX_TRUE;
-            pcmParams->nBitPerSample = 16;
+            pcmParams->nBitPerSample = mBitsPerSample;
             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -270,12 +272,26 @@
                 return OMX_ErrorUndefined;
             }
 
-            if (pcmParams->nChannels < 1 || pcmParams->nChannels > 2) {
+            if (pcmParams->nChannels < 1 || pcmParams->nChannels > kMaxChannels) {
                 return OMX_ErrorUndefined;
             }
 
             mNumChannels = pcmParams->nChannels;
             mSampleRate = pcmParams->nSamplingRate;
+
+            if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
+                mNumericalData = OMX_NumericalDataFloat;
+                mBitsPerSample = 32;
+            } else if (pcmParams->eNumData == OMX_NumericalDataSigned
+                     && pcmParams->nBitPerSample == 16) {
+                mNumericalData = OMX_NumericalDataSigned;
+                mBitsPerSample = 16;
+            } else {
+                ALOGE("%s: invalid eNumData %d, nBitsPerSample %d",
+                        __func__, pcmParams->eNumData, pcmParams->nBitPerSample);
+                return OMX_ErrorUndefined;
+            }
+
             ALOGV("will encode %d channels at %dHz", mNumChannels, mSampleRate);
 
             return configureEncoder();
@@ -356,6 +372,10 @@
     List<BufferInfo *> &inQueue = getPortQueue(0);
     List<BufferInfo *> &outQueue = getPortQueue(1);
 
+    const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
+    const size_t sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
+    const size_t frameSize = sampleSize * mNumChannels;
+
     FLAC__bool ok = true;
 
     while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mSentOutputEOS) {
@@ -381,13 +401,21 @@
             mEncoderReturnedNbBytes = 0;
             mCurrentInputTimeStamp = inHeader->nTimeStamp;
 
-            const unsigned nbInputFrames = inHeader->nFilledLen / (2 * mNumChannels);
-            const unsigned nbInputSamples = inHeader->nFilledLen / 2;
-            const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer);
+            const unsigned nbInputFrames = inHeader->nFilledLen / frameSize;
+            const unsigned nbInputSamples = inHeader->nFilledLen / sampleSize;
 
-            CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame);
-            for (unsigned i=0 ; i < nbInputSamples ; i++) {
-                mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+            if (inputFloat) {
+                CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels);
+                const float * const pcmFloat = reinterpret_cast<float *>(inHeader->pBuffer);
+                 memcpy_to_q8_23_from_float_with_clamp(
+                         mInputBufferPcm32, pcmFloat, nbInputSamples);
+            } else {
+                // note nbInputSamples may be 2x as large for pcm16 data.
+                CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels * 2);
+                const int16_t * const pcm16 = reinterpret_cast<int16_t *>(inHeader->pBuffer);
+                for (unsigned i = 0; i < nbInputSamples; ++i) {
+                    mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+                }
             }
             ALOGV(" about to encode %u samples per channel", nbInputFrames);
             ok = FLAC__stream_encoder_process_interleaved(
@@ -526,10 +554,12 @@
         return OMX_ErrorInvalidState;
     }
 
+    const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
+    const int codecBitsPerSample = inputFloat ? 24 : 16;
     FLAC__bool ok = true;
     ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels);
     ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate);
-    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
+    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, codecBitsPerSample);
     ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder,
             (unsigned)mCompressionLevel);
     ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
index 64a6b1e..722fc13 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
@@ -45,8 +45,10 @@
 
 private:
     const unsigned int kNumBuffers = 2;
-    const unsigned int kMaxNumSamplesPerFrame = 1152;
-    const unsigned int kMaxInputBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t) * 2;
+    static constexpr unsigned int kMaxChannels = 2;
+    static constexpr unsigned int kNumSamplesPerFrame = 1152;
+    static constexpr unsigned int kMaxInputBufferSize =
+            kNumSamplesPerFrame * kMaxChannels * sizeof(float);
     const unsigned int kMaxOutputBufferSize = 65536;    //TODO check if this can be reduced
 
     bool mSignalledError;
@@ -54,6 +56,8 @@
     OMX_U32 mNumChannels;
     OMX_U32 mSampleRate;
     OMX_U32 mCompressionLevel;
+    OMX_NUMERICALDATATYPE mNumericalData = OMX_NumericalDataSigned;
+    OMX_U32 mBitsPerSample = 16;
 
     // should the data received by the callback be written to the output port
     bool        mEncoderWriteData;
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 7a4cca9..c14983a 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -372,7 +372,7 @@
 
         int32_t step = 4 << segment;
 
-        int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33;
+        int32_t abs = (0x80L << exponent) + step * mantissa + step / 2 - 4 * 33;
 
         *out++ = (x < 0x80) ? -abs : abs;
     }
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
index 53149c1..ecc3217 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
@@ -377,15 +377,15 @@
 /*  In/out   : Nr, B, Rr                                                    */
 /*  Return   : Void                                                         */
 /*  Modified :                                                              */
+/* Input argument "video" is guaranteed non-null by caller                  */
 /* ======================================================================== */
 
-
 PV_STATUS RC_UpdateBuffer(VideoEncData *video, Int currLayer, Int num_skip)
 {
     rateControl *rc  = video->rc[currLayer];
     MultiPass   *pMP = video->pMP[currLayer];
 
-    if (video == NULL || rc == NULL || pMP == NULL)
+    if (rc == NULL || pMP == NULL)
         return PV_FAIL;
 
     rc->VBV_fullness   -= (Int)(rc->bitrate / rc->framerate * num_skip); //rc[currLayer]->Rp;
@@ -524,6 +524,7 @@
 /*  In/out   : rc->T                                                                */
 /*  Return   : Void                                                                 */
 /*  Modified :                                                                      */
+/* Input argument "input" is guaranteed non-null by caller                          */
 /* ================================================================================ */
 
 void targetBitCalculation(void *input)
@@ -537,7 +538,7 @@
     Int diff_counter_BTsrc, diff_counter_BTdst, prev_counter_diff, curr_counter_diff, bound;
     /* BT = Bit Transfer, for pMP->counter_BTsrc, pMP->counter_BTdst */
 
-    if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+    if (currVol == NULL || pMP == NULL || rc == NULL)
         return;
 
     /* some stuff about frame dropping remained here to be done because pMP cannot be inserted into updateRateControl()*/
@@ -693,6 +694,7 @@
 /*  In/out   : rc->T and rc->Qc                                                     */
 /*  Return   : Void                                                                 */
 /*  Modified :                                                                      */
+/*  Input argument "input" is guaranteed non-null by caller                         */
 /* ================================================================================ */
 
 /* Mad based variable bit allocation + QP calculation with a new quadratic method */
@@ -708,7 +710,7 @@
     float curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP;
 
 
-    if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+    if (currVol == NULL || pMP == NULL || rc == NULL)
         return;
 
     /* Mad based variable bit allocation */
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index cd984f0..80083f7 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -407,7 +407,7 @@
         }
 
         outHeader->nTimeStamp =
-            mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
+            mAnchorTimeUs + (mNumFramesOutput * 1000000LL) / mSamplingRate;
 
         if (inHeader) {
             CHECK_GE((int32_t)inHeader->nFilledLen, mConfig->inputBufferUsedLength);
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index 942f850..4f61aa8 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -430,6 +430,15 @@
                 return;
             }
 
+            if (size < sizeof(int64_t)) {
+                // The 2nd and 3rd input buffer are expected to contain
+                //  an int64_t (see below), so make sure we get at least
+                //  that much. The first input buffer must contain 19 bytes,
+                //  but that is checked already.
+                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+                return;
+            }
+
             if (mInputBufferCount == 0) {
                 delete mHeader;
                 mHeader = new OpusHeader();
@@ -573,7 +582,7 @@
         outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
 
         outHeader->nTimeStamp = mAnchorTimeUs +
-                                (mNumFramesOutput * 1000000ll) /
+                                (mNumFramesOutput * 1000000LL) /
                                 kRate;
 
         mNumFramesOutput += numFrames;
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index ce8d458..76a400c 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -554,7 +554,7 @@
 
         outHeader->nTimeStamp =
             mAnchorTimeUs
-                + (mNumFramesOutput * 1000000ll) / mVi->rate;
+                + (mNumFramesOutput * 1000000LL) / mVi->rate;
 
         mNumFramesOutput += numFrames;
 
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index f352fba..8a86a0d 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -110,15 +110,22 @@
 
 {
     initPorts();
-    CHECK_EQ(initDecoder(), (status_t)OK);
+    mMemoryVec.clear();
+    mDrcMemoryVec.clear();
+
+    CHECK_EQ(initDecoder(), IA_NO_ERROR);
 }
 
 SoftXAAC::~SoftXAAC() {
-    int errCode = deInitXAACDecoder();
-    if (0 != errCode) {
-        ALOGE("deInitXAACDecoder() failed %d", errCode);
+    IA_ERRORCODE err_code = deInitXAACDecoder();
+    if (IA_NO_ERROR != err_code) {
+        ALOGE("deInitXAACDecoder() failed %d", err_code);
     }
 
+    err_code = deInitMPEGDDDrc();
+    if (IA_NO_ERROR != err_code) {
+        ALOGE("deInitMPEGDDDrc() failed %d", err_code);
+    }
     mIsCodecInitialized = false;
     mIsCodecConfigFlushRequired = false;
 }
@@ -164,36 +171,16 @@
     addPort(def);
 }
 
-status_t SoftXAAC::initDecoder() {
-    status_t status = UNKNOWN_ERROR;
-
+IA_ERRORCODE SoftXAAC::initDecoder() {
     int ui_drc_val;
     IA_ERRORCODE err_code = IA_NO_ERROR;
     int loop = 0;
 
     err_code = initXAACDecoder();
     if (err_code != IA_NO_ERROR) {
-        if (NULL == mXheaacCodecHandle) {
-            ALOGE("AAC decoder handle is null");
-        }
-        if (NULL == mMpegDDrcHandle) {
-            ALOGE("MPEG-D DRC decoder handle is null");
-        }
-        for (loop = 1; loop < mMallocCount; loop++) {
-            if (mMemoryArray[loop] == NULL) {
-                ALOGE(" memory allocation error %d\n", loop);
-                break;
-            }
-        }
-        ALOGE("initXAACDecoder Failed");
-
-        for (loop = 0; loop < mMallocCount; loop++) {
-            if (mMemoryArray[loop]) free(mMemoryArray[loop]);
-        }
-        mMallocCount = 0;
-        return status;
-    } else {
-        status = OK;
+        ALOGE("initXAACDecoder failed with error %d", err_code);
+        deInitXAACDecoder();
+        return err_code;
     }
 
     mEndOfInput = false;
@@ -274,7 +261,7 @@
     RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE");
 
 #endif
-    return status;
+    return IA_NO_ERROR;
 }
 
 OMX_ERRORTYPE SoftXAAC::internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params) {
@@ -547,9 +534,6 @@
     /* sample currently                                                  */
     if (mIsCodecInitialized) {
         numOutBytes = mOutputFrameLength * (mPcmWdSz / 8) * mNumChannels;
-        if ((mPcmWdSz / 8) != 2) {
-            ALOGE("XAAC assumes 2 bytes per sample! mPcmWdSz %d", mPcmWdSz);
-        }
     }
 
     while ((!inQueue.empty() || mEndOfInput) && !outQueue.empty()) {
@@ -569,8 +553,8 @@
                 inBufferLength = inHeader->nFilledLen;
 
                 /* GA header configuration sent to Decoder! */
-                int err_code = configXAACDecoder(inBuffer, inBufferLength);
-                if (0 != err_code) {
+                IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength);
+                if (IA_NO_ERROR != err_code) {
                     ALOGW("configXAACDecoder err_code = %d", err_code);
                     mSignalledError = true;
                     notify(OMX_EventError, OMX_ErrorUndefined, err_code, NULL);
@@ -665,7 +649,7 @@
                     mCurrentTimestamp = inHeader->nTimeStamp;
                     mLastInHeader = inHeader;
                 } else {
-                    mCurrentTimestamp = mPrevTimestamp + mOutputFrameLength * 1000000ll / mSampFreq;
+                    mCurrentTimestamp = mPrevTimestamp + mOutputFrameLength * 1000000LL / mSampFreq;
                 }
             } else {
                 inBuffer = inHeader->pBuffer + inHeader->nOffset;
@@ -682,8 +666,8 @@
             /* which should initialize the codec. Once this state is reached, call the  */
             /* decodeXAACStream API with same frame to decode!                        */
             if (!mIsCodecInitialized) {
-                int err_code = configXAACDecoder(inBuffer, inBufferLength);
-                if (0 != err_code) {
+                IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength);
+                if (IA_NO_ERROR != err_code) {
                     ALOGW("configXAACDecoder Failed 2 err_code = %d", err_code);
                     mSignalledError = true;
                     notify(OMX_EventError, OMX_ErrorUndefined, err_code, NULL);
@@ -845,7 +829,7 @@
     }
 }
 
-int SoftXAAC::configflushDecode() {
+IA_ERRORCODE SoftXAAC::configflushDecode() {
     IA_ERRORCODE err_code;
     UWORD32 ui_init_done;
     uint32_t inBufferLength = 8203;
@@ -871,16 +855,13 @@
             "Found Codec with below config---\nsampFreq %d\nnumChannels %d\npcmWdSz "
             "%d\nchannelMask %d\noutputFrameLength %d",
             mSampFreq, mNumChannels, mPcmWdSz, mChannelMask, mOutputFrameLength);
-        if (mNumChannels > MAX_CHANNEL_COUNT) {
-            ALOGE(" No of channels are more than max channels\n");
-            mIsCodecInitialized = false;
-        } else
-            mIsCodecInitialized = true;
+
+        mIsCodecInitialized = true;
     }
-    return err_code;
+    return IA_NO_ERROR;
 }
-int SoftXAAC::drainDecoder() {
-    return 0;
+IA_ERRORCODE SoftXAAC::drainDecoder() {
+    return IA_NO_ERROR;
 }
 
 void SoftXAAC::onReset() {
@@ -921,7 +902,7 @@
     }
 }
 
-int SoftXAAC::initXAACDecoder() {
+IA_ERRORCODE SoftXAAC::initXAACDecoder() {
     LOOPIDX i;
 
     /* Error code */
@@ -939,11 +920,11 @@
     UWORD32 ui_proc_mem_tabs_size;
     /* API size */
     UWORD32 pui_api_size;
+    pVOID pv_alloc_ptr;
 
     mInputBufferSize = 0;
     mInputBuffer = 0;
     mOutputBuffer = 0;
-    mMallocCount = 0;
 
     /* Process struct initing end */
     /* ******************************************************************/
@@ -954,20 +935,13 @@
     err_code = ixheaacd_dec_api(NULL, IA_API_CMD_GET_API_SIZE, 0, &pui_api_size);
     RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE");
 
-    if (mMallocCount == MAX_MEM_ALLOCS) {
-        ALOGE("mMemoryArray is full");
-        return IA_FATAL_ERROR;
-    }
-
     /* Allocate memory for API */
-    mMemoryArray[mMallocCount] = memalign(4, pui_api_size);
-    if (mMemoryArray[mMallocCount] == NULL) {
+    mXheaacCodecHandle = memalign(4, pui_api_size);
+    if (mXheaacCodecHandle == NULL) {
         ALOGE("malloc for pui_api_size + 4 >> %d Failed", pui_api_size + 4);
         return IA_FATAL_ERROR;
     }
-    /* Set API object with the memory allocated */
-    mXheaacCodecHandle = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
-    mMallocCount++;
+    mMemoryVec.push(mXheaacCodecHandle);
 
     /* Set the config params to default values */
     err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT,
@@ -979,23 +953,16 @@
 
     RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE");
 
-    if (mMallocCount == MAX_MEM_ALLOCS) {
-        ALOGE("mMemoryArray is full");
-        return IA_FATAL_ERROR;
-    }
-
     /* Allocate memory for API */
-    mMemoryArray[mMallocCount] = memalign(4, pui_api_size);
+    mMpegDDrcHandle = memalign(4, pui_api_size);
 
-    if (mMemoryArray[mMallocCount] == NULL) {
+    if (mMpegDDrcHandle == NULL) {
         ALOGE("malloc for drc api structure Failed");
         return IA_FATAL_ERROR;
     }
-    memset(mMemoryArray[mMallocCount], 0, pui_api_size);
+    mMemoryVec.push(mMpegDDrcHandle);
 
-    /* Set API object with the memory allocated */
-    mMpegDDrcHandle = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
-    mMallocCount++;
+    memset(mMpegDDrcHandle, 0, pui_api_size);
 
     /* Set the config params to default values */
     err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
@@ -1021,23 +988,17 @@
                                 &ui_proc_mem_tabs_size);
     RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEMTABS_SIZE");
 
-    if (mMallocCount == MAX_MEM_ALLOCS) {
-        ALOGE("mMemoryArray is full");
-        return IA_FATAL_ERROR;
-    }
-
-    mMemoryArray[mMallocCount] = memalign(4, ui_proc_mem_tabs_size);
-    if (mMemoryArray[mMallocCount] == NULL) {
+    pv_alloc_ptr = memalign(4, ui_proc_mem_tabs_size);
+    if (pv_alloc_ptr == NULL) {
         ALOGE("Malloc for size (ui_proc_mem_tabs_size + 4) = %d failed!",
               ui_proc_mem_tabs_size + 4);
         return IA_FATAL_ERROR;
     }
-    mMallocCount++;
-    /* Set pointer for process memory tables    */
-    err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEMTABS_PTR, 0,
-                                (pVOID)((WORD8*)mMemoryArray[mMallocCount - 1]));
-    RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEMTABS_PTR");
+    mMemoryVec.push(pv_alloc_ptr);
 
+    /* Set pointer for process memory tables    */
+    err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEMTABS_PTR, 0, pv_alloc_ptr);
+    RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEMTABS_PTR");
 
     /* initialize the API, post config, fill memory tables  */
     err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT,
@@ -1066,17 +1027,12 @@
         err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
         RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
 
-        if (mMallocCount == MAX_MEM_ALLOCS) {
-            ALOGE("mMemoryArray is full");
-            return IA_FATAL_ERROR;
-        }
-        mMemoryArray[mMallocCount] = memalign(ui_alignment, ui_size);
-        if (mMemoryArray[mMallocCount] == NULL) {
+        pv_alloc_ptr = memalign(ui_alignment, ui_size);
+        if (pv_alloc_ptr == NULL) {
             ALOGE("Malloc for size (ui_size + ui_alignment) = %d failed!", ui_size + ui_alignment);
             return IA_FATAL_ERROR;
         }
-        pv_alloc_ptr = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
-        mMallocCount++;
+        mMemoryVec.push(pv_alloc_ptr);
 
         /* Set the buffer pointer */
         err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
@@ -1095,7 +1051,7 @@
     return IA_NO_ERROR;
 }
 
-int SoftXAAC::configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength) {
+IA_ERRORCODE SoftXAAC::configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength) {
     UWORD32 ui_init_done;
     int32_t i_bytes_consumed;
 
@@ -1154,13 +1110,73 @@
 
     return IA_NO_ERROR;
 }
-int SoftXAAC::configMPEGDDrc() {
+IA_ERRORCODE SoftXAAC::initMPEGDDDrc() {
+    IA_ERRORCODE err_code = IA_NO_ERROR;
+    int i;
+
+    for (i = 0; i < (WORD32)2; i++) {
+        WORD32 ui_size, ui_alignment, ui_type;
+        pVOID pv_alloc_ptr;
+
+        /* Get memory size */
+        err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size);
+
+        RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE");
+
+        /* Get memory alignment */
+        err_code =
+            ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &ui_alignment);
+
+        RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT");
+
+        /* Get memory type */
+        err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
+        RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
+
+        pv_alloc_ptr = memalign(4, ui_size);
+        if (pv_alloc_ptr == NULL) {
+            ALOGE(" Cannot create requested memory  %d", ui_size);
+            return IA_FATAL_ERROR;
+        }
+        mDrcMemoryVec.push(pv_alloc_ptr);
+
+        /* Set the buffer pointer */
+        err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
+
+        RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+    }
+
+    WORD32 ui_size;
+    ui_size = 8192 * 2;
+
+    mDrcInBuf = (int8_t*)memalign(4, ui_size);
+    if (mDrcInBuf == NULL) {
+        ALOGE(" Cannot create requested memory  %d", ui_size);
+        return IA_FATAL_ERROR;
+    }
+    mDrcMemoryVec.push(mDrcInBuf);
+
+    err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 2, mDrcInBuf);
+    RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+
+    mDrcOutBuf = (int8_t*)memalign(4, ui_size);
+    if (mDrcOutBuf == NULL) {
+        ALOGE(" Cannot create requested memory  %d", ui_size);
+        return IA_FATAL_ERROR;
+    }
+    mDrcMemoryVec.push(mDrcOutBuf);
+
+    err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 3, mDrcOutBuf);
+    RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+
+    return IA_NO_ERROR;
+}
+IA_ERRORCODE SoftXAAC::configMPEGDDrc() {
     IA_ERRORCODE err_code = IA_NO_ERROR;
     int i_effect_type;
     int i_loud_norm;
     int i_target_loudness;
     unsigned int i_sbr_mode;
-    int n_mems;
     int i;
 
 #ifdef ENABLE_MPEG_D_DRC
@@ -1217,78 +1233,16 @@
 
         RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS");
 
-        for (i = 0; i < (WORD32)2; i++) {
-            WORD32 ui_size, ui_alignment, ui_type;
-            pVOID pv_alloc_ptr;
+        /* Free any memory that is allocated for MPEG D Drc so far */
+        deInitMPEGDDDrc();
 
-            /* Get memory size */
-            err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size);
-
-            RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE");
-
-            /* Get memory alignment */
-            err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i,
-                                      &ui_alignment);
-
-            RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT");
-
-            /* Get memory type */
-            err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
-            RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
-            if (mMallocCount == MAX_MEM_ALLOCS) {
-                ALOGE("mMemoryArray is full");
-                return IA_FATAL_ERROR;
-            }
-
-            mMemoryArray[mMallocCount] = memalign(4, ui_size);
-            if (mMemoryArray[mMallocCount] == NULL) {
-                ALOGE(" Cannot create requested memory  %d", ui_size);
-                return IA_FATAL_ERROR;
-            }
-            pv_alloc_ptr = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
-            mMallocCount++;
-
-            /* Set the buffer pointer */
-            err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
-
-            RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+        err_code = initMPEGDDDrc();
+        if (err_code != IA_NO_ERROR) {
+            ALOGE("initMPEGDDDrc failed with error %d", err_code);
+            deInitMPEGDDDrc();
+            return err_code;
         }
-        {
-            WORD32 ui_size;
-            ui_size = 8192 * 2;
-            if (mMallocCount == MAX_MEM_ALLOCS) {
-                ALOGE("mMemoryArray is full");
-                return IA_FATAL_ERROR;
-            }
 
-            mMemoryArray[mMallocCount] = memalign(4, ui_size);
-            if (mMemoryArray[mMallocCount] == NULL) {
-                ALOGE(" Cannot create requested memory  %d", ui_size);
-                return IA_FATAL_ERROR;
-            }
-
-            mDrcInBuf = (int8_t*)mMemoryArray[mMallocCount];
-            mMallocCount++;
-            err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 2,
-                                      /*mOutputBuffer*/ mDrcInBuf);
-            RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
-
-            if (mMallocCount == MAX_MEM_ALLOCS) {
-                ALOGE("mMemoryArray is full");
-                return IA_FATAL_ERROR;
-            }
-            mMemoryArray[mMallocCount] = memalign(4, ui_size);
-            if (mMemoryArray[mMallocCount] == NULL) {
-                ALOGE(" Cannot create requested memory  %d", ui_size);
-                return IA_FATAL_ERROR;
-            }
-
-            mDrcOutBuf = (int8_t*)mMemoryArray[mMallocCount];
-            mMallocCount++;
-            err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 3,
-                                      /*mOutputBuffer*/ mDrcOutBuf);
-            RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
-        }
         /* DRC buffers
             buf[0] - contains extension element pay load loudness related
             buf[1] - contains extension element pay load*/
@@ -1423,10 +1377,10 @@
     }
 #endif
 
-    return err_code;
+    return IA_NO_ERROR;
 }
-int SoftXAAC::decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed,
-                               int32_t* outBytes) {
+IA_ERRORCODE SoftXAAC::decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength,
+                                        int32_t* bytesConsumed, int32_t* outBytes) {
     if (mInputBufferSize < inBufferLength) {
         ALOGE("Cannot config AAC, input buffer size %d < inBufferLength %d", mInputBufferSize,
               inBufferLength);
@@ -1516,24 +1470,33 @@
         memcpy(mOutputBuffer, mDrcOutBuf, *outBytes);
     }
 #endif
-    return err_code;
+    return IA_NO_ERROR;
 }
 
-int SoftXAAC::deInitXAACDecoder() {
+IA_ERRORCODE SoftXAAC::deInitXAACDecoder() {
     ALOGI("deInitXAACDecoder");
 
     /* Tell that the input is over in this buffer */
     IA_ERRORCODE err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INPUT_OVER, 0, NULL);
-    RETURN_IF_FATAL(err_code, "IA_API_CMD_INPUT_OVER");
 
-    for (int i = 0; i < mMallocCount; i++) {
-        if (mMemoryArray[i]) free(mMemoryArray[i]);
+    /* Irrespective of error returned in IA_API_CMD_INPUT_OVER, free allocated memory */
+    for (void* buf : mMemoryVec) {
+        free(buf);
     }
-    mMallocCount = 0;
-
+    mMemoryVec.clear();
     return err_code;
 }
 
+IA_ERRORCODE SoftXAAC::deInitMPEGDDDrc() {
+    ALOGI("deInitMPEGDDDrc");
+
+    for (void* buf : mDrcMemoryVec) {
+        free(buf);
+    }
+    mDrcMemoryVec.clear();
+    return IA_NO_ERROR;
+}
+
 IA_ERRORCODE SoftXAAC::getXAACStreamInfo() {
     IA_ERRORCODE err_code = IA_NO_ERROR;
 
@@ -1546,11 +1509,19 @@
     err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
                                 IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS, &mNumChannels);
     RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS");
+    if (mNumChannels > MAX_CHANNEL_COUNT) {
+        ALOGE(" No of channels are more than max channels\n");
+        return IA_FATAL_ERROR;
+    }
 
     /* PCM word size */
     err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
                                 IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ, &mPcmWdSz);
     RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ");
+    if ((mPcmWdSz / 8) != 2) {
+        ALOGE("Invalid Number of bytes per sample: %d, Expected is 2", mPcmWdSz);
+        return IA_FATAL_ERROR;
+    }
 
     /* channel mask to tell the arrangement of channels in bit stream */
     err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.h b/media/libstagefright/codecs/xaacdec/SoftXAAC.h
index 6176082..a62a797 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.h
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.h
@@ -33,8 +33,6 @@
 #include "impd_apicmd_standards.h"
 #include "impd_drc_config_params.h"
 
-#define MAX_MEM_ALLOCS 100
-
 extern "C" IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_module_obj, WORD32 i_cmd, WORD32 i_idx,
                                          pVOID pv_value);
 extern "C" IA_ERRORCODE ia_drc_dec_api(pVOID p_ia_module_obj, WORD32 i_cmd, WORD32 i_idx,
@@ -80,18 +78,19 @@
     enum { NONE, AWAITING_DISABLED, AWAITING_ENABLED } mOutputPortSettingsChange;
 
     void initPorts();
-    status_t initDecoder();
+    IA_ERRORCODE initDecoder();
     bool isConfigured() const;
-    int drainDecoder();
-    int initXAACDecoder();
-    int deInitXAACDecoder();
+    IA_ERRORCODE drainDecoder();
+    IA_ERRORCODE initXAACDecoder();
+    IA_ERRORCODE deInitXAACDecoder();
+    IA_ERRORCODE initMPEGDDDrc();
+    IA_ERRORCODE deInitMPEGDDDrc();
+    IA_ERRORCODE configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength);
+    IA_ERRORCODE configMPEGDDrc();
+    IA_ERRORCODE decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength,
+                                  int32_t* bytesConsumed, int32_t* outBytes);
 
-    int configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength);
-    int configMPEGDDrc();
-    int decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed,
-                         int32_t* outBytes);
-
-    int configflushDecode();
+    IA_ERRORCODE configflushDecode();
     IA_ERRORCODE getXAACStreamInfo();
     IA_ERRORCODE setXAACDRCInfo(int32_t drcCut, int32_t drcBoost, int32_t drcRefLevel,
                                 int32_t drcHeavyCompression
@@ -120,9 +119,8 @@
     int8_t* mDrcOutBuf;
     int32_t mMpegDDRCPresent;
     int32_t mDRCFlag;
-
-    void* mMemoryArray[MAX_MEM_ALLOCS];
-    int32_t mMallocCount;
+    Vector<void*> mMemoryVec;
+    Vector<void*> mDrcMemoryVec;
 
     DISALLOW_EVIL_CONSTRUCTORS(SoftXAAC);
 };
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 86bd9d6..d136d9e 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -27,6 +27,7 @@
 
 #include "libyuv/convert_from.h"
 #include "libyuv/convert_argb.h"
+#include "libyuv/planar_functions.h"
 #include "libyuv/video_common.h"
 #include <functional>
 #include <sys/time.h>
@@ -91,10 +92,17 @@
 
         case OMX_COLOR_FormatCbYCrY:
         case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
-        case OMX_COLOR_FormatYUV420SemiPlanar:
         case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
             return mDstFormat == OMX_COLOR_Format16bitRGB565;
 
+        case OMX_COLOR_FormatYUV420SemiPlanar:
+#ifdef USE_LIBYUV
+            return mDstFormat == OMX_COLOR_Format16bitRGB565
+                    || mDstFormat == OMX_COLOR_Format32BitRGBA8888;
+#else
+            return mDstFormat == OMX_COLOR_Format16bitRGB565;
+#endif
+
         default:
             return false;
     }
@@ -236,7 +244,11 @@
             break;
 
         case OMX_COLOR_FormatYUV420SemiPlanar:
+#ifdef USE_LIBYUV
+            err = convertYUV420SemiPlanarUseLibYUV(src, dst);
+#else
             err = convertYUV420SemiPlanar(src, dst);
+#endif
             break;
 
         case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
@@ -365,6 +377,36 @@
     return OK;
 }
 
+status_t ColorConverter::convertYUV420SemiPlanarUseLibYUV(
+        const BitmapParams &src, const BitmapParams &dst) {
+    uint8_t *dst_ptr = (uint8_t *)dst.mBits
+        + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
+
+    const uint8_t *src_y =
+        (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;
+
+    const uint8_t *src_u =
+        (const uint8_t *)src.mBits + src.mStride * src.mHeight
+        + (src.mCropTop / 2) * src.mStride + src.mCropLeft;
+
+    switch (mDstFormat) {
+    case OMX_COLOR_Format16bitRGB565:
+        libyuv::NV12ToRGB565(src_y, src.mStride, src_u, src.mStride, (uint8 *)dst_ptr,
+                dst.mStride, src.cropWidth(), src.cropHeight());
+        break;
+
+    case OMX_COLOR_Format32BitRGBA8888:
+        libyuv::NV12ToARGB(src_y, src.mStride, src_u, src.mStride, (uint8 *)dst_ptr,
+                dst.mStride, src.cropWidth(), src.cropHeight());
+        break;
+
+    default:
+        return ERROR_UNSUPPORTED;
+   }
+
+   return OK;
+}
+
 std::function<void (void *, void *, void *, size_t,
                     signed *, signed *, signed *, signed *)>
 getReadFromSrc(OMX_COLOR_FORMATTYPE srcFormat) {
@@ -852,7 +894,7 @@
 
     const uint8_t *src_u =
         (const uint8_t *)src.mBits + src.mHeight * src.mStride +
-        src.mCropTop * src.mStride / 2 + src.mCropLeft;
+        (src.mCropTop / 2) * src.mStride + src.mCropLeft;
 
     for (size_t y = 0; y < src.cropHeight(); ++y) {
         for (size_t x = 0; x < src.cropWidth(); x += 2) {
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index 751b053..307c9b0 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -27,11 +27,17 @@
     },
 
     static: {
-        whole_static_libs: ["libFLAC"],
+        whole_static_libs: [
+            "libFLAC",
+            "libaudioutils",
+        ],
     },
 
     shared: {
-        static_libs: ["libFLAC"],
+        static_libs: [
+            "libFLAC",
+            "libaudioutils",
+        ],
     },
 
     shared_libs: [
diff --git a/media/libstagefright/flac/dec/FLACDecoder.cpp b/media/libstagefright/flac/dec/FLACDecoder.cpp
index dfdc41c..cef0bc6 100644
--- a/media/libstagefright/flac/dec/FLACDecoder.cpp
+++ b/media/libstagefright/flac/dec/FLACDecoder.cpp
@@ -20,6 +20,7 @@
 
 #include "FLACDecoder.h"
 
+#include <audio_utils/primitives.h> // float_from_i32
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MediaDefs.h>
@@ -117,104 +118,43 @@
     mErrorStatus = status;
 }
 
-// Copy samples from FLAC native 32-bit non-interleaved to 16-bit interleaved.
+// Copy samples from FLAC native 32-bit non-interleaved to 16-bit signed
+// or 32-bit float interleaved.
+// TODO: Consider moving to audio_utils.  See similar code at FLACExtractor.cpp
 // These are candidates for optimization if needed.
-static void copyMono8(
-        int16_t *dst,
-        const int * src[FLACDecoder::kMaxChannels],
+static void copyTo16Signed(
+        short *dst,
+        const int *const *src,
         unsigned nSamples,
-        unsigned /* nChannels */) {
-    for (unsigned i = 0; i < nSamples; ++i) {
-        *dst++ = src[0][i] << 8;
-    }
-}
-
-static void copyStereo8(
-        int16_t *dst,
-        const int * src[FLACDecoder::kMaxChannels],
-        unsigned nSamples,
-        unsigned /* nChannels */) {
-    for (unsigned i = 0; i < nSamples; ++i) {
-        *dst++ = src[0][i] << 8;
-        *dst++ = src[1][i] << 8;
-    }
-}
-
-static void copyMultiCh8(
-        int16_t *dst,
-        const int * src[FLACDecoder::kMaxChannels],
-        unsigned nSamples,
-        unsigned nChannels) {
-    for (unsigned i = 0; i < nSamples; ++i) {
-        for (unsigned c = 0; c < nChannels; ++c) {
-            *dst++ = src[c][i] << 8;
+        unsigned nChannels,
+        unsigned bitsPerSample) {
+    const int leftShift = 16 - (int)bitsPerSample; // cast to int to prevent unsigned overflow.
+    if (leftShift >= 0) {
+        for (unsigned i = 0; i < nSamples; ++i) {
+            for (unsigned c = 0; c < nChannels; ++c) {
+                *dst++ = src[c][i] << leftShift;
+            }
+        }
+    } else {
+        const int rightShift = -leftShift;
+        for (unsigned i = 0; i < nSamples; ++i) {
+            for (unsigned c = 0; c < nChannels; ++c) {
+                *dst++ = src[c][i] >> rightShift;
+            }
         }
     }
 }
 
-static void copyMono16(
-        int16_t *dst,
-        const int * src[FLACDecoder::kMaxChannels],
+static void copyToFloat(
+        float *dst,
+        const int *const *src,
         unsigned nSamples,
-        unsigned /* nChannels */) {
-    for (unsigned i = 0; i < nSamples; ++i) {
-        *dst++ = src[0][i];
-    }
-}
-
-static void copyStereo16(
-        int16_t *dst,
-        const int * src[FLACDecoder::kMaxChannels],
-        unsigned nSamples,
-        unsigned /* nChannels */) {
-    for (unsigned i = 0; i < nSamples; ++i) {
-        *dst++ = src[0][i];
-        *dst++ = src[1][i];
-    }
-}
-
-static void copyMultiCh16(
-        int16_t *dst,
-        const int * src[FLACDecoder::kMaxChannels],
-        unsigned nSamples,
-        unsigned nChannels) {
+        unsigned nChannels,
+        unsigned bitsPerSample) {
+    const unsigned leftShift = 32 - bitsPerSample;
     for (unsigned i = 0; i < nSamples; ++i) {
         for (unsigned c = 0; c < nChannels; ++c) {
-            *dst++ = src[c][i];
-        }
-    }
-}
-
-// TODO: 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger
-static void copyMono24(
-        int16_t *dst,
-        const int * src[FLACDecoder::kMaxChannels],
-        unsigned nSamples,
-        unsigned /* nChannels */) {
-    for (unsigned i = 0; i < nSamples; ++i) {
-        *dst++ = src[0][i] >> 8;
-    }
-}
-
-static void copyStereo24(
-        int16_t *dst,
-        const int * src[FLACDecoder::kMaxChannels],
-        unsigned nSamples,
-        unsigned /* nChannels */) {
-    for (unsigned i = 0; i < nSamples; ++i) {
-        *dst++ = src[0][i] >> 8;
-        *dst++ = src[1][i] >> 8;
-    }
-}
-
-static void copyMultiCh24(
-        int16_t *dst,
-        const int * src[FLACDecoder::kMaxChannels],
-        unsigned nSamples,
-        unsigned nChannels) {
-    for (unsigned i = 0; i < nSamples; ++i) {
-        for (unsigned c = 0; c < nChannels; ++c) {
-            *dst++ = src[c][i] >> 8;
+            *dst++ = float_from_i32(src[c][i] << leftShift);
         }
     }
 }
@@ -238,8 +178,7 @@
       mStreamInfoValid(false),
       mWriteRequested(false),
       mWriteCompleted(false),
-      mErrorStatus((FLAC__StreamDecoderErrorStatus) -1),
-      mCopy(nullptr) {
+      mErrorStatus((FLAC__StreamDecoderErrorStatus) -1) {
     ALOGV("ctor:");
     memset(&mStreamInfo, 0, sizeof(mStreamInfo));
     memset(&mWriteHeader, 0, sizeof(mWriteHeader));
@@ -379,6 +318,7 @@
         case 8:
         case 16:
         case 24:
+        case 32: // generally rare, but is supported in the framework
             break;
 
         default:
@@ -387,31 +327,6 @@
             return ERROR_MALFORMED;
     }
 
-    // configure the appropriate copy function, defaulting to trespass
-    static const struct {
-        unsigned mChannels;
-        unsigned mBitsPerSample;
-        void (*mCopy)(int16_t *dst, const int * src[kMaxChannels],
-                unsigned nSamples, unsigned nChannels);
-    } table[] = {
-        { 1,  8, copyMono8     },
-        { 2,  8, copyStereo8   },
-        { 8,  8, copyMultiCh8  },
-        { 1, 16, copyMono16    },
-        { 2, 16, copyStereo16  },
-        { 8, 16, copyMultiCh16 },
-        { 1, 24, copyMono24    },
-        { 2, 24, copyStereo24  },
-        { 8, 24, copyMultiCh24 },
-    };
-    for (const auto &entry : table) {
-        if (entry.mChannels >= getChannels() &&
-                entry.mBitsPerSample == getBitsPerSample()) {
-            mCopy = entry.mCopy;
-            break;
-        }
-    }
-
     // Now we have all metadata blocks.
     mBufferPos = 0;
     mBufferDataSize = 0;
@@ -420,7 +335,7 @@
 }
 
 status_t FLACDecoder::decodeOneFrame(const uint8_t *inBuffer, size_t inBufferLen,
-        int16_t *outBuffer, size_t *outBufferLen) {
+        void *outBuffer, size_t *outBufferLen, bool outputFloat) {
     ALOGV("decodeOneFrame: input size(%zu)", inBufferLen);
 
     if (!mStreamInfoValid) {
@@ -469,21 +384,33 @@
         return ERROR_MALFORMED;
     }
 
-    size_t bufferSize = blocksize * getChannels() * sizeof(int16_t);
+    const unsigned channels = getChannels();
+    const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(int16_t);
+    const size_t frameSize = channels * sampleSize;
+    size_t bufferSize = blocksize * frameSize;
     if (bufferSize > *outBufferLen) {
         ALOGW("decodeOneFrame: output buffer holds only partial frame %zu:%zu",
                 *outBufferLen, bufferSize);
-        blocksize = *outBufferLen / (getChannels() * sizeof(int16_t));
-        bufferSize = blocksize * getChannels() * sizeof(int16_t);
+        blocksize = *outBufferLen / frameSize;
+        bufferSize = blocksize * frameSize;
     }
 
-    if (mCopy == nullptr) {
-        ALOGE("decodeOneFrame: format is not supported: channels(%d), BitsPerSample(%d)",
-                getChannels(), getBitsPerSample());
-        return ERROR_UNSUPPORTED;
-    }
     // copy PCM from FLAC write buffer to output buffer, with interleaving
-    (*mCopy)(outBuffer, mWriteBuffer, blocksize, getChannels());
+
+    const unsigned bitsPerSample = getBitsPerSample();
+    if (outputFloat) {
+        copyToFloat(reinterpret_cast<float*>(outBuffer),
+                    mWriteBuffer,
+                    blocksize,
+                    channels,
+                    bitsPerSample);
+    } else {
+        copyTo16Signed(reinterpret_cast<short*>(outBuffer),
+                       mWriteBuffer,
+                       blocksize,
+                       channels,
+                       bitsPerSample);
+    }
     *outBufferLen = bufferSize;
     return OK;
 }
diff --git a/media/libstagefright/flac/dec/FLACDecoder.h b/media/libstagefright/flac/dec/FLACDecoder.h
index af419a2..694fccb 100644
--- a/media/libstagefright/flac/dec/FLACDecoder.h
+++ b/media/libstagefright/flac/dec/FLACDecoder.h
@@ -41,7 +41,7 @@
 
     status_t parseMetadata(const uint8_t *inBuffer, size_t inBufferLen);
     status_t decodeOneFrame(const uint8_t *inBuffer, size_t inBufferLen,
-            int16_t *outBuffer, size_t *outBufferLen);
+            void *outBuffer, size_t *outBufferLen, bool outputFloat = false);
     void flush();
     virtual ~FLACDecoder();
 
@@ -89,8 +89,6 @@
     // most recent error reported by libFLAC decoder
     FLAC__StreamDecoderErrorStatus mErrorStatus;
 
-    void (*mCopy)(int16_t *dst, const int *src[kMaxChannels], unsigned nSamples, unsigned nChannels);
-
     status_t init();
 
     // FLAC stream decoder callbacks as C++ instance methods
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index 768cbd6..a276722 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -66,7 +66,7 @@
 
 // static
 int64_t ALooper::GetNowUs() {
-    return systemTime(SYSTEM_TIME_MONOTONIC) / 1000ll;
+    return systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
 }
 
 ALooper::ALooper()
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/libstagefright/foundation/MediaDefs.cpp
index aba44bb..9d1ec1f 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/libstagefright/foundation/MediaDefs.cpp
@@ -23,6 +23,7 @@
 
 const char *MEDIA_MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
 const char *MEDIA_MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
+const char *MEDIA_MIMETYPE_VIDEO_AV1 = "video/av01";
 const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc";
 const char *MEDIA_MIMETYPE_VIDEO_HEVC = "video/hevc";
 const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
index 8edddcc..e68852d 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -25,6 +25,7 @@
 
 extern const char *MEDIA_MIMETYPE_VIDEO_VP8;
 extern const char *MEDIA_MIMETYPE_VIDEO_VP9;
+extern const char *MEDIA_MIMETYPE_VIDEO_AV1;
 extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
 extern const char *MEDIA_MIMETYPE_VIDEO_HEVC;
 extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4;
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 86872c5..2ecfa43 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -44,10 +44,10 @@
 
 // static
 // Bandwidth Switch Mark Defaults
-const int64_t LiveSession::kUpSwitchMarkUs = 15000000ll;
-const int64_t LiveSession::kDownSwitchMarkUs = 20000000ll;
-const int64_t LiveSession::kUpSwitchMarginUs = 5000000ll;
-const int64_t LiveSession::kResumeThresholdUs = 100000ll;
+const int64_t LiveSession::kUpSwitchMarkUs = 15000000LL;
+const int64_t LiveSession::kDownSwitchMarkUs = 20000000LL;
+const int64_t LiveSession::kUpSwitchMarginUs = 5000000LL;
+const int64_t LiveSession::kResumeThresholdUs = 100000LL;
 
 //TODO: redefine this mark to a fair value
 // default buffer underflow mark
@@ -66,9 +66,9 @@
     // Bandwidth estimation parameters
     static const int32_t kShortTermBandwidthItems = 3;
     static const int32_t kMinBandwidthHistoryItems = 20;
-    static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec
-    static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec
-    static const int64_t kMaxBandwidthHistoryAgeUs = 60000000ll; // 60 sec
+    static const int64_t kMinBandwidthHistoryWindowUs = 5000000LL; // 5 sec
+    static const int64_t kMaxBandwidthHistoryWindowUs = 30000000LL; // 30 sec
+    static const int64_t kMaxBandwidthHistoryAgeUs = 60000000LL; // 60 sec
 
     struct BandwidthEntry {
         int64_t mTimestampUs;
@@ -284,7 +284,7 @@
       mPrevBufferPercentage(-1),
       mCurBandwidthIndex(-1),
       mOrigBandwidthIndex(-1),
-      mLastBandwidthBps(-1ll),
+      mLastBandwidthBps(-1LL),
       mLastBandwidthStable(false),
       mBandwidthEstimator(new BandwidthEstimator()),
       mMaxWidth(720),
@@ -294,8 +294,8 @@
       mSwapMask(0),
       mSwitchGeneration(0),
       mSubtitleGeneration(0),
-      mLastDequeuedTimeUs(0ll),
-      mRealTimeBaseUs(0ll),
+      mLastDequeuedTimeUs(0LL),
+      mRealTimeBaseUs(0LL),
       mReconfigurationInProgress(false),
       mSwitchInProgress(false),
       mUpSwitchMark(kUpSwitchMarkUs),
@@ -844,7 +844,7 @@
                     // (If we don't have that cushion we'd rather cancel and try again.)
                     int64_t delayUs =
                         switchUp ?
-                            (kUnderflowMarkMs * 1000ll + 1000000ll)
+                            (kUnderflowMarkMs * 1000LL + 1000000LL)
                             : 0;
                     bool needResumeUntil = false;
                     sp<AMessage> stopParams = msg;
@@ -954,7 +954,7 @@
 
 // static
 bool LiveSession::isBandwidthValid(const BandwidthItem &item) {
-    static const int64_t kBlacklistWindowUs = 300 * 1000000ll;
+    static const int64_t kBlacklistWindowUs = 300 * 1000000LL;
     return item.mLastFailureUs < 0
             || ALooper::GetNowUs() - item.mLastFailureUs > kBlacklistWindowUs;
 }
@@ -1060,7 +1060,7 @@
             BandwidthItem item;
 
             item.mPlaylistIndex = i;
-            item.mLastFailureUs = -1ll;
+            item.mLastFailureUs = -1LL;
 
             sp<AMessage> meta;
             AString uri;
@@ -1114,7 +1114,7 @@
 
     mPlaylist->pickRandomMediaItems();
     changeConfiguration(
-            0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
+            0LL /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
 }
 
 void LiveSession::finishDisconnect() {
@@ -1175,7 +1175,7 @@
     FetcherInfo info;
     info.mFetcher = new PlaylistFetcher(
             notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration);
-    info.mDurationUs = -1ll;
+    info.mDurationUs = -1LL;
     info.mToBeRemoved = false;
     info.mToBeResumed = false;
     mFetcherLooper->registerHandler(info.mFetcher);
@@ -1466,7 +1466,7 @@
 }
 
 status_t LiveSession::getDuration(int64_t *durationUs) const {
-    int64_t maxDurationUs = -1ll;
+    int64_t maxDurationUs = -1LL;
     for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
         int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
 
@@ -1592,7 +1592,7 @@
         // Delay fetcher removal if not picking tracks, AND old fetcher
         // has stream mask that overlaps new variant. (Okay to discard
         // old fetcher now, if completely no overlap.)
-        if (discardFetcher && timeUs < 0ll && !pickTrack
+        if (discardFetcher && timeUs < 0LL && !pickTrack
                 && (fetcher->getStreamTypeMask() & streamMask)) {
             discardFetcher = false;
             delayRemoval = true;
@@ -1604,7 +1604,7 @@
         } else {
             float threshold = 0.0f; // default to pause after current block (47Kbytes)
             bool disconnect = false;
-            if (timeUs >= 0ll) {
+            if (timeUs >= 0LL) {
                 // seeking, no need to finish fetching
                 disconnect = true;
             } else if (delayRemoval) {
@@ -1620,7 +1620,7 @@
     }
 
     sp<AMessage> msg;
-    if (timeUs < 0ll) {
+    if (timeUs < 0LL) {
         // skip onChangeConfiguration2 (decoder destruction) if not seeking.
         msg = new AMessage(kWhatChangeConfiguration3, this);
     } else {
@@ -1654,9 +1654,9 @@
     if (!mReconfigurationInProgress) {
         int32_t pickTrack = 0;
         msg->findInt32("pickTrack", &pickTrack);
-        changeConfiguration(-1ll /* timeUs */, -1, pickTrack);
+        changeConfiguration(-1LL /* timeUs */, -1, pickTrack);
     } else {
-        msg->post(1000000ll); // retry in 1 sec
+        msg->post(1000000LL); // retry in 1 sec
     }
 }
 
@@ -1788,7 +1788,7 @@
     CHECK(msg->findInt64("timeUs", &timeUs));
     CHECK(msg->findInt32("pickTrack", &pickTrack));
 
-    if (timeUs < 0ll) {
+    if (timeUs < 0LL) {
         if (!pickTrack) {
             // mSwapMask contains streams that are in both old and new variant,
             // (in mNewStreamMask & mStreamMask) but with different URIs
@@ -2062,7 +2062,7 @@
 void LiveSession::schedulePollBuffering() {
     sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
     msg->setInt32("generation", mPollBufferingGeneration);
-    msg->post(1000000ll);
+    msg->post(1000000LL);
 }
 
 void LiveSession::cancelPollBuffering() {
@@ -2208,13 +2208,13 @@
         int64_t readyMarkUs =
             (mInPreparationPhase ?
                 mBufferingSettings.mInitialMarkMs :
-                mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
+                mBufferingSettings.mResumePlaybackMarkMs) * 1000LL;
         if (bufferedDurationUs > readyMarkUs
                 || mPacketSources[i]->isFinished(0)) {
             ++readyCount;
         }
         if (!mPacketSources[i]->isFinished(0)) {
-            if (bufferedDurationUs < kUnderflowMarkMs * 1000ll) {
+            if (bufferedDurationUs < kUnderflowMarkMs * 1000LL) {
                 ++underflowCount;
             }
             if (bufferedDurationUs > mUpSwitchMark) {
@@ -2300,7 +2300,7 @@
         ssize_t lowestValid = getLowestValidBandwidthIndex();
         if (mCurBandwidthIndex > lowestValid) {
             cancelBandwidthSwitch();
-            changeConfiguration(-1ll, lowestValid);
+            changeConfiguration(-1LL, lowestValid);
             return true;
         }
     }
@@ -2370,7 +2370,7 @@
             // if not yet prepared, just restart again with new bw index.
             // this is faster and playback experience is cleaner.
             changeConfiguration(
-                    mInPreparationPhase ? 0 : -1ll, bandwidthIndex);
+                    mInPreparationPhase ? 0 : -1LL, bandwidthIndex);
             return true;
         }
     }
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index d06d9f2..16179d3 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -258,7 +258,7 @@
       mIsEvent(false),
       mFirstSeqNumber(-1),
       mLastSeqNumber(-1),
-      mTargetDurationUs(-1ll),
+      mTargetDurationUs(-1LL),
       mDiscontinuitySeq(0),
       mDiscontinuityCount(0),
       mSelectedIndex(-1) {
@@ -716,7 +716,7 @@
             ALOGE("Media playlist missing #EXT-X-TARGETDURATION");
             return ERROR_MALFORMED;
         }
-        mTargetDurationUs = targetDurationSecs * 1000000ll;
+        mTargetDurationUs = targetDurationSecs * 1000000LL;
 
         mFirstSeqNumber = 0;
         if (mMeta != NULL) {
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 823f90e..562c625 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -50,8 +50,8 @@
 namespace android {
 
 // static
-const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000ll;
-const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll;
+const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000LL;
+const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000LL;
 // LCM of 188 (size of a TS packet) & 1k works well
 const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024;
 
@@ -152,25 +152,25 @@
       mURI(uri),
       mFetcherID(id),
       mStreamTypeMask(0),
-      mStartTimeUs(-1ll),
-      mSegmentStartTimeUs(-1ll),
-      mDiscontinuitySeq(-1ll),
+      mStartTimeUs(-1LL),
+      mSegmentStartTimeUs(-1LL),
+      mDiscontinuitySeq(-1LL),
       mStartTimeUsRelative(false),
-      mLastPlaylistFetchTimeUs(-1ll),
-      mPlaylistTimeUs(-1ll),
+      mLastPlaylistFetchTimeUs(-1LL),
+      mPlaylistTimeUs(-1LL),
       mSeqNumber(-1),
       mNumRetries(0),
       mStartup(true),
       mIDRFound(false),
       mSeekMode(LiveSession::kSeekModeExactPosition),
       mTimeChangeSignaled(false),
-      mNextPTSTimeUs(-1ll),
+      mNextPTSTimeUs(-1LL),
       mMonitorQueueGeneration(0),
       mSubtitleGeneration(subtitleGeneration),
-      mLastDiscontinuitySeq(-1ll),
+      mLastDiscontinuitySeq(-1LL),
       mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY),
       mFirstPTSValid(false),
-      mFirstTimeUs(-1ll),
+      mFirstTimeUs(-1LL),
       mVideoBuffer(new AnotherPacketSource(NULL)),
       mSampleAesKeyItemChanged(false),
       mThresholdRatio(-1.0f),
@@ -200,7 +200,7 @@
     CHECK_GE(seqNumber, firstSeqNumberInPlaylist);
     CHECK_LE(seqNumber, lastSeqNumberInPlaylist);
 
-    int64_t segmentStartUs = 0ll;
+    int64_t segmentStartUs = 0LL;
     for (int32_t index = 0;
             index < seqNumber - firstSeqNumberInPlaylist; ++index) {
         sp<AMessage> itemMeta;
@@ -240,13 +240,13 @@
 int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const {
     int64_t nowUs = ALooper::GetNowUs();
 
-    if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) {
+    if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0LL) {
         CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
-        return 0ll;
+        return 0LL;
     }
 
     if (mPlaylist->isComplete()) {
-        return (~0llu >> 1);
+        return (~0LLU >> 1);
     }
 
     int64_t targetDurationUs = mPlaylist->getTargetDuration();
@@ -295,7 +295,7 @@
     }
 
     int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs;
-    return delayUs > 0ll ? delayUs : 0ll;
+    return delayUs > 0LL ? delayUs : 0LL;
 }
 
 status_t PlaylistFetcher::decryptBuffer(
@@ -857,7 +857,7 @@
         targetDurationUs = mPlaylist->getTargetDuration();
     }
 
-    int64_t bufferedDurationUs = 0ll;
+    int64_t bufferedDurationUs = 0LL;
     status_t finalResult = OK;
     if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
         sp<AnotherPacketSource> packetSource =
@@ -870,7 +870,7 @@
         // enqueued to prevent us from waiting on a non-existent stream;
         // when we cannot make out from the manifest what streams are included in
         // a playlist we might assume extra streams.
-        bufferedDurationUs = -1ll;
+        bufferedDurationUs = -1LL;
         for (size_t i = 0; i < mPacketSources.size(); ++i) {
             if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0
                     || mPacketSources[i]->getLatestEnqueuedMeta() == NULL) {
@@ -882,13 +882,13 @@
 
             FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs);
 
-            if (bufferedDurationUs == -1ll
+            if (bufferedDurationUs == -1LL
                  || bufferedStreamDurationUs < bufferedDurationUs) {
                 bufferedDurationUs = bufferedStreamDurationUs;
             }
         }
-        if (bufferedDurationUs == -1ll) {
-            bufferedDurationUs = 0ll;
+        if (bufferedDurationUs == -1LL) {
+            bufferedDurationUs = 0LL;
         }
     }
 
@@ -901,12 +901,12 @@
         // onDownloadNext();
         sp<AMessage> msg = new AMessage(kWhatDownloadNext, this);
         msg->setInt32("generation", mMonitorQueueGeneration);
-        msg->post(1000l);
+        msg->post(1000L);
     } else {
         // We'd like to maintain buffering above durationToBufferUs, so try
         // again when buffer just about to go below durationToBufferUs
         // (or after targetDurationUs / 2, whichever is smaller).
-        int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll;
+        int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000LL;
         if (delayUs > targetDurationUs / 2) {
             delayUs = targetDurationUs / 2;
         }
@@ -1073,10 +1073,10 @@
         }
     }
 
-    mSegmentFirstPTS = -1ll;
+    mSegmentFirstPTS = -1LL;
 
     if (mPlaylist != NULL && mSeqNumber < 0) {
-        CHECK_GE(mStartTimeUs, 0ll);
+        CHECK_GE(mStartTimeUs, 0LL);
 
         if (mSegmentStartTimeUs < 0) {
             if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) {
@@ -1379,7 +1379,7 @@
                         & (LiveSession::STREAMTYPE_AUDIO
                         | LiveSession::STREAMTYPE_VIDEO))) {
             mSession->addBandwidthMeasurement(bytesRead, delayUs);
-            if (delayUs > 2000000ll) {
+            if (delayUs > 2000000LL) {
                 FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip",
                         bytesRead, (double)delayUs / 1.0e6);
             }
@@ -1553,7 +1553,7 @@
         // if the previous fetcher paused in the middle of a segment, we
         // want to start at a segment that overlaps the last sample
         minDiffUs = -mPlaylist->getTargetDuration();
-        maxDiffUs = 0ll;
+        maxDiffUs = 0LL;
     } else {
         // if the previous fetcher paused at the end of a segment, ideally
         // we want to start at the segment that's roughly aligned with its
@@ -1704,7 +1704,7 @@
         mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
     }
 
-    if (mNextPTSTimeUs >= 0ll) {
+    if (mNextPTSTimeUs >= 0LL) {
         sp<AMessage> extra = new AMessage;
         // Since we are using absolute timestamps, signal an offset of 0 to prevent
         // ATSParser from skewing the timestamps of access units.
@@ -1719,7 +1719,7 @@
         mTSParser->signalDiscontinuity(
                 ATSParser::DISCONTINUITY_TIME, extra);
 
-        mNextPTSTimeUs = -1ll;
+        mNextPTSTimeUs = -1LL;
     }
 
     if (mSampleAesKeyItemChanged) {
@@ -1740,7 +1740,7 @@
     // setRange to indicate consumed bytes.
     buffer->setRange(buffer->offset() + offset, buffer->size() - offset);
 
-    if (mSegmentFirstPTS < 0ll) {
+    if (mSegmentFirstPTS < 0LL) {
         // get the smallest first PTS from all streams present in this parser
         for (size_t i = mPacketSources.size(); i > 0;) {
             i--;
@@ -1764,12 +1764,12 @@
             if (meta != NULL) {
                 int64_t timeUs;
                 CHECK(meta->findInt64("timeUs", &timeUs));
-                if (mSegmentFirstPTS < 0ll || timeUs < mSegmentFirstPTS) {
+                if (mSegmentFirstPTS < 0LL || timeUs < mSegmentFirstPTS) {
                     mSegmentFirstPTS = timeUs;
                 }
             }
         }
-        if (mSegmentFirstPTS < 0ll) {
+        if (mSegmentFirstPTS < 0LL) {
             // didn't find any TS packet, can return early
             return OK;
         }
@@ -1988,8 +1988,8 @@
         return OK;
     }
 
-    if (mNextPTSTimeUs >= 0ll) {
-        mNextPTSTimeUs = -1ll;
+    if (mNextPTSTimeUs >= 0LL) {
+        mNextPTSTimeUs = -1LL;
     }
 
     // This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio
@@ -2088,17 +2088,17 @@
         packetSource->setFormat(meta);
     }
 
-    int64_t numSamples = 0ll;
+    int64_t numSamples = 0LL;
     int32_t sampleRate;
     CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
 
-    int64_t timeUs = (PTS * 100ll) / 9ll;
+    int64_t timeUs = (PTS * 100LL) / 9LL;
     if (mStartup && !mFirstPTSValid) {
         mFirstPTSValid = true;
         mFirstTimeUs = timeUs;
     }
 
-    if (mSegmentFirstPTS < 0ll) {
+    if (mSegmentFirstPTS < 0LL) {
         mSegmentFirstPTS = timeUs;
         if (!mStartTimeUsRelative) {
             // Duplicated logic from how we handle .ts playlists.
@@ -2148,7 +2148,7 @@
 
         CHECK_LE(offset + aac_frame_length, buffer->size());
 
-        int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate;
+        int64_t unitTimeUs = timeUs + numSamples * 1000000LL / sampleRate;
         offset += aac_frame_length;
 
         // Each AAC frame encodes 1024 samples.
@@ -2209,7 +2209,7 @@
 }
 
 void PlaylistFetcher::updateDuration() {
-    int64_t durationUs = 0ll;
+    int64_t durationUs = 0LL;
     for (size_t index = 0; index < mPlaylist->size(); ++index) {
         sp<AMessage> itemMeta;
         CHECK(mPlaylist->itemAt(
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index b489183..792a68a 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -43,7 +43,7 @@
     }
 
     virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
-        off64_t available = (offset >= (off64_t)mSize) ? 0ll : mSize - offset;
+        off64_t available = (offset >= (off64_t)mSize) ? 0LL : mSize - offset;
 
         size_t copy = (available > (off64_t)size) ? size : available;
         memcpy(data, mData + offset, copy);
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 9b2853e..9d46d2d 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -488,7 +488,8 @@
     status_t setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels);
 
     status_t setupFlacCodec(
-            bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel);
+            bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel,
+            AudioEncoding encoding);
 
     status_t setupRawAudioFormat(
             OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels,
diff --git a/media/libstagefright/include/media/stagefright/ColorConverter.h b/media/libstagefright/include/media/stagefright/ColorConverter.h
index 6d4c1bf..75b0d8e 100644
--- a/media/libstagefright/include/media/stagefright/ColorConverter.h
+++ b/media/libstagefright/include/media/stagefright/ColorConverter.h
@@ -90,6 +90,9 @@
     status_t convertYUV420PlanarUseLibYUV(
             const BitmapParams &src, const BitmapParams &dst);
 
+    status_t convertYUV420SemiPlanarUseLibYUV(
+            const BitmapParams &src, const BitmapParams &dst);
+
     status_t convertYUV420Planar16(
             const BitmapParams &src, const BitmapParams &dst);
 
diff --git a/media/libstagefright/include/media/stagefright/MPEG4Writer.h b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
index f18940d..1abef8c 100644
--- a/media/libstagefright/include/media/stagefright/MPEG4Writer.h
+++ b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
@@ -110,6 +110,7 @@
     uint32_t mInterleaveDurationUs;
     int32_t mTimeScale;
     int64_t mStartTimestampUs;
+    int32_t mStartTimeOffsetBFramesUs; // Start time offset when B Frames are present
     int mLatitudex10000;
     int mLongitudex10000;
     bool mAreGeoTagsAvailable;
@@ -129,6 +130,7 @@
 
     void setStartTimestampUs(int64_t timeUs);
     int64_t getStartTimestampUs();  // Not const
+    int32_t getStartTimeOffsetBFramesUs();
     status_t startTracks(MetaData *params);
     size_t numTracks();
     int64_t estimateMoovBoxSize(int32_t bitRate);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 704bfdd..984c23d 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -153,6 +153,35 @@
 constexpr int32_t VP9Level61 = 0x1000;
 constexpr int32_t VP9Level62 = 0x2000;
 
+constexpr int32_t AV1Profile0 = 0x01;
+constexpr int32_t AV1Profile1 = 0x02;
+constexpr int32_t AV1Profile2 = 0x04;
+
+constexpr int32_t AV1Level2  = 0x1;
+constexpr int32_t AV1Level21 = 0x2;
+constexpr int32_t AV1Level22 = 0x4;
+constexpr int32_t AV1Level23 = 0x8;
+constexpr int32_t AV1Level3  = 0x10;
+constexpr int32_t AV1Level31 = 0x20;
+constexpr int32_t AV1Level32 = 0x40;
+constexpr int32_t AV1Level33 = 0x80;
+constexpr int32_t AV1Level4  = 0x100;
+constexpr int32_t AV1Level41 = 0x200;
+constexpr int32_t AV1Level42 = 0x400;
+constexpr int32_t AV1Level43 = 0x800;
+constexpr int32_t AV1Level5  = 0x1000;
+constexpr int32_t AV1Level51 = 0x2000;
+constexpr int32_t AV1Level52 = 0x4000;
+constexpr int32_t AV1Level53 = 0x8000;
+constexpr int32_t AV1Level6  = 0x10000;
+constexpr int32_t AV1Level61 = 0x20000;
+constexpr int32_t AV1Level62 = 0x40000;
+constexpr int32_t AV1Level63 = 0x80000;
+constexpr int32_t AV1Level7  = 0x100000;
+constexpr int32_t AV1Level71 = 0x200000;
+constexpr int32_t AV1Level72 = 0x400000;
+constexpr int32_t AV1Level73 = 0x800000;
+
 constexpr int32_t HEVCProfileMain        = 0x01;
 constexpr int32_t HEVCProfileMain10      = 0x02;
 constexpr int32_t HEVCProfileMainStill   = 0x04;
@@ -273,6 +302,7 @@
 // from MediaFormat.java
 constexpr char MIMETYPE_VIDEO_VP8[] = "video/x-vnd.on2.vp8";
 constexpr char MIMETYPE_VIDEO_VP9[] = "video/x-vnd.on2.vp9";
+constexpr char MIMETYPE_VIDEO_AV1[] = "video/av01";
 constexpr char MIMETYPE_VIDEO_AVC[] = "video/avc";
 constexpr char MIMETYPE_VIDEO_HEVC[] = "video/hevc";
 constexpr char MIMETYPE_VIDEO_MPEG4[] = "video/mp4v-es";
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 84e01f3..ba6631c 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -19,6 +19,7 @@
 #define MEDIA_EXTRACTOR_FACTORY_H_
 
 #include <stdio.h>
+#include <unordered_set>
 
 #include <media/IMediaExtractor.h>
 
@@ -35,6 +36,7 @@
             const sp<DataSource> &source, const char *mime = NULL);
     static void LoadPlugins(const ::std::string& apkPath);
     static status_t dump(int fd, const Vector<String16>& args);
+    static std::unordered_set<std::string> getSupportedTypes();
     static void SetLinkedLibraries(const std::string& linkedLibraries);
 
 private:
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 8dc8d38..f34f9b6 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -96,8 +96,7 @@
 
     bool getCachedDuration(int64_t *durationUs, bool *eos) const;
 
-    status_t getAudioPresentations(size_t trackIdx,
-            AudioPresentationCollection *presentations) const;
+    status_t getAudioPresentations(size_t trackIdx, AudioPresentationCollection *presentations);
 
 protected:
     virtual ~NuMediaExtractor();
diff --git a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
index be911cc..891b9a0 100644
--- a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
+++ b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
@@ -34,8 +34,8 @@
 private:
     void updateVsync() override;
 
-    long mAppVsyncOffset;
-    long mSfVsyncOffset;
+    nsecs_t mAppVsyncOffset;
+    nsecs_t mSfVsyncOffset;
     sp<VsyncTracker> mVsyncTracker;
     sp<ChoreographerThread> mChoreographerThread;
     Mutex mLock;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index e9baa1a..1482072 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -217,6 +217,9 @@
     sp<IDescrambler> mDescrambler;
     AudioPresentationCollection mAudioPresentations;
 
+    // Send audio presentations along with access units.
+    void addAudioPresentations(const sp<ABuffer> &buffer);
+
     // Flush accumulated payload if necessary --- i.e. at EOS or at the start of
     // another payload. event is set if the flushed payload is PES with a sync
     // frame.
@@ -758,21 +761,21 @@
     // reasonable amount of time. To handle the wrap-around, use fancy math
     // to get an extended PTS that is within [-0xffffffff, 0xffffffff]
     // of the latest recovered PTS.
-    if (mLastRecoveredPTS < 0ll) {
+    if (mLastRecoveredPTS < 0LL) {
         // Use the original 33bit number for 1st frame, the reason is that
         // if 1st frame wraps to negative that's far away from 0, we could
         // never start. Only start wrapping around from 2nd frame.
         mLastRecoveredPTS = static_cast<int64_t>(PTS_33bit);
     } else {
         mLastRecoveredPTS = static_cast<int64_t>(
-                ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000ll)
+                ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000LL)
                 & 0xfffffffe00000000ull) | PTS_33bit);
         // We start from 0, but recovered PTS could be slightly below 0.
         // Clamp it to 0 as rest of the pipeline doesn't take negative pts.
         // (eg. video is read first and starts at 0, but audio starts at 0xfffffff0)
-        if (mLastRecoveredPTS < 0ll) {
+        if (mLastRecoveredPTS < 0LL) {
             ALOGI("Clamping negative recovered PTS (%" PRId64 ") to 0", mLastRecoveredPTS);
-            mLastRecoveredPTS = 0ll;
+            mLastRecoveredPTS = 0LL;
         }
     }
 
@@ -822,7 +825,7 @@
 
     int64_t timeUs = (PTS * 100) / 9;
 
-    if (mParser->mAbsoluteTimeAnchorUs >= 0ll) {
+    if (mParser->mAbsoluteTimeAnchorUs >= 0LL) {
         timeUs += mParser->mAbsoluteTimeAnchorUs;
     }
 
@@ -1610,9 +1613,9 @@
                     detailedError = _detailedError;
                 });
 
-        if (!returnVoid.isOk()) {
-            ALOGE("[stream %d] descramble failed, trans=%s",
-                    mElementaryPID, returnVoid.description().c_str());
+        if (!returnVoid.isOk() || status != Status::OK) {
+            ALOGE("[stream %d] descramble failed, trans=%s, status=%d",
+                    mElementaryPID, returnVoid.description().c_str(), status);
             return UNKNOWN_ERROR;
         }
 
@@ -1708,6 +1711,13 @@
     return err;
 }
 
+void ATSParser::Stream::addAudioPresentations(const sp<ABuffer> &buffer) {
+    std::ostringstream outStream(std::ios::out);
+    serializeAudioPresentations(mAudioPresentations, &outStream);
+    sp<ABuffer> ap = ABuffer::CreateAsCopy(outStream.str().data(), outStream.str().size());
+    buffer->meta()->setBuffer("audio-presentation-info", ap);
+}
+
 void ATSParser::Stream::onPayloadData(
         unsigned PTS_DTS_flags, uint64_t PTS, uint64_t /* DTS */,
         unsigned PES_scrambling_control,
@@ -1723,7 +1733,7 @@
 
     ALOGV("onPayloadData mStreamType=0x%02x size: %zu", mStreamType, size);
 
-    int64_t timeUs = 0ll;  // no presentation timestamp available.
+    int64_t timeUs = 0LL;  // no presentation timestamp available.
     if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
         timeUs = mProgram->convertPTSToTimestamp(PTS);
     }
@@ -1758,8 +1768,10 @@
                     }
                 }
                 mSource = new AnotherPacketSource(meta);
+                if (mAudioPresentations.size() > 0) {
+                    addAudioPresentations(accessUnit);
+                }
                 mSource->queueAccessUnit(accessUnit);
-                mSource->convertAudioPresentationInfoToMetadata(mAudioPresentations);
                 ALOGV("onPayloadData: created AnotherPacketSource PID 0x%08x of type 0x%02x",
                         mElementaryPID, mStreamType);
             }
@@ -1771,8 +1783,10 @@
             if (mSource->getFormat() == NULL) {
                 mSource->setFormat(mQueue->getFormat());
             }
+            if (mAudioPresentations.size() > 0) {
+                addAudioPresentations(accessUnit);
+            }
             mSource->queueAccessUnit(accessUnit);
-            mSource->convertAudioPresentationInfoToMetadata(mAudioPresentations);
         }
 
         // Every access unit has a pesStartOffset queued in |mPesStartOffsets|.
@@ -1855,10 +1869,10 @@
 
 ATSParser::ATSParser(uint32_t flags)
     : mFlags(flags),
-      mAbsoluteTimeAnchorUs(-1ll),
+      mAbsoluteTimeAnchorUs(-1LL),
       mTimeOffsetValid(false),
-      mTimeOffsetUs(0ll),
-      mLastRecoveredPTS(-1ll),
+      mTimeOffsetUs(0LL),
+      mLastRecoveredPTS(-1LL),
       mNumTSPacketsParsed(0),
       mNumPCRs(0) {
     mPSISections.add(0 /* PID */, new PSISection);
@@ -1900,7 +1914,7 @@
         if ((mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)
                 && extra->findInt64(
                     kATSParserKeyRecentMediaTimeUs, &mediaTimeUs)) {
-            if (mAbsoluteTimeAnchorUs >= 0ll) {
+            if (mAbsoluteTimeAnchorUs >= 0LL) {
                 mediaTimeUs -= mAbsoluteTimeAnchorUs;
             }
             if (mTimeOffsetValid) {
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index e2c5031..62e3a4b 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -35,7 +35,7 @@
 
 namespace android {
 
-const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs
+const int64_t kNearEOSMarkUs = 2000000LL; // 2 secs
 
 AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
     : mIsAudio(false),
@@ -223,6 +223,12 @@
                     kKeyMpegUserData, 0, mpegUserData->data(), mpegUserData->size());
         }
 
+        sp<ABuffer> ap;
+        if (buffer->meta()->findBuffer("audio-presentation-info", &ap) && ap != NULL) {
+            bufmeta.setData(
+                    kKeyAudioPresentationInfo, 0, ap->data(), ap->size());
+        }
+
         int32_t cryptoMode;
         if (buffer->meta()->findInt32("cryptoMode", &cryptoMode)) {
             int32_t cryptoKey;
@@ -293,7 +299,7 @@
     if (buffer->meta()->findInt32("discontinuity", &discontinuity)){
         ALOGV("queueing a discontinuity with queueAccessUnit");
 
-        mLastQueuedTimeUs = 0ll;
+        mLastQueuedTimeUs = 0LL;
         mEOSResult = OK;
         mLatestEnqueuedMeta = NULL;
 
@@ -697,23 +703,4 @@
     return firstMeta;
 }
 
-void AnotherPacketSource::convertAudioPresentationInfoToMetadata(
-        const AudioPresentationCollection& presentations) {
-    sp<MetaData> meta = getFormat();
-    if (meta == NULL) {
-        return;
-    }
-    if (presentations.empty()) {
-        // Clear audio presentation info in metadata.
-        Mutex::Autolock autoLock(mLock);
-        meta->remove(kKeyAudioPresentationInfo);
-    } else {
-        std::ostringstream outStream(std::ios::out);
-        serializeAudioPresentations(presentations, &outStream);
-        Mutex::Autolock autoLock(mLock);
-        meta->setData(kKeyAudioPresentationInfo, MetaData::TYPE_NONE,
-                outStream.str().data(), outStream.str().size());
-    }
-}
-
 }  // namespace android
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 57a6c33..f4a6acb 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -85,8 +85,6 @@
     void trimBuffersAfterMeta(const sp<AMessage> &meta);
     sp<AMessage> trimBuffersBeforeMeta(const sp<AMessage> &meta);
 
-    void convertAudioPresentationInfoToMetadata(const AudioPresentationCollection &presentations);
-
 protected:
     virtual ~AnotherPacketSource();
 
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index fb8b9fd..b91edcd 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1111,7 +1111,7 @@
     memcpy(accessUnit->data(), mBuffer->data() + 4, payloadSize);
 
     int64_t timeUs = fetchTimestamp(payloadSize + 4);
-    if (timeUs < 0ll) {
+    if (timeUs < 0LL) {
         ALOGE("Negative timeUs");
         return NULL;
     }
@@ -1147,7 +1147,7 @@
         return NULL;
     }
 
-    if (info.mTimestampUs < 0ll) {
+    if (info.mTimestampUs < 0LL) {
         ALOGE("Negative info.mTimestampUs");
         return NULL;
     }
@@ -1317,7 +1317,7 @@
 
     }
 
-    if (timeUs == 0ll) {
+    if (timeUs == 0LL) {
         ALOGV("Returning 0 timestamp");
     }
 
@@ -1460,7 +1460,7 @@
             mBuffer->setRange(0, mBuffer->size() - nextScan);
 
             int64_t timeUs = fetchTimestamp(nextScan);
-            if (timeUs < 0ll) {
+            if (timeUs < 0LL) {
                 ALOGE("Negative timeUs");
                 return NULL;
             }
@@ -1545,7 +1545,7 @@
     mBuffer->setRange(0, mBuffer->size() - frameSize);
 
     int64_t timeUs = fetchTimestamp(frameSize);
-    if (timeUs < 0ll) {
+    if (timeUs < 0LL) {
         ALOGE("Negative timeUs");
         return NULL;
     }
@@ -1732,7 +1732,7 @@
                 mBuffer->setRange(0, mBuffer->size() - offset);
 
                 int64_t timeUs = fetchTimestamp(offset);
-                if (timeUs < 0ll) {
+                if (timeUs < 0LL) {
                     ALOGE("Negative timeUs");
                     return NULL;
                 }
@@ -1929,7 +1929,7 @@
                     mBuffer->setRange(0, size);
 
                     int64_t timeUs = fetchTimestamp(offset);
-                    if (timeUs < 0ll) {
+                    if (timeUs < 0LL) {
                         ALOGE("Negative timeus");
                         return NULL;
                     }
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 68b375a..d7aacff 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -355,9 +355,9 @@
       mQuirks(0),
       mBufferIDCount(0),
       mRestorePtsFailed(false),
-      mMaxTimestampGapUs(0ll),
-      mPrevOriginalTimeUs(-1ll),
-      mPrevModifiedTimeUs(-1ll)
+      mMaxTimestampGapUs(0LL),
+      mPrevOriginalTimeUs(-1LL),
+      mPrevModifiedTimeUs(-1LL)
 {
     mName = ADebug::GetDebugName(name);
     DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
@@ -1948,7 +1948,7 @@
 int64_t OMXNodeInstance::getCodecTimestamp(OMX_TICKS timestamp) {
     int64_t originalTimeUs = timestamp;
 
-    if (mMaxTimestampGapUs > 0ll) {
+    if (mMaxTimestampGapUs > 0LL) {
         /* Cap timestamp gap between adjacent frames to specified max
          *
          * In the scenario of cast mirroring, encoding could be suspended for
@@ -1956,7 +1956,7 @@
          * where encoder's rate control logic produces huge frames after a
          * long period of suspension.
          */
-        if (mPrevOriginalTimeUs >= 0ll) {
+        if (mPrevOriginalTimeUs >= 0LL) {
             int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
             timestamp = (timestampGapUs < mMaxTimestampGapUs ?
                 timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
@@ -1964,7 +1964,7 @@
         ALOGV("IN  timestamp: %lld -> %lld",
             static_cast<long long>(originalTimeUs),
             static_cast<long long>(timestamp));
-    } else if (mMaxTimestampGapUs < 0ll) {
+    } else if (mMaxTimestampGapUs < 0LL) {
         /*
          * Apply a fixed timestamp gap between adjacent frames.
          *
@@ -1972,7 +1972,7 @@
          * on frames could go forward or backward. Some encoders may silently
          * drop frames when it goes backward (or even stay unchanged).
          */
-        if (mPrevOriginalTimeUs >= 0ll) {
+        if (mPrevOriginalTimeUs >= 0LL) {
             timestamp = mPrevModifiedTimeUs - mMaxTimestampGapUs;
         }
         ALOGV("IN  timestamp: %lld -> %lld",
@@ -1983,7 +1983,7 @@
     mPrevOriginalTimeUs = originalTimeUs;
     mPrevModifiedTimeUs = timestamp;
 
-    if (mMaxTimestampGapUs != 0ll && !mRestorePtsFailed) {
+    if (mMaxTimestampGapUs != 0LL && !mRestorePtsFailed) {
         mOriginalTimeUs.add(timestamp, originalTimeUs);
     }
 
@@ -2016,7 +2016,7 @@
 void OMXNodeInstance::codecBufferFilled(omx_message &msg) {
     Mutex::Autolock autoLock(mLock);
 
-    if (mMaxTimestampGapUs == 0ll || mRestorePtsFailed) {
+    if (mMaxTimestampGapUs == 0LL || mRestorePtsFailed) {
         return;
     }
 
diff --git a/media/libstagefright/omx/OMXUtils.cpp b/media/libstagefright/omx/OMXUtils.cpp
index b187035..1b8493a 100644
--- a/media/libstagefright/omx/OMXUtils.cpp
+++ b/media/libstagefright/omx/OMXUtils.cpp
@@ -150,6 +150,8 @@
             "video_decoder.vp8", "video_encoder.vp8" },
         { MEDIA_MIMETYPE_VIDEO_VP9,
             "video_decoder.vp9", "video_encoder.vp9" },
+        { MEDIA_MIMETYPE_VIDEO_AV1,
+            "video_decoder.av1", "video_encoder.av1" },
         { MEDIA_MIMETYPE_AUDIO_RAW,
             "audio_decoder.raw", "audio_encoder.raw" },
         { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 201a5df..b964bc0 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -417,7 +417,7 @@
     if (sessionDesc->getDurationUs(&durationUs)) {
         mFormat->setInt64(kKeyDuration, durationUs);
     } else {
-        mFormat->setInt64(kKeyDuration, -1ll);
+        mFormat->setInt64(kKeyDuration, -1LL);
     }
 
     mInitCheck = OK;
diff --git a/media/libstagefright/rtsp/ARTPAssembler.cpp b/media/libstagefright/rtsp/ARTPAssembler.cpp
index c7a65c2..befc226 100644
--- a/media/libstagefright/rtsp/ARTPAssembler.cpp
+++ b/media/libstagefright/rtsp/ARTPAssembler.cpp
@@ -36,7 +36,7 @@
 
         if (status == WRONG_SEQUENCE_NUMBER) {
             if (mFirstFailureTimeUs >= 0) {
-                if (ALooper::GetNowUs() - mFirstFailureTimeUs > 10000ll) {
+                if (ALooper::GetNowUs() - mFirstFailureTimeUs > 10000LL) {
                     mFirstFailureTimeUs = -1;
 
                     // LOG(VERBOSE) << "waited too long for packet.";
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index a86ab74..6a4706d 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -50,7 +50,7 @@
 }
 
 // static
-const int64_t ARTPConnection::kSelectTimeoutUs = 1000ll;
+const int64_t ARTPConnection::kSelectTimeoutUs = 1000LL;
 
 struct ARTPConnection::StreamInfo {
     int mRTPSocket;
@@ -118,7 +118,7 @@
     bumpSocketBufferSize(*rtcpSocket);
 
     /* rand() * 1000 may overflow int type, use long long */
-    unsigned start = (unsigned)((rand()* 1000ll)/RAND_MAX) + 15550;
+    unsigned start = (unsigned)((rand()* 1000LL)/RAND_MAX) + 15550;
     start &= ~1;
 
     for (unsigned port = start; port < 65536; port += 2) {
@@ -307,7 +307,7 @@
 
     int64_t nowUs = ALooper::GetNowUs();
     if (mLastReceiverReportTimeUs <= 0
-            || mLastReceiverReportTimeUs + 5000000ll <= nowUs) {
+            || mLastReceiverReportTimeUs + 5000000LL <= nowUs) {
         sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
         List<StreamInfo>::iterator it = mStreams.begin();
         while (it != mStreams.end()) {
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 4827cd2..4afa6f4 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -180,7 +180,7 @@
     }
 
     int64_t nowUs = ALooper::GetNowUs();
-    if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000ll > nowUs) {
+    if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000LL > nowUs) {
         // Send FIR requests at most every 5 secs.
         return;
     }
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 49e01c0..4f86773 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -420,10 +420,10 @@
 uint64_t ARTPWriter::GetNowNTP() {
     uint64_t nowUs = ALooper::GetNowUs();
 
-    nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
+    nowUs += ((70LL * 365 + 17) * 24) * 60 * 60 * 1000000LL;
 
-    uint64_t hi = nowUs / 1000000ll;
-    uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
+    uint64_t hi = nowUs / 1000000LL;
+    uint64_t lo = ((1LL << 32) * (nowUs % 1000000LL)) / 1000000LL;
 
     return (hi << 32) | lo;
 }
@@ -576,7 +576,7 @@
     int64_t timeUs;
     CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
 
-    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
 
     const uint8_t *mediaData =
         (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
@@ -671,7 +671,7 @@
     int64_t timeUs;
     CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
 
-    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
 
     const uint8_t *mediaData =
         (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 33c1c18..20cb415 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -39,7 +39,7 @@
 namespace android {
 
 // static
-const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
+const int64_t ARTSPConnection::kSelectTimeoutUs = 1000LL;
 
 // static
 const AString ARTSPConnection::sUserAgent =
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 23269af..4b6f928 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -364,14 +364,14 @@
         // adjust time-stamps after pause/resume
         if (mResumed) {
             int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
-            CHECK_GE(durExcludingEarlierPausesUs, 0ll);
+            CHECK_GE(durExcludingEarlierPausesUs, 0LL);
             int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
             CHECK_GE(pausedDurationUs, lastDurationUs);
             previousPausedDurationUs += pausedDurationUs - lastDurationUs;
             mResumed = false;
         }
         timestampUs -= previousPausedDurationUs;
-        CHECK_GE(timestampUs, 0ll);
+        CHECK_GE(timestampUs, 0LL);
 
         int32_t isSync = false;
         md.findInt32(kKeyIsSyncFrame, &isSync);
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index f7597db..1fbb85e 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -20,7 +20,7 @@
         libmediaplayerservice \
         libutils \
         libbinder \
-        libicuuc \
+        libandroidicu \
         android.hardware.media.omx@1.0 \
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index b86ab42..1a0c3b1 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -357,8 +357,10 @@
               it != mAcquiredImages.end(); it++) {
         AImage* image = *it;
         Mutex::Autolock _l(image->mLock);
-        releaseImageLocked(image, /*releaseFenceFd*/-1);
+        // Do not alter mAcquiredImages while we are iterating on it
+        releaseImageLocked(image, /*releaseFenceFd*/-1, /*clearCache*/false);
     }
+    mAcquiredImages.clear();
 
     // Delete Buffer Items
     for (auto it = mBuffers.begin();
@@ -497,7 +499,7 @@
 }
 
 void
-AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd) {
+AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd, bool clearCache) {
     BufferItem* buffer = image->mBuffer;
     if (buffer == nullptr) {
         // This should not happen, but is not fatal
@@ -521,6 +523,10 @@
     image->mLockedBuffer = nullptr;
     image->mIsClosed = true;
 
+    if (!clearCache) {
+        return;
+    }
+
     bool found = false;
     // cleanup acquired image list
     for (auto it = mAcquiredImages.begin();
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 78152d2..e328cb1 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -88,7 +88,7 @@
     media_status_t acquireImageLocked(/*out*/AImage** image, /*out*/int* fenceFd);
 
     // Called by AImage/~AImageReader to close image. Caller is responsible to grab AImage::mLock
-    void releaseImageLocked(AImage* image, int releaseFenceFd);
+    void releaseImageLocked(AImage* image, int releaseFenceFd, bool clearCache = true);
 
     static int getBufferWidth(BufferItem* buffer);
     static int getBufferHeight(BufferItem* buffer);
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index f697bd1..8296598 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -448,6 +448,16 @@
         meta->setBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, mpegUserData);
     }
 
+    const void *audioPresentationsPointer;
+    size_t audioPresentationsLength;
+    if (sampleMeta->findData(
+            kKeyAudioPresentationInfo, &dataType,
+            &audioPresentationsPointer, &audioPresentationsLength)) {
+        sp<ABuffer> audioPresentationsData = ABuffer::CreateAsCopy(
+                audioPresentationsPointer, audioPresentationsLength);
+        meta->setBuffer(AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, audioPresentationsData);
+    }
+
     return AMEDIA_OK;
 }
 
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 92d3aef..fcb706d 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -298,7 +298,7 @@
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_IV = "crypto-iv";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_KEY = "crypto-key";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_MODE = "crypto-mode";
-EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES = "crypto-encrypted-sizes";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES = "crypto-plain-sizes";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK = "crypto-skip-byte-block";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0";
diff --git a/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl b/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl
index 74897f7..433b12f 100644
--- a/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl
+++ b/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl
@@ -48,9 +48,9 @@
     PendingIntent getLaunchPendingIntent();
     long getFlags();
     ParcelableVolumeInfo getVolumeAttributes();
-    void adjustVolume(String packageName, ISessionControllerCallback caller,
+    void adjustVolume(String packageName, String opPackageName, ISessionControllerCallback caller,
             boolean asSystemService, int direction, int flags);
-    void setVolumeTo(String packageName, ISessionControllerCallback caller,
+    void setVolumeTo(String packageName, String opPackageName, ISessionControllerCallback caller,
             int value, int flags);
 
     // These commands are for the TransportControls
diff --git a/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl b/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl
index 3578c16..d6c226f 100644
--- a/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl
+++ b/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl
@@ -17,7 +17,6 @@
 
 import android.content.ComponentName;
 import android.media.IRemoteVolumeController;
-import android.media.ISessionTokensListener;
 import android.media.session.IActiveSessionsListener;
 import android.media.session.ICallback;
 import android.media.session.IOnMediaKeyListener;
@@ -36,9 +35,10 @@
     List<IBinder> getSessions(in ComponentName compName, int userId);
     void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
             boolean needWakeLock);
-    void dispatchVolumeKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
-            int stream, boolean musicOnly);
-    void dispatchAdjustVolume(String packageName, int suggestedStream, int delta, int flags);
+    void dispatchVolumeKeyEvent(String packageName, String opPackageName, boolean asSystemService,
+            in KeyEvent keyEvent, int stream, boolean musicOnly);
+    void dispatchAdjustVolume(String packageName, String opPackageName, int suggestedStream,
+            int delta, int flags);
     void addSessionsListener(in IActiveSessionsListener listener, in ComponentName compName,
             int userId);
     void removeSessionsListener(in IActiveSessionsListener listener);
@@ -55,12 +55,4 @@
 
     // MediaSession2
     boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid);
-    boolean createSession2(in Bundle sessionToken);
-    void destroySession2(in Bundle sessionToken);
-    List<Bundle> getSessionTokens(boolean activeSessionOnly, boolean sessionServiceOnly,
-            String packageName);
-
-    void addSessionTokensListener(in ISessionTokensListener listener, int userId,
-            String packageName);
-    void removeSessionTokensListener(in ISessionTokensListener listener, String packageName);
 }
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaController.java b/packages/MediaComponents/apex/java/android/media/session/MediaController.java
index 8c3a013..65682a8 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaController.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaController.java
@@ -153,9 +153,7 @@
             return false;
         }
         try {
-            //TODO(b/119748678): Resolve mContext.getOpPackageName() through this file.
-            // Temporarilly it's replaced with "mContext.getOpPackageName()" for compiling.
-            return mSessionBinder.sendMediaButton("mContext.getOpPackageName()", mCbStub,
+            return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub,
                     asSystemService, keyEvent);
         } catch (RemoteException e) {
             // System is dead. =(
@@ -188,8 +186,9 @@
                         break;
                 }
                 try {
-                    mSessionBinder.adjustVolume("mContext.getOpPackageName()", mCbStub, true,
-                            direction, AudioManager.FLAG_SHOW_UI);
+                    mSessionBinder.adjustVolume(mContext.getPackageName(),
+                            mContext.getOpPackageName(), mCbStub, true, direction,
+                            AudioManager.FLAG_SHOW_UI);
                 } catch (RemoteException e) {
                     Log.wtf(TAG, "Error calling adjustVolumeBy", e);
                 }
@@ -199,8 +198,8 @@
                 final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
                         | AudioManager.FLAG_FROM_KEY;
                 try {
-                    mSessionBinder.adjustVolume("mContext.getOpPackageName()", mCbStub, true, 0,
-                            flags);
+                    mSessionBinder.adjustVolume(mContext.getPackageName(),
+                            mContext.getOpPackageName(), mCbStub, true, 0, flags);
                 } catch (RemoteException e) {
                     Log.wtf(TAG, "Error calling adjustVolumeBy", e);
                 }
@@ -369,7 +368,8 @@
      */
     public void setVolumeTo(int value, int flags) {
         try {
-            mSessionBinder.setVolumeTo("mContext.getOpPackageName()", mCbStub, value, flags);
+            mSessionBinder.setVolumeTo(mContext.getPackageName(), mContext.getOpPackageName(),
+                    mCbStub, value, flags);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling setVolumeTo.", e);
         }
@@ -390,8 +390,8 @@
      */
     public void adjustVolume(int direction, int flags) {
         try {
-            mSessionBinder.adjustVolume("mContext.getOpPackageName()", mCbStub, false, direction,
-                    flags);
+            mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
+                    mCbStub, false, direction, flags);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
         }
@@ -457,7 +457,7 @@
             throw new IllegalArgumentException("command cannot be null or empty");
         }
         try {
-            mSessionBinder.sendCommand("mContext.getOpPackageName()", mCbStub, command, args, cb);
+            mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
         } catch (RemoteException e) {
             Log.d(TAG, "Dead object in sendCommand.", e);
         }
@@ -523,7 +523,7 @@
 
         if (!mCbRegistered) {
             try {
-                mSessionBinder.registerCallbackListener("mContext.getOpPackageName()", mCbStub);
+                mSessionBinder.registerCallbackListener(mContext.getPackageName(), mCbStub);
                 mCbRegistered = true;
             } catch (RemoteException e) {
                 Log.e(TAG, "Dead object in registerCallback", e);
@@ -670,7 +670,7 @@
          */
         public void prepare() {
             try {
-                mSessionBinder.prepare("mContext.getOpPackageName()", mCbStub);
+                mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare.", e);
             }
@@ -694,7 +694,7 @@
                         "You must specify a non-empty String for prepareFromMediaId.");
             }
             try {
-                mSessionBinder.prepareFromMediaId("mContext.getOpPackageName()", mCbStub, mediaId,
+                mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
                         extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
@@ -721,7 +721,7 @@
                 query = "";
             }
             try {
-                mSessionBinder.prepareFromSearch("mContext.getOpPackageName()", mCbStub, query,
+                mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query,
                         extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
@@ -746,7 +746,7 @@
                         "You must specify a non-empty Uri for prepareFromUri.");
             }
             try {
-                mSessionBinder.prepareFromUri("mContext.getOpPackageName()", mCbStub, uri, extras);
+                mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
             }
@@ -757,7 +757,7 @@
          */
         public void play() {
             try {
-                mSessionBinder.play("mContext.getOpPackageName()", mCbStub);
+                mSessionBinder.play(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play.", e);
             }
@@ -776,7 +776,7 @@
                         "You must specify a non-empty String for playFromMediaId.");
             }
             try {
-                mSessionBinder.playFromMediaId("mContext.getOpPackageName()", mCbStub, mediaId,
+                mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
                         extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
@@ -799,7 +799,7 @@
                 query = "";
             }
             try {
-                mSessionBinder.playFromSearch("mContext.getOpPackageName()", mCbStub, query, extras);
+                mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + query + ").", e);
             }
@@ -818,7 +818,7 @@
                         "You must specify a non-empty Uri for playFromUri.");
             }
             try {
-                mSessionBinder.playFromUri("mContext.getOpPackageName()", mCbStub, uri, extras);
+                mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + uri + ").", e);
             }
@@ -830,7 +830,7 @@
          */
         public void skipToQueueItem(long id) {
             try {
-                mSessionBinder.skipToQueueItem("mContext.getOpPackageName()", mCbStub, id);
+                mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
             }
@@ -842,7 +842,7 @@
          */
         public void pause() {
             try {
-                mSessionBinder.pause("mContext.getOpPackageName()", mCbStub);
+                mSessionBinder.pause(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling pause.", e);
             }
@@ -854,7 +854,7 @@
          */
         public void stop() {
             try {
-                mSessionBinder.stop("mContext.getOpPackageName()", mCbStub);
+                mSessionBinder.stop(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling stop.", e);
             }
@@ -867,7 +867,7 @@
          */
         public void seekTo(long pos) {
             try {
-                mSessionBinder.seekTo("mContext.getOpPackageName()", mCbStub, pos);
+                mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling seekTo.", e);
             }
@@ -879,7 +879,7 @@
          */
         public void fastForward() {
             try {
-                mSessionBinder.fastForward("mContext.getOpPackageName()", mCbStub);
+                mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling fastForward.", e);
             }
@@ -890,7 +890,7 @@
          */
         public void skipToNext() {
             try {
-                mSessionBinder.next("mContext.getOpPackageName()", mCbStub);
+                mSessionBinder.next(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling next.", e);
             }
@@ -902,7 +902,7 @@
          */
         public void rewind() {
             try {
-                mSessionBinder.rewind("mContext.getOpPackageName()", mCbStub);
+                mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling rewind.", e);
             }
@@ -913,7 +913,7 @@
          */
         public void skipToPrevious() {
             try {
-                mSessionBinder.previous("mContext.getOpPackageName()", mCbStub);
+                mSessionBinder.previous(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling previous.", e);
             }
@@ -928,7 +928,7 @@
          */
         public void setRating(Rating rating) {
             try {
-                mSessionBinder.rate("mContext.getOpPackageName()", mCbStub, rating);
+                mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling rate.", e);
             }
@@ -963,7 +963,7 @@
                 throw new IllegalArgumentException("CustomAction cannot be null.");
             }
             try {
-                mSessionBinder.sendCustomAction("mContext.getOpPackageName()", mCbStub, action, args);
+                mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
             } catch (RemoteException e) {
                 Log.d(TAG, "Dead object in sendCustomAction.", e);
             }
@@ -1142,8 +1142,7 @@
         private boolean mRegistered = false;
 
         public MessageHandler(Looper looper, MediaController.Callback cb) {
-            //TODO:(b/119539849) Uncomment below line and resolve the error.
-            // super(looper, null, true);
+            super(looper);
             mCallback = cb;
         }
 
@@ -1182,6 +1181,7 @@
 
         public void post(int what, Object obj, Bundle data) {
             Message msg = obtainMessage(what, obj);
+            msg.setAsynchronous(true);
             msg.setData(data);
             msg.sendToTarget();
         }
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
index 943843d..73e16a6 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
@@ -1458,8 +1458,7 @@
         private RemoteUserInfo mCurrentControllerInfo;
 
         public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {
-            //TODO:(b/119539849) Uncomment below line and resolve the error.
-            //super(looper, null, true);
+            super(looper);
             mCallback = callback;
             mCallback.mHandler = this;
         }
@@ -1467,6 +1466,7 @@
         public void post(RemoteUserInfo caller, int what, Object obj, Bundle data, long delayMs) {
             Pair<RemoteUserInfo, Object> objWithCaller = Pair.create(caller, obj);
             Message msg = obtainMessage(what, objWithCaller);
+            msg.setAsynchronous(true);
             msg.setData(data);
             if (delayMs > 0) {
                 sendMessageDelayed(msg, delayMs);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c6941c0..989e6eb 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3850,6 +3850,7 @@
         type |= patch->sinks[i].ext.device.type;
     }
 
+    audio_port_handle_t sinkPortId = patch->sinks[0].id;
 #ifdef ADD_BATTERY_DATA
     // when changing the audio output device, call addBatteryData to notify
     // the change
@@ -3879,7 +3880,7 @@
 
     // mPrevOutDevice is the latest device set by createAudioPatch_l(). It is not set when
     // the thread is created so that the first patch creation triggers an ioConfigChanged callback
-    bool configChanged = mPrevOutDevice != type;
+    bool configChanged = (mPrevOutDevice != type) || (mDeviceId != sinkPortId);
     mOutDevice = type;
     mPatch = *patch;
 
@@ -3908,6 +3909,7 @@
     }
     if (configChanged) {
         mPrevOutDevice = type;
+        mDeviceId = sinkPortId;
         sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
     }
     return status;
@@ -8145,6 +8147,7 @@
 
     // store new device and send to effects
     mInDevice = patch->sources[0].ext.device.type;
+    audio_port_handle_t deviceId = patch->sources[0].id;
     mPatch = *patch;
     for (size_t i = 0; i < mEffectChains.size(); i++) {
         mEffectChains[i]->setDevice_l(mInDevice);
@@ -8186,9 +8189,10 @@
         *handle = AUDIO_PATCH_HANDLE_NONE;
     }
 
-    if (mInDevice != mPrevInDevice) {
+    if ((mInDevice != mPrevInDevice) || (mDeviceId != deviceId)) {
         sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
         mPrevInDevice = mInDevice;
+        mDeviceId = deviceId;
     }
 
     return status;
@@ -8285,7 +8289,7 @@
         audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
     : ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
       mSessionId(AUDIO_SESSION_NONE),
-      mDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE),
+      mPortId(AUDIO_PORT_HANDLE_NONE),
       mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
       mActiveTracks(&this->mLocalLog),
       mHalVolFloat(-1.0f), // Initialize to illegal value so it always gets set properly later.
@@ -8769,7 +8773,7 @@
         *handle = AUDIO_PATCH_HANDLE_NONE;
     }
 
-    if (isOutput() && mPrevOutDevice != mOutDevice) {
+    if (isOutput() && (mPrevOutDevice != mOutDevice || mDeviceId != deviceId)) {
         mPrevOutDevice = type;
         sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
         sp<MmapStreamCallback> callback = mCallback.promote();
@@ -8780,7 +8784,7 @@
         }
         mDeviceId = deviceId;
     }
-    if (!isOutput() && mPrevInDevice != mInDevice) {
+    if (!isOutput() && (mPrevInDevice != mInDevice || mDeviceId != deviceId)) {
         mPrevInDevice = type;
         sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
         sp<MmapStreamCallback> callback = mCallback.promote();
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index e8b2158..5d06773 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -485,6 +485,10 @@
                 audio_devices_t         mPrevOutDevice;   // previous output device
                 audio_devices_t         mPrevInDevice;    // previous input device
                 struct audio_patch      mPatch;
+                /**
+                 * @brief mDeviceId  current device port unique identifier
+                 */
+                audio_port_handle_t     mDeviceId = AUDIO_PORT_HANDLE_NONE;
                 audio_source_t          mAudioSource;
 
                 const audio_io_handle_t mId;
@@ -1704,7 +1708,6 @@
 
                 audio_attributes_t      mAttr;
                 audio_session_t         mSessionId;
-                audio_port_handle_t     mDeviceId;
                 audio_port_handle_t     mPortId;
 
                 wp<MmapStreamCallback>  mCallback;
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index bfa1b5e..ebb4f3b 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -51,6 +51,7 @@
     libcutils \
     libutils \
     liblog \
+    libaudioclient \
     libsoundtrigger
 
 ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
@@ -85,7 +86,7 @@
 LOCAL_SHARED_LIBRARIES += libmedia_helper
 LOCAL_SHARED_LIBRARIES += libmediametrics
 
-LOCAL_SHARED_LIBRARIES += libhidlbase libicuuc libxml2
+LOCAL_SHARED_LIBRARIES += libhidlbase libxml2
 
 ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
 LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index ad12a90..1c2b9d7 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -210,6 +210,10 @@
     virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes) = 0;
     virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes) = 0;
 
+    virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+            = 0;
+    virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
+
     virtual status_t startAudioSource(const struct audio_port_config *source,
                                       const audio_attributes_t *attributes,
                                       audio_port_handle_t *portId,
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index d0b4973..e5ebab7 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -24,7 +24,6 @@
     shared_libs: [
         "libcutils",
         "libhidlbase",
-        "libicuuc",
         "liblog",
         "libmedia",
         "libutils",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 96c00ea..955e87b 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -80,6 +80,10 @@
 
     status_t getInputMixForAttr(audio_attributes_t attr, AudioMix **policyMix);
 
+    status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+    status_t removeUidDeviceAffinities(uid_t uid);
+    status_t getDevicesForUid(uid_t uid, Vector<AudioDeviceTypeAddr>& devices) const;
+
     void dump(String8 *dst) const;
 };
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 3cf8014..776d98f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -340,6 +340,87 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyMixCollection::setUidDeviceAffinities(uid_t uid,
+        const Vector<AudioDeviceTypeAddr>& devices) {
+    // remove existing rules for this uid
+    removeUidDeviceAffinities(uid);
+
+    // for each player mix: add a rule to match or exclude the uid based on the device
+    for (size_t i = 0; i < size(); i++) {
+        const AudioMix *mix = valueAt(i)->getMix();
+        if (mix->mMixType != MIX_TYPE_PLAYERS) {
+            continue;
+        }
+        // check if this mix goes to a device in the list of devices
+        bool deviceMatch = false;
+        for (size_t j = 0; j < devices.size(); j++) {
+            if (devices[j].mType == mix->mDeviceType
+                    && devices[j].mAddress == mix->mDeviceAddress) {
+                deviceMatch = true;
+                break;
+            }
+        }
+        if (!deviceMatch) {
+            // this mix doesn't go to one of the listed devices for the given uid,
+            // modify its rules to exclude the uid
+            mix->excludeUid(uid);
+        }
+    }
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::removeUidDeviceAffinities(uid_t uid) {
+    // for each player mix: remove existing rules that match or exclude this uid
+    for (size_t i = 0; i < size(); i++) {
+        bool foundUidRule = false;
+        AudioMix *mix = valueAt(i)->getMix();
+        if (mix->mMixType != MIX_TYPE_PLAYERS) {
+            continue;
+        }
+        std::vector<size_t> criteriaToRemove;
+        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+            const uint32_t rule = mix->mCriteria[j].mRule;
+            // is this rule affecting the uid?
+            if (rule == RULE_EXCLUDE_UID
+                    && uid == mix->mCriteria[j].mValue.mUid) {
+                foundUidRule = true;
+                criteriaToRemove.push_back(j);
+            }
+        }
+        if (foundUidRule) {
+            for (size_t j = criteriaToRemove.size() - 1; j >= 0; j--) {
+                mix->mCriteria.removeAt(criteriaToRemove[j]);
+            }
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::getDevicesForUid(uid_t uid,
+        Vector<AudioDeviceTypeAddr>& devices) const {
+    // for each player mix: find rules that don't exclude this uid, and add the device to the list
+    for (size_t i = 0; i < size(); i++) {
+        bool ruleAllowsUid = true;
+        AudioMix *mix = valueAt(i)->getMix();
+        if (mix->mMixType != MIX_TYPE_PLAYERS) {
+            continue;
+        }
+        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+            const uint32_t rule = mix->mCriteria[j].mRule;
+            if (rule == RULE_EXCLUDE_UID
+                    && uid == mix->mCriteria[j].mValue.mUid) {
+                ruleAllowsUid = false;
+                break;
+            }
+        }
+        if (ruleAllowsUid) {
+            devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress));
+        }
+    }
+    return NO_ERROR;
+}
+
 void AudioPolicyMixCollection::dump(String8 *dst) const
 {
     dst->append("\nAudio Policy Mix:\n");
diff --git a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
index a597e87..efc69da 100644
--- a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
+++ b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
@@ -19,10 +19,8 @@
 class AudioPolicyManagerInterface;
 class AudioPolicyPluginInterface;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 class Engine;
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
index baaefd2..7631976 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
@@ -7,15 +7,19 @@
 #
 ################################################################################################
 
-ifeq (1, 0)
-
 LOCAL_PATH := $(call my-dir)
 
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
+
 PFW_CORE := external/parameter-framework
-BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
+#@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
+
 ##################################################################
 # CONFIGURATION FILES
 ##################################################################
@@ -25,7 +29,8 @@
 LOCAL_MODULE := ParameterFrameworkConfigurationPolicy.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework
 LOCAL_SRC_FILES := $(LOCAL_MODULE).in
 
 AUDIO_PATTERN = @TUNING_ALLOWED@
@@ -46,7 +51,8 @@
 LOCAL_MODULE := PolicyClass.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
 LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
 
@@ -54,12 +60,12 @@
 LOCAL_MODULE := PolicySubsystem.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
 LOCAL_REQUIRED_MODULES := \
     PolicySubsystem-CommonTypes.xml \
-    PolicySubsystem-Volume.xml \
-    libpolicy-subsystem \
+    libpolicy-subsystem
 
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
 LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
 
@@ -67,7 +73,8 @@
 LOCAL_MODULE := PolicySubsystem-CommonTypes.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
 LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
 
@@ -76,15 +83,16 @@
 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_ADDITIONAL_DEPENDENCIES := \
-        PolicyClass.xml \
-        PolicySubsystem.xml \
-        ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+    policy_criteria.xml \
+    policy_criterion_types.xml \
+    PolicySubsystem.xml \
+    PolicyClass.xml \
+    ParameterFrameworkConfigurationPolicy.xml
 
 ifeq ($(pfw_rebuild_settings),true)
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
 PFW_EDD_FILES := \
         $(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
         $(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -100,6 +108,17 @@
         $(LOCAL_PATH)/Settings/device_for_input_source.pfw \
         $(LOCAL_PATH)/Settings/volumes.pfw
 
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+    $(PFW_EDD_FILES)
+
+
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
+
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+
 include $(BUILD_PFW_SETTINGS)
 else
 # Use the existing file
@@ -107,19 +126,27 @@
 include $(BUILD_PREBUILT)
 endif # pfw_rebuild_settings
 
+endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 0)
+
 ######### Policy PFW Settings - No Output #########
+ifeq (0, 1)
+
 include $(CLEAR_VARS)
 LOCAL_MODULE := parameter-framework.policy.no-output
 LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoOutputDevice.xml
 LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-        PolicyClass.xml \
-        PolicySubsystem.xml \
-        ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+    policy_criteria.xml \
+    policy_criterion_types.xml \
+    PolicySubsystem.xml \
+    PolicyClass.xml \
+    ParameterFrameworkConfigurationPolicy.xml
 
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
 PFW_EDD_FILES := \
         $(LOCAL_PATH)/SettingsNoOutput/device_for_strategies.pfw \
         $(LOCAL_PATH)/Settings/strategy_for_stream.pfw \
@@ -128,20 +155,26 @@
         $(LOCAL_PATH)/Settings/volumes.pfw
 
 include $(BUILD_PFW_SETTINGS)
-
+endif # ifeq (0, 1)
 ######### Policy PFW Settings - No Input #########
+ifeq (0, 1)
+
 include $(CLEAR_VARS)
 LOCAL_MODULE := parameter-framework.policy.no-input
 LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoInputDevice.xml
 LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-        PolicyClass.xml \
-        PolicySubsystem.xml \
-        ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+    policy_criteria.xml \
+    policy_criterion_types.xml \
+    PolicySubsystem.xml \
+    PolicyClass.xml \
+    ParameterFrameworkConfigurationPolicy.xml
 
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
 PFW_EDD_FILES := \
         $(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
         $(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -160,3 +193,9 @@
 include $(BUILD_PFW_SETTINGS)
 
 endif # ifeq (1, 0)
+
+#######################################################################
+# Recursive call sub-folder Android.mk
+#######################################################################
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
index f5615cd..f80a07f 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    SystemClassName="Policy" ServerPort="5019" TuningAllowed="@TUNING_ALLOWED@">
+    SystemClassName="Policy" ServerPort="/dev/socket/audioserver/policy_debug"
+    TuningAllowed="@TUNING_ALLOWED@">
 
     <SubsystemPlugins>
         <Location Folder="">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
index b43f83b..0710441 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
@@ -8472,7 +8472,7 @@
     <Configurations>
       <Configuration Name="Sonification">
         <CompoundRule Type="All">
-          <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="RingTone"/>
+          <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="Ringtone"/>
         </CompoundRule>
       </Configuration>
       <Configuration Name="Phone">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
index b3115e7..fbea9e2 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
@@ -24,7 +24,7 @@
 			# In case of Ring or Alarm stream type active, switching to sonification
 			# @todo: handle this dynamic case. As a WA, using Ringtone mode...
 			#
-			TelephonyMode Is RingTone
+			TelephonyMode Is Ringtone
 
 			/Policy/policy/usages/assistance_accessibility/applicable_strategy/strategy = sonification
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
index 917d4a7..f923610 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
@@ -9,7 +9,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -37,7 +37,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -65,7 +65,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -93,7 +93,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -121,7 +121,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -149,7 +149,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -177,7 +177,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -205,7 +205,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -233,7 +233,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
index 461e44a..daa7f68 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
@@ -37,6 +37,10 @@
             <BitParameter Name="speaker_safe" Size="1" Pos="22"/>
             <BitParameter Name="ip" Size="1" Pos="23"/>
             <BitParameter Name="bus" Size="1" Pos="24"/>
+            <BitParameter Name="proxy" Size="1" Pos="25"/>
+            <BitParameter Name="usb_headset" Size="1" Pos="26"/>
+            <BitParameter Name="hearing_aid" Size="1" Pos="27"/>
+            <BitParameter Name="echo_canceller" Size="1" Pos="28"/>
             <BitParameter Name="stub" Size="1" Pos="30"/>
         </BitParameterBlock>
     </ComponentType>
@@ -67,6 +71,9 @@
             <BitParameter Name="loopback" Size="1" Pos="18"/>
             <BitParameter Name="ip" Size="1" Pos="19"/>
             <BitParameter Name="bus" Size="1" Pos="20"/>
+            <BitParameter Name="proxy" Size="1" Pos="21"/>
+            <BitParameter Name="usb_headset" Size="1" Pos="22"/>
+            <BitParameter Name="bluetooth_ble" Size="1" Pos="23"/>
             <BitParameter Name="stub" Size="1" Pos="30"/>
         </BitParameterBlock>
     </ComponentType>
@@ -144,7 +151,7 @@
 
     <!--#################### STRATEGY COMMON TYPES BEGIN ####################-->
 
-    <ComponentType Name="StrategyConfig" Mapping="Strategy:'%1'">
+    <ComponentType Name="StrategyConfig" Mapping="Strategy">
         <Component Name="selected_output_devices" Type="OutputDevicesMask"/>
     </ComponentType>
 
@@ -170,7 +177,7 @@
         </EnumParameter>
     </ComponentType>
 
-    <ComponentType Name="Stream">
+    <ComponentType Name="Stream"  Mapping="Stream">
         <Component Name="applicable_strategy" Type="Strategy"/>
         <Component Name="applicable_volume_profile" Type="VolumeProfileType"
                    Description="Volume profile followed by a given stream type."/>
@@ -181,7 +188,7 @@
     <!--#################### USAGE COMMON TYPES BEGIN ####################-->
 
     <ComponentType Name="Usage">
-        <Component Name="applicable_strategy" Type="Strategy" Mapping="Usage:'%1'"/>
+        <Component Name="applicable_strategy" Type="Strategy" Mapping="Usage"/>
     </ComponentType>
 
     <!--#################### USAGE COMMON TYPES END ####################-->
@@ -190,7 +197,7 @@
 
     <ComponentType Name="InputSource">
         <Component Name="applicable_input_device" Type="InputDevicesMask"
-                   Mapping="InputSource:'%1'" Description="Selected Input device"/>
+                   Mapping="InputSource" Description="Selected Input device"/>
     </ComponentType>
 
     <!--#################### INPUT SOURCE COMMON TYPES END ####################-->
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
index ad9c356..45d1e8a 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
@@ -13,54 +13,40 @@
 
         <!--#################### STRATEGY BEGIN ####################-->
 
-        <ComponentType Name="Strategies" Description="Identifier must match the enum value to make
-                             the link between the PolicyManager and PFW">
-            <Component Name="media" Type="StrategyConfig" Mapping="Amend1:Media,Identifier:0"/>
-            <Component Name="phone" Type="StrategyConfig" Mapping="Amend1:Phone,Identifier:1"/>
-            <Component Name="sonification" Type="StrategyConfig"
-                                           Mapping="Amend1:Sonification,Identifier:2"/>
-            <Component Name="sonification_respectful" Type="StrategyConfig"
-                       Mapping="Amend1:SonificationRespectful,Identifier:3"/>
-            <Component Name="dtmf" Type="StrategyConfig" Mapping="Amend1:Dtmf,Identifier:4"/>
-            <Component Name="enforced_audible" Type="StrategyConfig"
-                                               Mapping="Amend1:EnforcedAudible,Identifier:5"/>
-            <Component Name="transmitted_through_speaker" Type="StrategyConfig"
-                       Mapping="Amend1:TransmittedThroughSpeaker,Identifier:6"/>
-            <Component Name="accessibility" Type="StrategyConfig"
-                                            Mapping="Amend1:Accessibility,Identifier:7"/>
-            <Component Name="rerouting" Type="StrategyConfig"
-                                        Mapping="Amend1:Rerouting,Identifier:8"/>
+        <ComponentType Name="Strategies">
+            <Component Name="media" Type="StrategyConfig" Mapping="Name:STRATEGY_MEDIA"/>
+            <Component Name="phone" Type="StrategyConfig" Mapping="Name:STRATEGY_PHONE"/>
+            <Component Name="sonification" Type="StrategyConfig" Mapping="Name:STRATEGY_SONIFICATION"/>
+            <Component Name="sonification_respectful" Type="StrategyConfig" Mapping="Name:STRATEGY_SONIFICATION_RESPECTFUL"/>
+            <Component Name="dtmf" Type="StrategyConfig" Mapping="Name:STRATEGY_DTMF"/>
+            <Component Name="enforced_audible" Type="StrategyConfig" Mapping="Name:STRATEGY_ENFORCED_AUDIBLE"/>
+            <Component Name="transmitted_through_speaker" Type="StrategyConfig" Mapping="Name:STRATEGY_TRANSMITTED_THROUGH_SPEAKER"/>
+            <Component Name="accessibility" Type="StrategyConfig" Mapping="Name:STRATEGY_ACCESSIBILITY"/>
+            <Component Name="rerouting" Type="StrategyConfig" Mapping=",Name:STRATEGY_REROUTING"/>
         </ComponentType>
 
         <!--#################### STRATEGY END ####################-->
 
         <!--#################### STREAM BEGIN ####################-->
 
-        <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition,
-                             identifier mapping must match the value of the enum">
-            <Component Name="voice_call" Type="Stream" Mapping="Stream:VoiceCall,Identifier:0"/>
-            <Component Name="system" Type="Stream" Mapping="Stream:System,Identifier:1"/>
-            <Component Name="ring" Type="Stream" Mapping="Stream:Ring,Identifier:2"/>
-            <Component Name="music" Type="Stream" Mapping="Stream:Music,Identifier:3"/>
-            <Component Name="alarm" Type="Stream" Mapping="Stream:Alarm,Identifier:4"/>
-            <Component Name="notification" Type="Stream"
-                                           Mapping="Stream:Notification,Identifier:5"/>
-            <Component Name="bluetooth_sco" Type="Stream"
-                                            Mapping="Stream:BluetoothSco,Identifier:6"/>
-            <Component Name="enforced_audible" Type="Stream"
-                                               Mapping="Stream:EnforceAudible,Identifier:7"
-                       Description="Sounds that cannot be muted by user and must
-                                    be routed to speaker"/>
-            <Component Name="dtmf" Type="Stream" Mapping="Stream:Dtmf,Identifier:8"/>
-            <Component Name="tts" Type="Stream" Mapping="Stream:Tts,Identifier:9"
-                             Description="Transmitted Through Speaker.
-                                          Plays over speaker only, silent on other devices"/>
-            <Component Name="accessibility" Type="Stream"
-                                            Mapping="Stream:Accessibility,Identifier:10"
+        <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition">
+            <Component Name="voice_call" Type="Stream" Mapping="Name:AUDIO_STREAM_VOICE_CALL"/>
+            <Component Name="system" Type="Stream" Mapping="Name:AUDIO_STREAM_SYSTEM"/>
+            <Component Name="ring" Type="Stream" Mapping="Name:AUDIO_STREAM_RING"/>
+            <Component Name="music" Type="Stream" Mapping="Name:AUDIO_STREAM_MUSIC"/>
+            <Component Name="alarm" Type="Stream" Mapping="Name:AUDIO_STREAM_ALARM"/>
+            <Component Name="notification" Type="Stream" Mapping="Name:AUDIO_STREAM_NOTIFICATION"/>
+            <Component Name="bluetooth_sco" Type="Stream" Mapping="Name:AUDIO_STREAM_BLUETOOTH_SCO"/>
+            <Component Name="enforced_audible" Type="Stream" Mapping="Name:AUDIO_STREAM_ENFORCED_AUDIBLE"
+                       Description="Sounds that cannot be muted by user and must be routed to speaker"/>
+            <Component Name="dtmf" Type="Stream" Mapping="Name:AUDIO_STREAM_DTMF"/>
+            <Component Name="tts" Type="Stream" Mapping="Name:AUDIO_STREAM_TTS"
+                             Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
+            <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
                              Description="For accessibility talk back prompts"/>
-            <Component Name="rerouting" Type="Stream" Mapping="Stream:Rerouting,Identifier:11"
+            <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
                              Description="For dynamic policy output mixes"/>
-            <Component Name="patch" Type="Stream" Mapping="Stream:Patch,Identifier:12"
+            <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
                              Description="For internal audio flinger tracks. Fixed volume"/>
         </ComponentType>
 
@@ -68,36 +54,34 @@
 
         <!--#################### USAGE BEGIN ####################-->
 
-        <ComponentType Name="Usages" Description="associated to audio_usage_t definition,
-                             identifier mapping must match the value of the enum">
-            <Component Name="unknown" Type="Usage" Mapping="Amend1:Unknown,Identifier:0"/>
-            <Component Name="media" Type="Usage" Mapping="Amend1:Media,Identifier:1"/>
+        <ComponentType Name="Usages" Description="associated to audio_usage_t definition">
+            <Component Name="unknown" Type="Usage" Mapping="Name:AUDIO_USAGE_UNKNOWN"/>
+            <Component Name="media" Type="Usage" Mapping="Name:AUDIO_USAGE_MEDIA"/>
             <Component Name="voice_communication" Type="Usage"
-                                                  Mapping="Amend1:VoiceCommunication,Identifier:2"/>
+                       Mapping="Name:AUDIO_USAGE_VOICE_COMMUNICATION"/>
             <Component Name="voice_communication_signalling" Type="Usage"
-                       Mapping="Amend1:VoiceCommunicationSignalling,Identifier:3"/>
-            <Component Name="alarm" Type="Usage" Mapping="Amend1:Alarm,Identifier:4"/>
-            <Component Name="notification" Type="Usage" Mapping="Amend1:Notification,Identifier:5"/>
+                       Mapping="Name:AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/>
+            <Component Name="alarm" Type="Usage" Mapping="Name:AUDIO_USAGE_ALARM"/>
+            <Component Name="notification" Type="Usage" Mapping="Name:AUDIO_USAGE_NOTIFICATION"/>
             <Component Name="notification_telephony_ringtone" Type="Usage"
-                       Mapping="Amend1:NotificationTelephonyRingtone,Identifier:6"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
             <Component Name="notification_communication_request" Type="Usage"
-                       Mapping="Amend1:NotificationCommunicationRequest,Identifier:7"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/>
             <Component Name="notification_communication_instant" Type="Usage"
-                       Mapping="Amend1:NotificationCommunicationInstant,Identifier:8"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/>
             <Component Name="notification_communication_delayed" Type="Usage"
-                       Mapping="Amend1:NotificationCommunicationDelated,Identifier:9"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/>
             <Component Name="notification_event" Type="Usage"
-                                                 Mapping="Amend1:NotificationEvent,Identifier:10"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_EVENT"/>
             <Component Name="assistance_accessibility" Type="Usage"
-                       Mapping="Amend1:AssistanceAccessibility,Identifier:11"/>
+                       Mapping="Name:AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/>
             <Component Name="assistance_navigation_guidance" Type="Usage"
-                       Mapping="Amend1:AssistanceNavigationGuidance,Identifier:12"/>
+                       Mapping="Name:AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
             <Component Name="assistance_sonification" Type="Usage"
-                       Mapping="Amend1:AssistanceSonification,Identifier:13"/>
-            <Component Name="game" Type="Usage" Mapping="Amend1:BluetoothSco,Identifier:14"/>
-            <Component Name="virtual_source" Type="Usage"
-                                             Mapping="Amend1:VirtualSource,Identifier:15"/>
-            <Component Name="assistant" Type="Usage" Mapping="Amend1:Assistant,Identifier:16"/>
+                       Mapping="Name:AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
+            <Component Name="game" Type="Usage" Mapping="Name:AUDIO_USAGE_GAME"/>
+            <Component Name="virtual_source" Type="Usage" Mapping="Name:AUDIO_USAGE_VIRTUAL_SOURCE"/>
+            <Component Name="assistant" Type="Usage" Mapping="Name:AUDIO_USAGE_ASSISTANT"/>
         </ComponentType>
 
         <!--#################### USAGE END ####################-->
@@ -106,25 +90,25 @@
 
         <ComponentType Name="InputSources" Description="associated to audio_source_t definition,
                              identifier mapping must match the value of the enum">
-            <Component Name="default" Type="InputSource" Mapping="Amend1:Default,Identifier:0"/>
-            <Component Name="mic" Type="InputSource" Mapping="Amend1:Mic,Identifier:1"/>
+            <Component Name="default" Type="InputSource" Mapping="Name:AUDIO_SOURCE_DEFAULT"/>
+            <Component Name="mic" Type="InputSource" Mapping="Name:AUDIO_SOURCE_MIC"/>
             <Component Name="voice_uplink" Type="InputSource"
-                                           Mapping="Amend1:VoiceUplink,Identifier:2"/>
+                                           Mapping="Name:AUDIO_SOURCE_VOICE_UPLINK"/>
             <Component Name="voice_downlink" Type="InputSource"
-                                             Mapping="Amend1:VoiceDownlink,Identifier:3"/>
+                                             Mapping="Name:AUDIO_SOURCE_VOICE_DOWNLINK"/>
             <Component Name="voice_call" Type="InputSource"
-                                         Mapping="Amend1:VoiceCall,Identifier:4"/>
-            <Component Name="camcorder" Type="InputSource" Mapping="Amend1:Camcorder,Identifier:5"/>
+                                         Mapping="Name:AUDIO_SOURCE_VOICE_CALL"/>
+            <Component Name="camcorder" Type="InputSource" Mapping="Name:AUDIO_SOURCE_CAMCORDER"/>
             <Component Name="voice_recognition" Type="InputSource"
-                                                Mapping="Amend1:VoiceRecognition,Identifier:6"/>
+                                                Mapping="Name:AUDIO_SOURCE_VOICE_RECOGNITION"/>
             <Component Name="voice_communication" Type="InputSource"
-                                                  Mapping="Amend1:VoiceCommunication,Identifier:7"/>
+                                                  Mapping="Name:AUDIO_SOURCE_VOICE_COMMUNICATION"/>
             <Component Name="remote_submix" Type="InputSource"
-                                            Mapping="Amend1:RemoteSubmix,Identifier:8"/>
+                                            Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
             <Component Name="unprocessed" Type="InputSource"
-                                            Mapping="Amend1:Unprocessed,Identifier:9"/>
-            <Component Name="fm_tuner" Type="InputSource" Mapping="Amend1:FmTuner,Identifier:1998"/>
-            <Component Name="hotword" Type="InputSource" Mapping="Amend1:Hotword,Identifier:1999"/>
+                                            Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
+            <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 ####################-->
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt b/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
deleted file mode 100644
index 480cbe1..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-ExclusiveCriterion TelephonyMode                :   Normal          RingTone                InCall              InCommunication
-InclusiveCriterion AvailableInputDevices        :   Communication Ambient BuiltinMic BluetoothScoHeadset WiredHeadset Hdmi TelephonyRx BackMic RemoteSubmix AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice FmTuner TvTuner Line Spdif BluetoothA2dp Loopback Ip Bus Stub
-InclusiveCriterion AvailableOutputDevices       :   Earpiece Speaker WiredSpeaker WiredHeadset WiredHeadphone BluetoothSco BluetoothScoHeadset BluetoothScoCarkit BluetoothA2dp BluetoothA2dpHeadphones BluetoothA2dpSpeaker Hdmi AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice RemoteSubmix TelephonyTx Line HdmiArc Spdif Fm AuxLine SpeakerSafe Ip Bus Stub
-ExclusiveCriterion ForceUseForCommunication     :   ForceNone       ForceSpeaker            ForceBtSco
-ExclusiveCriterion ForceUseForMedia             :   ForceNone       ForceSpeaker			ForceHeadphones         ForceBtA2dp         ForceWiredAccessory ForceAnalogDock ForceDigitalDock    ForceNoBtA2dp       ForceSystemEnforced
-ExclusiveCriterion ForceUseForRecord            :   ForceNone       ForceBtSco              ForceWiredAccessory
-ExclusiveCriterion ForceUseForDock              :   ForceNone       ForceWiredAccessory     ForceBtCarDock      ForceBtDeskDock     ForceAnalogDock ForceDigitalDock
-ExclusiveCriterion ForceUseForSystem            :   ForceNone       ForceSystemEnforced
-ExclusiveCriterion ForceUseForHdmiSystemAudio   :   ForceNone       ForceHdmiSystemEnforced
-ExclusiveCriterion ForceUseForEncodedSurround   :   ForceNone       ForceEncodedSurroundNever   ForceEncodedSurroundAlways
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
index 3559cf1..db1f038 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
@@ -28,6 +28,7 @@
 LOCAL_SHARED_LIBRARIES := \
     libaudiopolicyengineconfigurable  \
     libparameter \
+    libmedia_helper \
     liblog \
 
 LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
index eac4efe..f91f8d7 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
@@ -17,6 +17,7 @@
 #include "InputSource.h"
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
 
 using std::string;
 
@@ -33,9 +34,13 @@
                            instanceConfigurableElement->getBelongingSubsystem())),
       mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
 {
-    mId = static_cast<audio_source_t>(context.getItemAsInteger(MappingKeyIdentifier));
+    std::string name(context.getItem(MappingKeyName));
+
+    if(not android::SourceTypeConverter::fromString(name, mId)) {
+        LOG_ALWAYS_FATAL("Invalid Input Source name: %s, invalid XML structure file", name.c_str());
+    }
     // Declares the strategy to audio policy engine
-    mPolicyPluginInterface->addInputSource(getFormattedMappingValue(), mId);
+    mPolicyPluginInterface->addInputSource(name, mId);
 }
 
 bool InputSource::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
index 98d10a9..7374fc3 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
@@ -65,22 +65,22 @@
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<Stream>(
             mStreamComponentName,
-            (1 << MappingKeyIdentifier))
+            (1 << MappingKeyName))
         );
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<Strategy>(
             mStrategyComponentName,
-            (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+            0)
         );
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<Usage>(
             mUsageComponentName,
-            (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+            (1 << MappingKeyName))
         );
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<InputSource>(
             mInputSourceComponentName,
-            (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+            (1 << MappingKeyName))
         );
 }
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
index 746c3a8..876bcb0 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
@@ -17,10 +17,38 @@
 #include "Strategy.h"
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
+#include <RoutingStrategy.h>
 
 using std::string;
 using android::routing_strategy;
 
+namespace detail {
+
+constexpr std::pair<routing_strategy, const char*> routingStrategyMap[] = {
+    {android::STRATEGY_MEDIA, "STRATEGY_MEDIA"},
+    {android::STRATEGY_PHONE, "STRATEGY_PHONE"},
+    {android::STRATEGY_SONIFICATION, "STRATEGY_SONIFICATION"},
+    {android::STRATEGY_SONIFICATION_RESPECTFUL, "STRATEGY_SONIFICATION_RESPECTFUL"},
+    {android::STRATEGY_DTMF, "STRATEGY_DTMF"},
+    {android::STRATEGY_ENFORCED_AUDIBLE, "STRATEGY_ENFORCED_AUDIBLE"},
+    {android::STRATEGY_TRANSMITTED_THROUGH_SPEAKER, "STRATEGY_TRANSMITTED_THROUGH_SPEAKER"},
+    {android::STRATEGY_ACCESSIBILITY, "STRATEGY_ACCESSIBILITY"},
+    {android::STRATEGY_REROUTING, "STRATEGY_REROUTING"},
+};
+
+bool fromString(const char *literalName, routing_strategy &type)
+{
+    for (auto& pair : routingStrategyMap) {
+        if (strcmp(pair.second, literalName) == 0) {
+            type = pair.first;
+            return true;
+        }
+    }
+    return false;
+}
+
+}
+
 Strategy::Strategy(const string &mappingValue,
                    CInstanceConfigurableElement *instanceConfigurableElement,
                    const CMappingContext &context,
@@ -35,10 +63,12 @@
                            instanceConfigurableElement->getBelongingSubsystem())),
       mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
 {
-    mId = static_cast<routing_strategy>(context.getItemAsInteger(MappingKeyIdentifier));
-
+    std::string name(context.getItem(MappingKeyName));
+    if (not detail::fromString(name.c_str(), mId)) {
+        LOG_ALWAYS_FATAL("Invalid Strategy %s, invalid XML structure file", name.c_str());
+    }
     // Declares the strategy to audio policy engine
-    mPolicyPluginInterface->addStrategy(getFormattedMappingValue(), mId);
+    mPolicyPluginInterface->addStrategy(instanceConfigurableElement->getName(), mId);
 }
 
 bool Strategy::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
index c642a23..46c9e1c 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
@@ -17,6 +17,7 @@
 #include "Stream.h"
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
 
 using std::string;
 using android::routing_strategy;
@@ -29,10 +30,14 @@
                            instanceConfigurableElement->getBelongingSubsystem())),
       mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
 {
-    mId = static_cast<audio_stream_type_t>(context.getItemAsInteger(MappingKeyIdentifier));
+    std::string name(context.getItem(MappingKeyName));
+
+    if (not android::StreamTypeConverter::fromString(name, mId)) {
+        LOG_ALWAYS_FATAL("Invalid Stream type name: %s, invalid XML structure file", name.c_str());
+    }
 
     // Declares the strategy to audio policy engine
-    mPolicyPluginInterface->addStream(getFormattedMappingValue(), mId);
+    mPolicyPluginInterface->addStream(name, mId);
 }
 
 bool Stream::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
index 78199f8..925d631 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
@@ -17,6 +17,7 @@
 #include "Usage.h"
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
 
 using std::string;
 using android::routing_strategy;
@@ -34,10 +35,13 @@
                            instanceConfigurableElement->getBelongingSubsystem())),
       mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
 {
-    mId = static_cast<audio_usage_t>(context.getItemAsInteger(MappingKeyIdentifier));
+    std::string name(context.getItem(MappingKeyName));
 
+    if (not android::UsageTypeConverter::fromString(name, mId)) {
+        LOG_ALWAYS_FATAL("Invalid Usage name: %s, invalid XML structure file", name.c_str());
+    }
     // Declares the strategy to audio policy engine
-    mPolicyPluginInterface->addUsage(getFormattedMappingValue(), mId);
+    mPolicyPluginInterface->addUsage(name, mId);
 }
 
 bool Usage::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te b/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te
new file mode 100644
index 0000000..4d41d42
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te
@@ -0,0 +1,4 @@
+userdebug_or_eng(`
+  allow audioserver audioserver_socket:dir rw_dir_perms;
+  allow audioserver audioserver_socket:sock_file create_file_perms;
+')
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/file.te b/services/audiopolicy/engineconfigurable/sepolicy/file.te
new file mode 100644
index 0000000..7db1937
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/file.te
@@ -0,0 +1,2 @@
+# Policy Engine remote connection for runtime debug of parameter framework
+type audioserver_socket, file_type, coredomain_socket;
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/file_contexts b/services/audiopolicy/engineconfigurable/sepolicy/file_contexts
new file mode 100644
index 0000000..950fcce
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/file_contexts
@@ -0,0 +1 @@
+/dev/socket/audioserver(/.*)?    u:object_r:audioserver_socket:s0
diff --git a/services/audiopolicy/engineconfigurable/src/Collection.h b/services/audiopolicy/engineconfigurable/src/Collection.h
index b72ded8..1f8ed8d 100644
--- a/services/audiopolicy/engineconfigurable/src/Collection.h
+++ b/services/audiopolicy/engineconfigurable/src/Collection.h
@@ -28,10 +28,8 @@
 #include <stdint.h>
 #include <string>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 /**
  * Collection of policy element as a map indexed with a their UID type.
diff --git a/services/audiopolicy/engineconfigurable/src/Element.h b/services/audiopolicy/engineconfigurable/src/Element.h
index 52e77e5..1b55c8c 100644
--- a/services/audiopolicy/engineconfigurable/src/Element.h
+++ b/services/audiopolicy/engineconfigurable/src/Element.h
@@ -22,10 +22,8 @@
 #include <system/audio.h>
 #include <utils/Log.h>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 template <typename Key>
 class Element
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 0d18ffa..009cf90 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -35,10 +35,9 @@
 using std::string;
 using std::map;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
 template <>
 StrategyCollection &Engine::getCollection<routing_strategy>()
 {
@@ -220,8 +219,10 @@
 }
 
 status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
-                                          audio_policy_dev_state_t /*state*/)
+                                          audio_policy_dev_state_t state)
 {
+    mPolicyParameterMgr->setDeviceConnectionState(devDesc, state);
+
     if (audio_is_output_device(devDesc->type())) {
         return mPolicyParameterMgr->setAvailableOutputDevices(
                     mApmObserver->getAvailableOutputDevices().types());
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 328d23d..ba4f889 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -21,12 +21,10 @@
 #include <AudioPolicyPluginInterface.h>
 #include "Collection.h"
 
-namespace android
-{
+namespace android {
 class AudioPolicyManagerObserver;
 
-namespace audio_policy
-{
+namespace audio_policy {
 
 class ParameterManagerWrapper;
 class VolumeProfile;
diff --git a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
index 9aa89b2..2442590 100644
--- a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
+++ b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
@@ -21,10 +21,8 @@
 
 using std::string;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 EngineInstance::EngineInstance()
 {
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.cpp b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
index ae39fef..b9a38d4 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
@@ -20,10 +20,9 @@
 
 using std::string;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
 status_t Element<audio_source_t>::setIdentifier(audio_source_t identifier)
 {
     if (identifier > AUDIO_SOURCE_MAX && identifier != AUDIO_SOURCE_HOTWORD) {
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.h b/services/audiopolicy/engineconfigurable/src/InputSource.h
index 6c498dc..64b390e 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.h
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.h
@@ -18,10 +18,8 @@
 
 #include "Element.h"
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 /**
  * Specialization of policy base class element for audio_source_t
diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.cpp b/services/audiopolicy/engineconfigurable/src/Strategy.cpp
index a539914..310b35e 100644
--- a/services/audiopolicy/engineconfigurable/src/Strategy.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Strategy.cpp
@@ -20,10 +20,8 @@
 
 using std::string;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 status_t Element<routing_strategy>::setIdentifier(routing_strategy identifier)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.h b/services/audiopolicy/engineconfigurable/src/Strategy.h
index 1157d55..f2487fd 100644
--- a/services/audiopolicy/engineconfigurable/src/Strategy.h
+++ b/services/audiopolicy/engineconfigurable/src/Strategy.h
@@ -19,10 +19,8 @@
 #include "Element.h"
 #include <RoutingStrategy.h>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 /**
  * @tparam audio_devices_t: Applicable output device(s) for this strategy.
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp
index 0ed364f..73fb94d 100644
--- a/services/audiopolicy/engineconfigurable/src/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp
@@ -21,10 +21,8 @@
 
 using std::string;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 status_t Element<audio_stream_type_t>::setIdentifier(audio_stream_type_t identifier)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.h b/services/audiopolicy/engineconfigurable/src/Stream.h
index 6902003..2bf70b3 100644
--- a/services/audiopolicy/engineconfigurable/src/Stream.h
+++ b/services/audiopolicy/engineconfigurable/src/Stream.h
@@ -21,10 +21,9 @@
 #include <RoutingStrategy.h>
 #include <map>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
 /**
  * @tparam routing_strategy: Applicable strategy for this stream.
  */
diff --git a/services/audiopolicy/engineconfigurable/src/Usage.cpp b/services/audiopolicy/engineconfigurable/src/Usage.cpp
index 5d20828..8c0dfba 100644
--- a/services/audiopolicy/engineconfigurable/src/Usage.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Usage.cpp
@@ -18,10 +18,8 @@
 
 #include "Usage.h"
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 status_t Element<audio_usage_t>::setIdentifier(audio_usage_t identifier)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Usage.h b/services/audiopolicy/engineconfigurable/src/Usage.h
index d69e0e0..72a452f 100644
--- a/services/audiopolicy/engineconfigurable/src/Usage.h
+++ b/services/audiopolicy/engineconfigurable/src/Usage.h
@@ -19,10 +19,8 @@
 #include "Element.h"
 #include <RoutingStrategy.h>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 /**
  * @tparam routing_strategy: Applicable strategy for this usage.
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
new file mode 100644
index 0000000..d8f29dc
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -0,0 +1,31 @@
+// 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.
+
+python_binary_host {
+    name: "buildPolicyCriterionTypes.py",
+    owner: "renault",
+    main: "buildPolicyCriterionTypes.py",
+    srcs: [
+        "buildPolicyCriterionTypes.py",
+    ],
+    version: {
+        py2: {
+            enabled: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+}
+
diff --git a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
new file mode 100755
index 0000000..0fb70a6
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
@@ -0,0 +1,243 @@
+#!/usr/bin/python
+
+#
+# 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.
+#
+
+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 criterion types file used by
+# the engineconfigurable to start the parameter-framework.
+# It prevents to fill them manually and avoid divergences with android.
+#
+# The Device Types criterion types are fed from audio-base.h file with the option
+#           --androidaudiobaseheader <path/to/android/audio/base/file/audio-base.h>
+#
+# The Device Addresses criterion types are fed from the audio policy configuration file
+# in order to discover all the devices for which the address matter.
+#           --audiopolicyconfigurationfile <path/to/audio_policy_configuration.xml>
+#
+# The reference file of criterion types must also be set as an input of the script:
+#           --criteriontypes <path/to/criterion/file/audio_criterion_types.xml.in>
+#
+# At last, the output of the script shall be set also:
+#           --outputfile <path/to/out/vendor/etc/audio_criterion_types.xml>
+#
+
+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.")
+    argparser.add_argument('--androidaudiobaseheader',
+            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)
+    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)
+    argparser.add_argument('--outputfile',
+            help="Criterion types outputfile file. Mandatory.",
+            metavar="CRITERION_TYPE_OUTPUT_FILE",
+            type=argparse.FileType('w'),
+            required=True)
+    argparser.add_argument('--verbose',
+            action='store_true')
+
+    return argparser.parse_args()
+
+
+def generateXmlCriterionTypesFile(criterionTypes, addressCriteria, criterionTypesFile, outputFile):
+
+    logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+    criterion_types_in_tree = ET.parse(criterionTypesFile)
+
+    criterion_types_root = criterion_types_in_tree.getroot()
+
+    for criterion_name, values_dict in criterionTypes.items():
+        for criterion_type in criterion_types_root.findall('criterion_type'):
+            if criterion_type.get('name') == criterion_name:
+                values_node = ET.SubElement(criterion_type, "values")
+                ordered_values = OrderedDict(sorted(values_dict.items(), key=lambda x: x[1]))
+                for key, value in ordered_values.items():
+                    value_node = ET.SubElement(values_node, "value")
+                    value_node.set('numerical', str(value))
+                    value_node.set('literal', key)
+
+    if addressCriteria:
+        for criterion_name, values_list in addressCriteria.items():
+            for criterion_type in criterion_types_root.findall('criterion_type'):
+                if criterion_type.get('name') == criterion_name:
+                    values_node = ET.SubElement(criterion_type, "values")
+                    index = 0
+                    for value in values_list:
+                        value_node = ET.SubElement(values_node, "value", literal=value)
+                        value_node.set('numerical', str(1 << index))
+                        index += 1
+
+    xmlstr = ET.tostring(criterion_types_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'))
+
+def capitalizeLine(line):
+    return ' '.join((w.capitalize() for w in line.split(' ')))
+
+
+#
+# Parse the audio policy configuration file and output a dictionary of device criteria addresses
+#
+def parseAndroidAudioPolicyConfigurationFile(audiopolicyconfigurationfile):
+
+    logging.info("Checking Audio Policy Configuration file {}".format(audiopolicyconfigurationfile))
+    #
+    # extract all devices addresses from audio policy configuration file
+    #
+    address_criteria_mapping_table = {
+        'sink' : "OutputDevicesAddressesType",
+        'source' : "InputDevicesAddressesType" }
+
+    address_criteria = {
+        'OutputDevicesAddressesType' : [],
+        'InputDevicesAddressesType' : [] }
+
+    oldWorkingDir = os.getcwd()
+    print "Current working directory %s" % oldWorkingDir
+
+    newDir = os.path.join(oldWorkingDir , audiopolicyconfigurationfile.name)
+
+    policy_in_tree = ET.parse(audiopolicyconfigurationfile)
+    os.chdir(os.path.dirname(os.path.normpath(newDir)))
+
+    print "new working directory %s" % os.getcwd()
+
+    policy_root = policy_in_tree.getroot()
+    EI.include(policy_root)
+
+    os.chdir(oldWorkingDir)
+
+    for device in policy_root.iter('devicePort'):
+        for key in address_criteria_mapping_table.keys():
+            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'))
+
+    for criteria in address_criteria:
+        values = ','.join(address_criteria[criteria])
+        logging.info("{}: <{}>".format(criteria, values))
+
+    return address_criteria
+
+#
+# Parse the audio-base.h file and output a dictionary of android dependent criterion types:
+#   -Android Mode
+#   -Output devices type
+#   -Input devices type
+#
+def parseAndroidAudioFile(androidaudiobaseheaderFile):
+    #
+    # Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
+    #
+    criterion_mapping_table = {
+        'AUDIO_MODE' : "AndroidModeType",
+        'AUDIO_DEVICE_OUT' : "OutputDevicesMaskType",
+        'AUDIO_DEVICE_IN' : "InputDevicesMaskType"}
+
+    all_criteria = {
+        'AndroidModeType' : {},
+        'OutputDevicesMaskType' : {},
+        'InputDevicesMaskType' : {} }
+
+    #
+    # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
+    #
+    ignored_values = [ 'CNT', 'MAX', 'ALL', 'NONE' ]
+
+    criteria_pattern = re.compile(
+        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]+)")
+
+    logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
+
+    for line_number, line in enumerate(androidaudiobaseheaderFile):
+        match = criteria_pattern.match(line)
+        if match:
+            logging.debug("The following line is VALID: {}:{}\n{}".format(
+                androidaudiobaseheaderFile.name, line_number, line))
+
+            criterion_name = criterion_mapping_table[match.groupdict()['type']]
+            literal = ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
+            numerical_value = match.groupdict()['values']
+
+            # for AUDIO_DEVICE_IN: need to remove sign bit
+            if criterion_name == "InputDevicesMaskType":
+                numerical_value = str(int(numerical_value, 0) & ~2147483648)
+
+            # Remove duplicated numerical values
+            if int(numerical_value, 0) in all_criteria[criterion_name].values():
+                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():
+                    if all_criteria[criterion_name][key] == int(numerical_value, 0):
+                        del all_criteria[criterion_name][key]
+
+            all_criteria[criterion_name][literal] = int(numerical_value, 0)
+
+            logging.debug("type:{},".format(criterion_name))
+            logging.debug("iteral:{},".format(literal))
+            logging.debug("values:{}.".format(numerical_value))
+
+    return all_criteria
+
+
+def main():
+    logging.root.setLevel(logging.INFO)
+    args = parseArgs()
+
+    all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader)
+
+    address_criteria = parseAndroidAudioPolicyConfigurationFile(args.audiopolicyconfigurationfile)
+
+    criterion_types = args.criteriontypes
+
+    generateXmlCriterionTypesFile(all_criteria, address_criteria, criterion_types, args.outputfile)
+
+# If this file is directly executed
+if __name__ == "__main__":
+    exit(main())
diff --git a/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
new file mode 100644
index 0000000..2b86469
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
@@ -0,0 +1,35 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): MY_TOOL := 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_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) domainGeneratorPolicy.py
+
+	"$(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
new file mode 100755
index 0000000..7929402
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
@@ -0,0 +1,268 @@
+#!/usr/bin/python
+
+#
+# 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.
+#
+
+import EddParser
+from PFWScriptGenerator import PfwScriptTranslator
+import hostConfig
+
+import argparse
+import re
+import sys
+import tempfile
+import os
+import logging
+import subprocess
+import xml.etree.ElementTree as ET
+
+#
+# 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
+# the engineconfigurable.
+# This scripts allows generates the settings from the same audio_criterion_types.xml /
+# audio_criteria.xml files used at run time by the engineconfigurable
+#
+
+def parseArgs():
+    argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+        Settings file generator.\n\
+        Exit with the number of (recoverable or not) error that occured.")
+    argparser.add_argument('--toplevel-config',
+            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)
+    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)
+    argparser.add_argument('--initial-settings',
+            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=[])
+    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')
+    argparser.add_argument('--schemas-dir',
+            help="Directory of parameter-framework XML Schemas for generation \
+        validation",
+            default=None)
+    argparser.add_argument('--target-schemas-dir',
+            help="Ignored. Kept for retro-compatibility")
+    argparser.add_argument('--validate',
+            help="Validate the settings against XML schemas",
+            action='store_true')
+    argparser.add_argument('--verbose',
+            action='store_true')
+
+    return argparser.parse_args()
+
+#
+# Parses audio_criterion_types.xml / audio_criteria.xml files used at run time by the
+# engineconfigurable and outputs a dictionnary of criteria.
+# For each criteria, the name, type (aka inclusive (bitfield) or exclusive (enum), the values
+# are provided.
+#
+def parseCriteriaAndCriterionTypes(criteriaFile, criterionTypesFile):
+    # Parse criteria and criterion types XML files
+    #
+    criteria_tree = ET.parse(criteriaFile)
+    logging.info("Importing criteriaFile {}".format(criteriaFile))
+    criterion_types_tree = ET.parse(criterionTypesFile)
+    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'):
+        criterion_name = criterion.get('name')
+        type_name = criterion.get('type')
+        logging.info("Importing criterion_name {}".format(criterion_name))
+        logging.info("Importing type_name {}".format(type_name))
+
+        for criterion_types in criterion_types_tree.findall('criterion_type'):
+            criterion_type_name = criterion_types.get('name')
+            if criterion_type_name == type_name:
+                criterion_inclusiveness = criterion_types.get('type')
+
+                criterion_values = []
+
+                values_node = criterion_types.find('values')
+                if values_node:
+                    for value in values_node.findall('value'):
+                        criterion_values.append(value.get('literal'))
+
+                if len(criterion_values) == 0:
+                    criterion_values.append('')
+
+                logging.info("Importing criterion_type_name {}".format(criterion_type_name))
+                logging.info("Importing criterion_inclusiveness {}".format(criterion_inclusiveness))
+                logging.info("Importing criterion_values {}".format(criterion_values))
+
+                all_criteria.append({
+                    "name" : criterion_name,
+                    "inclusive" : criterion_inclusiveness,
+                    "values" : criterion_values})
+                break
+
+    return all_criteria
+
+#
+# Parses the Edd files (aka .pfw extension file), which is a simplified language to write the
+# parameter framework settings.
+#
+def parseEdd(EDDFiles):
+    parsed_edds = []
+
+    for edd_file in EDDFiles:
+        try:
+            root = EddParser.Parser().parse(edd_file)
+        except EddParser.MySyntaxError as ex:
+            logging.critical(str(ex))
+            logging.info("EXIT ON FAILURE")
+            exit(2)
+
+        try:
+            root.propagate()
+        except EddParser.MyPropagationError, ex :
+            logging.critical(str(ex))
+            logging.info("EXIT ON FAILURE")
+            exit(1)
+
+        parsed_edds.append((edd_file.name, root))
+    return parsed_edds
+
+#
+# Generates all the required commands to be sent to the instance of parameter-framework launched
+# at runtime to generate the XML Settings file.
+# 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']
+
+        yield ["start"]
+
+        # Import initial settings file
+        if initial_settings:
+            logging.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]
+
+        # 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
+
+#
+# Entry point of the domain generator.
+#       -Parses Criterion types and criteria files
+#       -Parses settings written in simplified pfw language.
+#       -Launches a parameter-framework
+#       -Translates the settings into command that can be interpreted by parameter-framework.
+#       -Use the exports command and output them in XML Settings file.
+#
+def main():
+    logging.root.setLevel(logging.INFO)
+    args = parseArgs()
+
+    all_criteria = parseCriteriaAndCriterionTypes(args.criteria, args.criteriontypes)
+
+    #
+    # EDD files (aka ".pfw" files)
+    #
+    parsed_edds = parseEdd(args.edd_files)
+
+    # We need to modify the toplevel configuration file to account for differences
+    # between development setup and target (installation) setup, in particular, the
+    # TuningMwith ode must be enforced, regardless of what will be allowed on the target
+    fake_toplevel_config = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".xml",
+                                                       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)
+    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)
+
+    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")
+
+    # Closing the connector's input triggers the domain generation
+    connector.stdin.close()
+    connector.wait()
+    os.remove(fake_toplevel_config.name)
+    return connector.returncode
+
+# If this file is directly executed
+if __name__ == "__main__":
+    exit(main())
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
new file mode 100644
index 0000000..4814376
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
@@ -0,0 +1,24 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+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)/bin/buildPolicyCriterionTypes.py
+$(LOCAL_BUILT_MODULE): $(LOCAL_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) \
+    buildPolicyCriterionTypes.py \
+    $(CRITERION_TYPES_FILE) \
+    $(ANDROID_AUDIO_BASE_HEADER_FILE)
+
+	"$(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/wrapper/Android.mk b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
index b128a38..d19a364 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.mk
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
@@ -1,5 +1,8 @@
 LOCAL_PATH:= $(call my-dir)
 
+TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
+PROVISION_CRITERION_TYPES := $(TOOLS)/provision_criterion_types_from_android_headers.mk
+
 ##################################################################
 # WRAPPER LIBRARY
 ##################################################################
@@ -10,12 +13,22 @@
     $(LOCAL_PATH)/include \
     frameworks/av/services/audiopolicy/engineconfigurable/include \
     frameworks/av/services/audiopolicy/engineconfigurable/interface \
+    frameworks/av/services/audiopolicy/common/include \
+    external/libxml2/include \
+    external/icu/icu4c/source/common
 
-LOCAL_SRC_FILES:= ParameterManagerWrapper.cpp
+LOCAL_SRC_FILES:= \
+    ParameterManagerWrapper.cpp \
+    ParameterManagerWrapperConfig.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libparameter \
-    libmedia_helper
+    libmedia_helper \
+    libicuuc \
+    libxml2
+
+LOCAL_STATIC_LIBRARIES := \
+    libaudiopolicycomponents
 
 LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
 
@@ -31,11 +44,35 @@
 # CONFIGURATION FILE
 ##################################################################
 
-# specific management of audio_policy_criteria.conf
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
+
 include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_criteria.conf
+LOCAL_MODULE := policy_wrapper_configuration.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
+LOCAL_VENDOR_MODULE := true
 LOCAL_SRC_FILES := config/$(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := policy_criteria.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := config/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := policy_criterion_types.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+    $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
+
+AUDIO_POLICY_CONFIGURATION_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
+ANDROID_AUDIO_BASE_HEADER_FILE := system/media/audio/include/system/audio-base.h
+CRITERION_TYPES_FILE := $(LOCAL_PATH)/config/policy_criterion_types.xml.in
+
+include $(PROVISION_CRITERION_TYPES)
+
+endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 9b0442e..fc6c1e4 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -18,7 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include "ParameterManagerWrapper.h"
-#include "audio_policy_criteria_conf.h"
+#include "ParameterManagerWrapperConfig.h"
 #include <ParameterMgrPlatformConnector.h>
 #include <SelectionCriterionTypeInterface.h>
 #include <SelectionCriterionInterface.h>
@@ -38,6 +38,7 @@
 using std::string;
 using std::map;
 using std::vector;
+using CriterionTypes = std::map<std::string, ISelectionCriterionTypeInterface *>;
 
 /// PFW related definitions
 // Logger
@@ -56,16 +57,36 @@
     }
 };
 
-namespace android
-{
+namespace android {
 
 using utilities::convertTo;
 
-namespace audio_policy
-{
+namespace audio_policy {
+
 const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
     "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
 
+static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
+static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
+static const char *const gPhoneStateCriterionName = "TelephonyMode";
+static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
+static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
+
+/**
+ * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
+ */
+static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
+{
+    [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] =        "ForceUseForCommunication",
+    [AUDIO_POLICY_FORCE_FOR_MEDIA] =                "ForceUseForMedia",
+    [AUDIO_POLICY_FORCE_FOR_RECORD] =               "ForceUseForRecord",
+    [AUDIO_POLICY_FORCE_FOR_DOCK] =                 "ForceUseForDock",
+    [AUDIO_POLICY_FORCE_FOR_SYSTEM] =               "ForceUseForSystem",
+    [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] =    "ForceUseForHdmiSystemAudio",
+    [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] =     "ForceUseForEncodedSurround",
+    [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] =      "ForceUseForVibrateRinging"
+};
+
 template <>
 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
 template <>
@@ -80,15 +101,64 @@
     // Logger
     mPfwConnector->setLogger(mPfwConnectorLogger);
 
-    // Load criteria file
-    if ((loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaVendorConfFilePath) != NO_ERROR) &&
-        (loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaConfFilePath) != NO_ERROR)) {
-        ALOGE("%s: Neither vendor conf file (%s) nor system conf file (%s) could be found",
-              __FUNCTION__, gAudioPolicyCriteriaVendorConfFilePath,
-              gAudioPolicyCriteriaConfFilePath);
+    status_t loadResult = loadConfig();
+    if (loadResult < 0) {
+        ALOGE("Policy Wrapper configuration is partially invalid.");
     }
 }
 
+status_t ParameterManagerWrapper::loadConfig()
+{
+    auto result = wrapper_config::parse();
+    if (result.parsedConfig == nullptr) {
+        return -ENOENT;
+    }
+    ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
+
+    CriterionTypes criterionTypes;
+    for (auto criterionType : result.parsedConfig->criterionTypes) {
+        ALOG_ASSERT(criterionTypes.find(criterionType.name) == criterionTypes.end(),
+                          "CriterionType %s already added", criterionType.name.c_str());
+        ALOGV("%s: Adding new criterionType %s", __FUNCTION__, criterionType.name.c_str());
+
+        auto criterionTypePfw =
+                mPfwConnector->createSelectionCriterionType(criterionType.isInclusive);
+
+        for (auto pair : criterionType.valuePairs) {
+            std::string error;
+            ALOGV("%s: Adding pair %d,%s for criterionType %s", __FUNCTION__, pair.first,
+                  pair.second.c_str(), criterionType.name.c_str());
+            criterionTypePfw->addValuePair(pair.first, pair.second, error);
+        }
+        criterionTypes[criterionType.name] = criterionTypePfw;
+    }
+
+    for (auto criterion : result.parsedConfig->criteria) {
+        ALOG_ASSERT(mPolicyCriteria.find(criterion.name) == mPolicyCriteria.end(),
+                    "%s: Criterion %s already added", __FUNCTION__, criterion.name.c_str());
+
+        auto criterionType =
+                getElement<ISelectionCriterionTypeInterface>(criterion.typeName, criterionTypes);
+        ALOG_ASSERT(criterionType != nullptr, "No %s Criterion type found for criterion %s",
+                    criterion.typeName.c_str(), criterion.name.c_str());
+
+        auto criterionPfw = mPfwConnector->createSelectionCriterion(criterion.name, criterionType);
+        mPolicyCriteria[criterion.name] = criterionPfw;
+
+        if (not criterion.defaultLiteralValue.empty()) {
+            int numericalValue = 0;
+            if (not criterionType->getNumericalValue(criterion.defaultLiteralValue.c_str(),
+                                                     numericalValue)) {
+                ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
+                      criterion.defaultLiteralValue.c_str());
+                continue;
+            }
+            criterionPfw->setCriterionState(numericalValue);
+        }
+    }
+    return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
+}
+
 ParameterManagerWrapper::~ParameterManagerWrapper()
 {
     // Unset logger
@@ -112,112 +182,6 @@
     return NO_ERROR;
 }
 
-
-void ParameterManagerWrapper::addCriterionType(const string &typeName, bool isInclusive)
-{
-    ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) == mPolicyCriterionTypes.end(),
-                      "CriterionType %s already added", typeName.c_str());
-    ALOGD("%s: Adding new criterionType %s", __FUNCTION__, typeName.c_str());
-
-    mPolicyCriterionTypes[typeName] = mPfwConnector->createSelectionCriterionType(isInclusive);
-}
-
-void ParameterManagerWrapper::addCriterionTypeValuePair(
-    const string &typeName,
-    uint32_t numericValue,
-    const string &literalValue)
-{
-    ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) != mPolicyCriterionTypes.end(),
-                      "CriterionType %s not found", typeName.c_str());
-    ALOGV("%s: Adding new value pair (%d,%s) for criterionType %s", __FUNCTION__,
-          numericValue, literalValue.c_str(), typeName.c_str());
-    ISelectionCriterionTypeInterface *criterionType = mPolicyCriterionTypes[typeName];
-    std::string error;
-    criterionType->addValuePair(numericValue, literalValue, error);
-}
-
-void ParameterManagerWrapper::loadCriterionType(cnode *root, bool isInclusive)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node;
-    for (node = root->first_child; node != NULL; node = node->next) {
-
-        ALOG_ASSERT(node != NULL, "error in parsing file");
-        const char *typeName = node->name;
-        char *valueNames = strndup(node->value, strlen(node->value));
-
-        addCriterionType(typeName, isInclusive);
-
-        uint32_t index = 0;
-        char *ctx;
-        char *valueName = strtok_r(valueNames, ",", &ctx);
-        while (valueName != NULL) {
-            if (strlen(valueName) != 0) {
-
-                // Conf file may use or not pair, if no pair, use incremental index, else
-                // use provided index.
-                if (strchr(valueName, ':') != NULL) {
-
-                    char *first = strtok(valueName, ":");
-                    char *second = strtok(NULL, ":");
-                    ALOG_ASSERT((first != NULL) && (strlen(first) != 0) &&
-                                      (second != NULL) && (strlen(second) != 0),
-                                      "invalid value pair");
-
-                    if (!convertTo<string, uint32_t>(first, index)) {
-                        ALOGE("%s: Invalid index(%s) found", __FUNCTION__, first);
-                    }
-                    addCriterionTypeValuePair(typeName, index, second);
-                } else {
-
-                    uint32_t pfwIndex = isInclusive ? 1 << index : index;
-                    addCriterionTypeValuePair(typeName, pfwIndex, valueName);
-                    index += 1;
-                }
-            }
-            valueName = strtok_r(NULL, ",", &ctx);
-        }
-        free(valueNames);
-    }
-}
-
-void ParameterManagerWrapper::loadInclusiveCriterionType(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node = config_find(root, gInclusiveCriterionTypeTag.c_str());
-    if (node == NULL) {
-        return;
-    }
-    loadCriterionType(node, true);
-}
-
-void ParameterManagerWrapper::loadExclusiveCriterionType(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node = config_find(root, gExclusiveCriterionTypeTag.c_str());
-    if (node == NULL) {
-        return;
-    }
-    loadCriterionType(node, false);
-}
-
-void ParameterManagerWrapper::parseChildren(cnode *root, string &defaultValue, string &type)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node;
-    for (node = root->first_child; node != NULL; node = node->next) {
-        ALOG_ASSERT(node != NULL, "error in parsing file");
-
-        if (string(node->name) == gDefaultTag) {
-            defaultValue = node->value;
-        } else if (string(node->name) == gTypeTag) {
-            type = node->value;
-        } else {
-             ALOGE("%s: Unrecognized %s %s node", __FUNCTION__, node->name, node->value);
-        }
-    }
-}
-
 template <typename T>
 T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
 {
@@ -236,97 +200,6 @@
     return it != elementsMap.end() ? it->second : NULL;
 }
 
-void ParameterManagerWrapper::loadCriteria(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node = config_find(root, gCriterionTag.c_str());
-
-    if (node == NULL) {
-        ALOGW("%s: no inclusive criteria found", __FUNCTION__);
-        return;
-    }
-    for (node = node->first_child; node != NULL; node = node->next) {
-        loadCriterion(node);
-    }
-}
-
-void ParameterManagerWrapper::addCriterion(const string &name, const string &typeName,
-                              const string &defaultLiteralValue)
-{
-    ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
-                "Route Criterion %s already added", name.c_str());
-
-    ISelectionCriterionTypeInterface *criterionType =
-            getElement<ISelectionCriterionTypeInterface>(typeName, mPolicyCriterionTypes);
-
-    ISelectionCriterionInterface *criterion =
-            mPfwConnector->createSelectionCriterion(name, criterionType);
-
-    mPolicyCriteria[name] = criterion;
-    int numericalValue = 0;
-    if (!criterionType->getNumericalValue(defaultLiteralValue.c_str(),  numericalValue)) {
-        ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
-              defaultLiteralValue.c_str());
-    }
-    criterion->setCriterionState(numericalValue);
-}
-
-void ParameterManagerWrapper::loadCriterion(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    const char *criterionName = root->name;
-
-    ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(),
-                      "Criterion %s already added", criterionName);
-
-    string paramKeyName = "";
-    string path = "";
-    string typeName = "";
-    string defaultValue = "";
-
-    parseChildren(root, defaultValue, typeName);
-
-    addCriterion(criterionName, typeName, defaultValue);
-}
-
-void ParameterManagerWrapper::loadConfig(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node = config_find(root, gPolicyConfTag.c_str());
-    if (node == NULL) {
-        ALOGW("%s: Could not find node for pfw", __FUNCTION__);
-        return;
-    }
-    ALOGD("%s: Loading conf for pfw", __FUNCTION__);
-    loadInclusiveCriterionType(node);
-    loadExclusiveCriterionType(node);
-    loadCriteria(node);
-}
-
-
-status_t ParameterManagerWrapper::loadAudioPolicyCriteriaConfig(const char *path)
-{
-    ALOG_ASSERT(path != NULL, "error in parsing file: empty path");
-    cnode *root;
-    char *data;
-    ALOGD("%s", __FUNCTION__);
-    data = (char *)load_file(path, NULL);
-    if (data == NULL) {
-        return -ENODEV;
-    }
-    root = config_node("", "");
-    ALOG_ASSERT(root != NULL, "Unable to allocate a configuration node");
-    config_load(root, data);
-
-    loadConfig(root);
-
-    config_free(root);
-    free(root);
-    free(data);
-    ALOGD("%s: loaded", __FUNCTION__);
-    return NO_ERROR;
-}
-
 bool ParameterManagerWrapper::isStarted()
 {
     return mPfwConnector && mPfwConnector->isStarted();
@@ -335,9 +208,9 @@
 status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
 {
     ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
         return BAD_VALUE;
     }
     if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
@@ -351,9 +224,9 @@
 audio_mode_t ParameterManagerWrapper::getPhoneState() const
 {
     const ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
         return AUDIO_MODE_NORMAL;
     }
     return static_cast<audio_mode_t>(criterion->getCriterionState());
@@ -370,7 +243,7 @@
     ISelectionCriterionInterface *criterion =
             getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
         return BAD_VALUE;
     }
     if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
@@ -390,7 +263,7 @@
     const ISelectionCriterionInterface *criterion =
             getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
         return AUDIO_POLICY_FORCE_NONE;
     }
     return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
@@ -404,12 +277,45 @@
     return interface->getLiteralValue(valueToCheck, literalValue);
 }
 
+status_t ParameterManagerWrapper::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+                                                           audio_policy_dev_state_t state)
+{
+    std::string criterionName = audio_is_output_device(devDesc->type()) ?
+                gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
+
+    ALOGV("%s: device with address %s %s", __FUNCTION__, devDesc->mAddress.string(),
+          state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
+    ISelectionCriterionInterface *criterion =
+            getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
+
+    if (criterion == NULL) {
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, criterionName.c_str());
+        return DEAD_OBJECT;
+    }
+
+    auto criterionType = criterion->getCriterionType();
+    int deviceAddressId;
+    if (not criterionType->getNumericalValue(devDesc->mAddress.string(), deviceAddressId)) {
+        ALOGE("%s: unknown device address reported (%s)", __FUNCTION__, devDesc->mAddress.c_str());
+        return BAD_TYPE;
+    }
+    int currentValueMask = criterion->getCriterionState();
+    if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+        currentValueMask |= deviceAddressId;
+    }
+    else {
+        currentValueMask &= ~deviceAddressId;
+    }
+    criterion->setCriterionState(currentValueMask);
+    return NO_ERROR;
+}
+
 status_t ParameterManagerWrapper::setAvailableInputDevices(audio_devices_t inputDevices)
 {
     ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gInputDeviceCriterionTag, mPolicyCriteria);
+            getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionTag.c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionName);
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(inputDevices & ~AUDIO_DEVICE_BIT_IN);
@@ -420,9 +326,9 @@
 status_t ParameterManagerWrapper::setAvailableOutputDevices(audio_devices_t outputDevices)
 {
     ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionTag, mPolicyCriteria);
+            getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionTag.c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionName);
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(outputDevices);
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp
new file mode 100644
index 0000000..bc6d046
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp
@@ -0,0 +1,208 @@
+/*
+ * 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_TAG "APM::AudioPolicyEngine/PFWWrapperConfig"
+#define LOG_NDEBUG 0
+
+#include "ParameterManagerWrapperConfig.h"
+
+#include <media/convert.h>
+#include <utils/Log.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <istream>
+
+
+namespace android {
+
+using utilities::convertTo;
+
+namespace audio_policy {
+namespace wrapper_config {
+namespace detail {
+
+std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
+{
+    xmlChar *xmlValue = xmlGetProp(cur, (const xmlChar *)attribute);
+    if (xmlValue == NULL) {
+        return "";
+    }
+    std::string value((const char *)xmlValue);
+    xmlFree(xmlValue);
+    return value;
+}
+
+template <class Trait>
+static status_t deserializeCollection(_xmlDoc *doc, const _xmlNode *cur,
+                                      typename Trait::Collection &collection,
+                                      size_t &nbSkippedElement)
+{
+    const xmlNode *root = cur->xmlChildrenNode;
+    while (root != NULL) {
+        if (xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag) &&
+            xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+            root = root->next;
+            continue;
+        }
+        const xmlNode *child = root;
+        if (!xmlStrcmp(child->name, (const xmlChar *)Trait::collectionTag)) {
+            child = child->xmlChildrenNode;
+        }
+        while (child != NULL) {
+            if (!xmlStrcmp(child->name, (const xmlChar *)Trait::tag)) {
+                status_t status = Trait::deserialize(doc, child, collection);
+                if (status == NO_ERROR) {
+                    nbSkippedElement += 1;
+                }
+            }
+            child = child->next;
+        }
+        if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+            return NO_ERROR;
+        }
+        root = root->next;
+    }
+    return NO_ERROR;
+}
+
+const char *const ValueTraits::tag = "value";
+const char *const ValueTraits::collectionTag = "values";
+
+const char ValueTraits::Attributes::literal[] = "literal";
+const char ValueTraits::Attributes::numerical[] = "numerical";
+
+status_t ValueTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *child, Collection &values)
+{
+    std::string literal = getXmlAttribute(child, Attributes::literal);
+    if (literal.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::literal);
+        return BAD_VALUE;
+    }
+    uint32_t numerical = 0;
+    std::string numericalTag = getXmlAttribute(child, Attributes::numerical);
+    if (numericalTag.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::literal);
+        return BAD_VALUE;
+    }
+    if (!convertTo(numericalTag, numerical)) {
+        ALOGE("%s: : Invalid value(%s)", __FUNCTION__, numericalTag.c_str());
+        return BAD_VALUE;
+    }
+    values.push_back({numerical, literal});
+    return NO_ERROR;
+}
+
+const char *const CriterionTypeTraits::tag = "criterion_type";
+const char *const CriterionTypeTraits::collectionTag = "criterion_types";
+
+const char CriterionTypeTraits::Attributes::name[] = "name";
+const char CriterionTypeTraits::Attributes::type[] = "type";
+
+status_t CriterionTypeTraits::deserialize(_xmlDoc *doc, const _xmlNode *child,
+                                          Collection &criterionTypes)
+{
+    std::string name = getXmlAttribute(child, Attributes::name);
+    if (name.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s %s = %s", __FUNCTION__, tag, Attributes::name, name.c_str());
+
+    std::string type = getXmlAttribute(child, Attributes::type);
+    if (type.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::type);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s %s = %s", __FUNCTION__, tag, Attributes::type, type.c_str());
+    bool isInclusive(type == "inclusive");
+
+    ValuePairs pairs;
+    size_t nbSkippedElements = 0;
+    detail::deserializeCollection<detail::ValueTraits>(doc, child, pairs, nbSkippedElements);
+
+    criterionTypes.push_back({name, isInclusive, pairs});
+    return NO_ERROR;
+}
+
+const char *const CriterionTraits::tag = "criterion";
+const char *const CriterionTraits::collectionTag = "criteria";
+
+const char CriterionTraits::Attributes::name[] = "name";
+const char CriterionTraits::Attributes::type[] = "type";
+const char CriterionTraits::Attributes::defaultVal[] = "default";
+
+status_t CriterionTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *child, Collection &criteria)
+{
+    std::string name = getXmlAttribute(child, Attributes::name);
+    if (name.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
+
+    std::string defaultValue = getXmlAttribute(child, Attributes::defaultVal);
+    if (defaultValue.empty()) {
+        // Not mandatory to provide a default value for a criterion, even it is recommanded...
+        ALOGV("%s: No attribute %s found", __FUNCTION__, Attributes::defaultVal);
+    }
+    ALOGV("%s: %s = %s", __FUNCTION__, Attributes::defaultVal, defaultValue.c_str());
+
+    std::string typeName = getXmlAttribute(child, Attributes::type);
+    if (typeName.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s = %s", __FUNCTION__, Attributes::type, typeName.c_str());
+
+    criteria.push_back({name, typeName, defaultValue});
+    return NO_ERROR;
+}
+} // namespace detail
+
+ParsingResult parse(const char* path) {
+    xmlDocPtr doc;
+    doc = xmlParseFile(path);
+    if (doc == NULL) {
+        ALOGE("%s: Could not parse document %s", __FUNCTION__, path);
+        return {nullptr, 0};
+    }
+    xmlNodePtr cur = xmlDocGetRootElement(doc);
+    if (cur == NULL) {
+        ALOGE("%s: Could not parse: empty document %s", __FUNCTION__, path);
+        xmlFreeDoc(doc);
+        return {nullptr, 0};
+    }
+    if (xmlXIncludeProcess(doc) < 0) {
+        ALOGE("%s: libxml failed to resolve XIncludes on document %s", __FUNCTION__, path);
+        return {nullptr, 0};
+    }
+    size_t nbSkippedElements = 0;
+    auto config = std::make_unique<Config>();
+
+    detail::deserializeCollection<detail::CriterionTraits>(
+                doc, cur, config->criteria, nbSkippedElements);
+    detail::deserializeCollection<detail::CriterionTypeTraits>(
+                doc, cur, config->criterionTypes, nbSkippedElements);
+
+    return {std::move(config), nbSkippedElements};
+}
+
+} // namespace wrapper_config
+} // namespace audio_policy
+} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h
new file mode 100644
index 0000000..467d0e1
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <utils/Errors.h>
+
+struct _xmlNode;
+struct _xmlDoc;
+
+namespace android {
+namespace audio_policy {
+namespace wrapper_config {
+
+/** Default path of audio policy usages configuration file. */
+constexpr char DEFAULT_PATH[] = "/vendor/etc/policy_wrapper_configuration.xml";
+
+/** Directories where the effect libraries will be search for. */
+constexpr const char* POLICY_USAGE_LIBRARY_PATH[] = {"/odm/etc/", "/vendor/etc/", "/system/etc/"};
+
+using ValuePair = std::pair<uint32_t, std::string>;
+using ValuePairs = std::vector<ValuePair>;
+
+struct CriterionType
+{
+    std::string name;
+    bool isInclusive;
+    ValuePairs valuePairs;
+};
+
+using CriterionTypes = std::vector<CriterionType>;
+
+struct Criterion
+{
+    std::string name;
+    std::string typeName;
+    std::string defaultLiteralValue;
+};
+
+using Criteria = std::vector<Criterion>;
+
+struct Config {
+    float version;
+    Criteria criteria;
+    CriterionTypes criterionTypes;
+};
+
+namespace detail
+{
+struct ValueTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char literal[];
+        static const char numerical[];
+    };
+
+    typedef ValuePair Element;
+    typedef ValuePair *PtrElement;
+    typedef ValuePairs Collection;
+
+    static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+                                         Collection &collection);
+};
+
+struct CriterionTypeTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char name[];
+        static const char type[];
+    };
+
+    typedef CriterionType Element;
+    typedef CriterionType *PtrElement;
+    typedef CriterionTypes Collection;
+
+    static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+                                         Collection &collection);
+};
+
+struct CriterionTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char name[];
+        static const char type[];
+        static const char defaultVal[];
+    };
+
+    typedef Criterion Element;
+    typedef Criterion *PtrElement;
+    typedef Criteria Collection;
+
+    static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+                                         Collection &collection);
+};
+} // namespace detail
+
+/** Result of `parse(const char*)` */
+struct ParsingResult {
+    /** Parsed config, nullptr if the xml lib could not load the file */
+    std::unique_ptr<Config> parsedConfig;
+    size_t nbSkippedElement; //< Number of skipped invalid product strategies
+};
+
+/** Parses the provided audio policy usage configuration.
+ * @return audio policy usage @see Config
+ */
+ParsingResult parse(const char* path = DEFAULT_PATH);
+
+} // namespace wrapper_config
+} // namespace audio_policy
+} // android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h b/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
deleted file mode 100644
index e4fd176..0000000
--- a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
+++ /dev/null
@@ -1,73 +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
-
-#include <string>
-#include <system/audio_policy.h>
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-//      Definitions for audio policy criteria configuration file (audio_policy_criteria.conf)   //
-//                                                                                              //
-//      @TODO: scripted from audio.h & audio_policy,h                                           //
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-static const char *const gAudioPolicyCriteriaConfFilePath =
-    "/system/etc/audio_policy_criteria.conf";
-static const char *const gAudioPolicyCriteriaVendorConfFilePath =
-    "/vendor/etc/audio_policy_criteria.conf";
-
-/**
- * PFW instances tags
- */
-static const std::string &gPolicyConfTag = "Policy";
-static const std::string &gDefaultTag = "Default";
-static const std::string &gTypeTag = "Type";
-
-/**
- * PFW elements tags
- */
-static const std::string &gInclusiveCriterionTypeTag = "InclusiveCriterionType";
-static const std::string &gExclusiveCriterionTypeTag = "ExclusiveCriterionType";
-static const std::string &gCriterionTag = "Criterion";
-
-/**
- * PFW known criterion tags
- */
-static const std::string &gInputDeviceCriterionTag = "AvailableInputDevices";
-static const std::string &gOutputDeviceCriterionTag = "AvailableOutputDevices";
-static const std::string &gPhoneStateCriterionTag = "TelephonyMode";
-
-/**
- * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
- */
-static const std::string gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
-{
-    [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] =        "ForceUseForCommunication",
-    [AUDIO_POLICY_FORCE_FOR_MEDIA] =                "ForceUseForMedia",
-    [AUDIO_POLICY_FORCE_FOR_RECORD] =               "ForceUseForRecord",
-    [AUDIO_POLICY_FORCE_FOR_DOCK] =                 "ForceUseForDock",
-    [AUDIO_POLICY_FORCE_FOR_SYSTEM] =               "ForceUseForSystem",
-    [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] =    "ForceUseForHdmiSystemAudio",
-    [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] =     "ForceUseForEncodedSurround",
-    [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] =      "ForceUseForVibrateRinging"
-};
-
-
-
-
-
-
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf b/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf
deleted file mode 100644
index 043d5a6..0000000
--- a/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf
+++ /dev/null
@@ -1,146 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Criteria file example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-#########################################################
-# Criterion type Example:
-# For each criterion, a couple of numerical, literal values must be provided to the PFW.
-# The numerical part is not mandatory. If not filled by the user, a default numerical value will be
-# automatically provided by audio HAL using the following logic:
-#   - Exclusive criterion:
-#          * 0 -> first literal value,
-#          * 1 -> second literal value,
-#               ...
-#          * N -> (N+1)th literal value.
-#   - Inclusive criterion:
-#          * 1 << 0 -> first literal value,
-#          * 1 << 1 -> second literal value,
-#               ...
-#          * 1 << N -> (N+1)th literal value,
-#
-#########################################################
-# Policy {
-#    InclusiveCriterionType|ExclusiveCriterionType {
-#        <Criterion Name>  [numerical value 1:]<literal value 1>,[numerical value 2:]<literal value 2>,<literal value 3>,...
-#    }
-# }
-
-#########################################################
-# Criterion:
-#########################################################
-# Policy {
-#    Criterion {
-#        <Criterion Name> {
-#            Type            <Criterion type name>
-#            Default         <default value of the criterion>
-#        }
-#    }
-# }
-
-Policy {
-    InclusiveCriterionType {
-        #
-        # DO NOT CHANGE ORDER. This definition must be aligned with the definition of
-        # AUDIO_DEVICE_OUT_* within <system/audio.h> file of android.
-        #
-        OutputDevicesMaskType   Earpiece,Speaker,WiredHeadset,WiredHeadphone,BluetoothSco,BluetoothScoHeadset,BluetoothScoCarkit,BluetoothA2dp,BluetoothA2dpHeadphones,BluetoothA2dpSpeaker,Hdmi,AnlgDockHeadset,DgtlDockHeadset,UsbAccessory,UsbDevice,RemoteSubmix,TelephonyTx,Line,HdmiArc,Spdif,Fm,AuxLine,SpeakerSafe
-        #
-        # DO NOT CHANGE ORDER. This definition must be aligned with the definition of
-        # AUDIO_DEVICE_IN_* within <system/audio.h> file of android.
-        # Note also that direction bit will be decimated by AudioHAL in order to allow using a mask
-        # with the cardinality of 1 between a bit and an input device.
-        #
-        InputDevicesMaskType    Communication,Ambient,BuiltinMic,BluetoothScoHeadset,WiredHeadset,Hdmi,TelephonyRx,BackMic,RemoteSubmix,AnlgDockHeadset,DgtlDockHeadset,UsbAccessory,UsbDevice,FmTuner,TvTune,Line,Spdif,BluetoothA2dp,Loopback
-    }
-    ExclusiveCriterionType {
-        #
-        # The values of the mode MUST be aligned with the definition of the audio_mode_t
-        # from system/audio.h
-        #
-        AndroidModeType     0:Normal,1:RingTone,2:InCall,3:InCommunication
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForCommunicationType    0:ForceNone,1:ForceSpeaker,3:ForceBtSco
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForMediaType            0:ForceNone,1:ForceSpeaker,2:ForceHeadphones,4:ForceBtA2dp,5:ForceWiredAccessory,8:ForceAnalogDock,9:ForceDigitalDock,10:ForceNoBtA2dp
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForRecordType           0:ForceNone,3:ForceBtSco,5:ForceWiredAccessory
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForDockType             0:ForceNone,5:ForceWiredAccessory,6:ForceBtCarDock,7:ForceBtDeskDock,8:ForceAnalogDock,9:ForceDigitalDock
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForSystemType           0:ForceNone,11:ForceSystemEnforced
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForHdmiSystemAudioType  0:ForceNone,12:ForceHdmiSystemEnforced
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio_policy.h
-        #
-        ForceUseForEncodedSurroundType  0:ForceNone,13:ForceEncodedSurroundNever,14:ForceEncodedSurroundAlways
-    }
-
-    Criterion {
-        AvailableInputDevices {
-            Type            InputDevicesMaskType
-            Default         none
-        }
-        AvailableOutputDevices {
-            Type            OutputDevicesMaskType
-            Default         none
-        }
-        TelephonyMode {
-            Type            AndroidModeType
-            Default         Normal
-        }
-        ForceUseForCommunication {
-            Type            ForceUseForCommunicationType
-            Default         ForceNone
-        }
-        ForceUseForMedia {
-            Type            ForceUseForMediaType
-            Default         ForceNone
-        }
-        ForceUseForRecord {
-            Type            ForceUseForRecordType
-            Default         ForceNone
-        }
-        ForceUseForDock {
-            Type            ForceUseForDockType
-            Default         ForceNone
-        }
-        ForceUseForSystem {
-            Type            ForceUseForSystemType
-            Default         ForceNone
-        }
-        ForceUseForHdmiSystemAudio {
-            Type            ForceUseForHdmiSystemAudioType
-            Default         ForceNone
-        }
-        ForceUseForEncodedSurround {
-            Type            ForceUseForEncodedSurroundType
-            Default         ForceNone
-        }
-    }
-}
-
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml
new file mode 100644
index 0000000..ec82b2e
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<criteria>
+    <criterion name="AvailableInputDevices" type="InputDevicesMaskType" default="none"/>
+    <criterion name="AvailableOutputDevices" type="OutputDevicesMaskType" default="none"/>
+    <criterion name="AvailableOutputDevicesAddresses" type="OutputDevicesAddressesType" default="none"/>
+    <criterion name="AvailableInputDevicesAddresses" type="InputDevicesAddressesType" default="none"/>
+    <criterion name="TelephonyMode" type="AndroidModeType" default="Normal"/>
+    <criterion name="ForceUseForCommunication" type="ForceUseForCommunicationType" default="ForceNone"/>
+    <criterion name="ForceUseForMedia" type="ForceUseForMediaType" default="ForceNone"/>
+    <criterion name="ForceUseForRecord" type="ForceUseForRecordType" default="ForceNone"/>
+    <criterion name="ForceUseForDock" type="ForceUseForDockType" default="ForceNone"/>
+    <criterion name="ForceUseForSystem" type="ForceUseForSystemType" default="ForceNone"/>
+    <criterion name="ForceUseForHdmiSystemAudio" type="ForceUseForHdmiSystemAudioType" default="ForceNone"/>
+    <criterion name="ForceUseForEncodedSurround" type="ForceUseForEncodedSurroundType" default="ForceNone"/>
+    <criterion name="ForceUseForVibrateRinging" type="ForceUseForVibrateRingingType" default="ForceNone"/>
+</criteria>
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in
new file mode 100644
index 0000000..6cb799f
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in
@@ -0,0 +1,91 @@
+<?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.
+-->
+<criterion_types>
+    <criterion_type name="OutputDevicesMaskType" type="inclusive"/>
+    <criterion_type name="InputDevicesMaskType" type="inclusive"/>
+    <criterion_type name="OutputDevicesAddressesType" type="inclusive"/>
+    <criterion_type name="InputDevicesAddressesType" type="inclusive"/>
+    <criterion_type name="AndroidModeType" type="exclusive"/>
+    <criterion_type name="BooleanType" type="exclusive">
+        <values>
+            <value literal="False" numerical="0"/>
+            <value literal="True" numerical="1"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForCommunicationType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceSpeaker" numerical="1"/>
+            <value literal="ForceBtSco" numerical="3"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForMediaType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceSpeaker" numerical="1"/>
+            <value literal="ForceHeadphones" numerical="2"/>
+            <value literal="ForceBtA2dp" numerical="4"/>
+            <value literal="ForceWiredAccessory" numerical="5"/>
+            <value literal="ForceAnalogDock" numerical="8"/>
+            <value literal="ForceDigitalDock" numerical="9"/>
+            <value literal="ForceNoBtA2dp" numerical="10"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForRecordType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceBtSco" numerical="3"/>
+            <value literal="ForceWiredAccessory" numerical="5"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForDockType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceWiredAccessory" numerical="5"/>
+            <value literal="ForceBtCarDock" numerical="6"/>
+            <value literal="ForceBtDeskDock" numerical="7"/>
+            <value literal="ForceAnalogDock" numerical="8"/>
+            <value literal="ForceDigitalDock" numerical="9"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForSystemType" type="exclusive" >
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceSystemEnforced" numerical="11"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForHdmiSystemAudioType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceHdmiSystemEnforced" numerical="12"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForEncodedSurroundType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceEncodedSurroundNever" numerical="13"/>
+            <value literal="ForceEncodedSurroundAlways" numerical="14"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForVibrateRingingType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceBtSco" numerical="3"/>
+        </values>
+    </criterion_type>
+</criterion_types>
+
+
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml b/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml
new file mode 100644
index 0000000..5d9193b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- 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.
+-->
+<!--
+    These are the minimum required criteria to be used by Audio HAL to ensure a basic
+    user experience on an Android device
+-->
+<configuration name="audio_policy_wrapper_configuration" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+    <xi:include href="policy_criterion_types.xml"/>
+    <xi:include href="policy_criteria.xml"/>
+
+</configuration>
diff --git a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
index 4c1acfe..1a634a1 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
+++ b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
@@ -16,10 +16,15 @@
 
 #pragma once
 
+#include <AudioGain.h>
+#include <AudioPort.h>
+#include <HwModule.h>
+#include <DeviceDescriptor.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include <utils/Errors.h>
 #include <utils/RWLock.h>
+#include <utils/RefBase.h>
 #include <list>
 #include <map>
 #include <string>
@@ -27,27 +32,17 @@
 
 class CParameterMgrPlatformConnector;
 class ISelectionCriterionInterface;
-class ISelectionCriterionTypeInterface;
 struct cnode;
 
 class ParameterMgrPlatformConnectorLogger;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 class ParameterManagerWrapper
 {
 private:
-    typedef std::pair<int, const char *> CriterionTypeValuePair;
-
-    typedef std::map<std::string, ISelectionCriterionInterface *> CriterionCollection;
-    typedef std::map<std::string, ISelectionCriterionTypeInterface *> CriterionTypeCollection;
-    typedef CriterionCollection::iterator CriterionMapIterator;
-    typedef CriterionCollection::const_iterator CriterionMapConstIterator;
-    typedef CriterionTypeCollection::iterator CriterionTypeMapIterator;
-    typedef CriterionTypeCollection::const_iterator CriteriaTypeMapConstIterator;
+    using Criteria = std::map<std::string, ISelectionCriterionInterface *>;
 
 public:
     ParameterManagerWrapper();
@@ -120,6 +115,9 @@
      */
     status_t setAvailableOutputDevices(audio_devices_t outputDevices);
 
+    status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+                                      audio_policy_dev_state_t state);
+
 private:
     /**
      * Apply the configuration of the platform on the policy parameter manager.
@@ -136,93 +134,11 @@
     /**
      * Load the criterion configuration file.
      *
-     * @param[in] path Criterion conf file path.
-     *
      * @return NO_ERROR is parsing successful, error code otherwise.
      */
-    status_t loadAudioPolicyCriteriaConfig(const char *path);
+    status_t loadConfig();
 
-    /**
-     * Add a criterion type to AudioPolicyPfw.
-     *
-     * @param[in] typeName of the PFW criterion type.
-     * @param[in] isInclusive attribute of the criterion type.
-     */
-    void addCriterionType(const std::string &typeName, bool isInclusive);
-
-    /**
-     * Add a criterion type value pair to AudioPolicyPfw.
-     *
-     * @param[in] typeName criterion type name to which this value pair is added to.
-     * @param[in] numeric part of the value pair.
-     * @param[in] literal part of the value pair.
-     */
-    void addCriterionTypeValuePair(const std::string &typeName, uint32_t numeric,
-                                   const std::string &literal);
-
-    /**
-     * Add a criterion to AudioPolicyPfw.
-     *
-     * @param[in] name of the PFW criterion.
-     * @param[in] typeName criterion type name to which this criterion is associated to.
-     * @param[in] defaultLiteralValue of the PFW criterion.
-     */
-    void addCriterion(const std::string &name,
-                      const std::string &typeName,
-                      const std::string &defaultLiteralValue);
-    /**
-     * Parse and load the inclusive criterion type from configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadInclusiveCriterionType(cnode *root);
-
-    /**
-     * Parse and load the exclusive criterion type from configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadExclusiveCriterionType(cnode *root);
-
-    /**
-     * Parse and load the criteria from configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadCriteria(cnode *root);
-
-    /**
-     * Parse and load a criterion from configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadCriterion(cnode *root);
-
-    /**
-     * Parse and load the criterion types from configuration file.
-     *
-     * @param[in] root node of the configuration file
-     * @param[in] isInclusive true if inclusive, false is exclusive.
-     */
-    void loadCriterionType(cnode *root, bool isInclusive);
-
-    /**
-     * Load the configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadConfig(cnode *root);
-
-    /**
-     * Parse and load the chidren node from a given root node.
-     *
-     * @param[in] root node of the configuration file
-     * @param[out] defaultValue of the parameter manager element to retrieve.
-     * @param[out] type of the parameter manager element to retrieve.
-    */
-    void parseChildren(cnode *root, std::string &defaultValue, std::string &type);
-
-    /**
+     /**
      * Retrieve an element from a map by its name.
      *
      * @tparam T type of element to search.
@@ -266,8 +182,7 @@
 
     bool isValueValidForCriterion(ISelectionCriterionInterface *criterion, int valueToCheck);
 
-    CriterionTypeCollection mPolicyCriterionTypes; /**< Policy Criterion Type map. */
-    CriterionCollection mPolicyCriteria; /**< Policy Criterion Map. */
+    Criteria mPolicyCriteria; /**< Policy Criterion Map. */
 
     CParameterMgrPlatformConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
     ParameterMgrPlatformConnectorLogger *mPfwConnectorLogger; /**< Policy PFW logger. */
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index aa205f0..5544821 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2674,6 +2674,59 @@
     }
 }
 
+status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid,
+        const Vector<AudioDeviceTypeAddr>& devices) {
+    ALOGV("%s() uid=%d num devices %zu", __FUNCTION__, uid, devices.size());
+    // uid/device affinity is only for output devices
+    for (size_t i = 0; i < devices.size(); i++) {
+        if (!audio_is_output_device(devices[i].mType)) {
+            ALOGE("setUidDeviceAffinities() device=%08x is NOT an output device",
+                    devices[i].mType);
+            return BAD_VALUE;
+        }
+    }
+    status_t res =  mPolicyMixes.setUidDeviceAffinities(uid, devices);
+    if (res == NO_ERROR) {
+        // reevaluate outputs for all given devices
+        for (size_t i = 0; i < devices.size(); i++) {
+            sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
+                            devices[i].mType, devices[i].mAddress, String8());
+            SortedVector<audio_io_handle_t> outputs;
+            if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                    outputs,
+                    devDesc->address()) != NO_ERROR) {
+                ALOGE("setUidDeviceAffinities() error in checkOutputsForDevice for device=%08x"
+                        " addr=%s", devices[i].mType, devices[i].mAddress.string());
+                return INVALID_OPERATION;
+            }
+        }
+    }
+    return res;
+}
+
+status_t AudioPolicyManager::removeUidDeviceAffinities(uid_t uid) {
+    ALOGV("%s() uid=%d", __FUNCTION__, uid);
+    Vector<AudioDeviceTypeAddr> devices;
+    status_t res =  mPolicyMixes.getDevicesForUid(uid, devices);
+    if (res == NO_ERROR) {
+        // reevaluate outputs for all found devices
+        for (size_t i = 0; i < devices.size(); i++) {
+            sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
+                    devices[i].mType, devices[i].mAddress, String8());
+            SortedVector<audio_io_handle_t> outputs;
+            if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                    outputs,
+                    devDesc->address()) != NO_ERROR) {
+                ALOGE("%s() error in checkOutputsForDevice for device=%08x addr=%s",
+                        __FUNCTION__, devices[i].mType, devices[i].mAddress.string());
+                return INVALID_OPERATION;
+            }
+        }
+    }
+
+    return res;
+}
+
 void AudioPolicyManager::dump(String8 *dst) const
 {
     dst->appendFormat("\nAudioPolicyManager Dump: %p\n", this);
@@ -4089,9 +4142,9 @@
     for (size_t i = 0; i  < mAvailableInputDevices.size(); i++) {
         if (mAvailableInputDevices[i]->address().isEmpty()) {
             if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                mAvailableInputDevices[i]->address() = String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+                mAvailableInputDevices[i]->setAddress(String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS));
             } else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
-                mAvailableInputDevices[i]->address() = String8(AUDIO_BACK_MICROPHONE_ADDRESS);
+                mAvailableInputDevices[i]->setAddress(String8(AUDIO_BACK_MICROPHONE_ADDRESS));
             }
         }
     }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 35dd87c..9eb1dcf 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -218,6 +218,9 @@
 
         virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes);
         virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
+        virtual status_t setUidDeviceAffinities(uid_t uid,
+                const Vector<AudioDeviceTypeAddr>& devices);
+        virtual status_t removeUidDeviceAffinities(uid_t uid);
 
         virtual status_t startAudioSource(const struct audio_port_config *source,
                                           const audio_attributes_t *attributes,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 439764b..80503fd 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1037,6 +1037,31 @@
     }
 }
 
+status_t AudioPolicyService::setUidDeviceAffinities(uid_t uid,
+        const Vector<AudioDeviceTypeAddr>& devices) {
+    Mutex::Autolock _l(mLock);
+    if(!modifyAudioRoutingAllowed()) {
+        return PERMISSION_DENIED;
+    }
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    AutoCallerClear acc;
+    return mAudioPolicyManager->setUidDeviceAffinities(uid, devices);
+}
+
+status_t AudioPolicyService::removeUidDeviceAffinities(uid_t uid) {
+    Mutex::Autolock _l(mLock);
+    if(!modifyAudioRoutingAllowed()) {
+        return PERMISSION_DENIED;
+    }
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    AutoCallerClear acc;
+    return mAudioPolicyManager->removeUidDeviceAffinities(uid);
+}
+
 status_t AudioPolicyService::startAudioSource(const struct audio_port_config *source,
                                               const audio_attributes_t *attributes,
                                               audio_port_handle_t *portId)
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c44d816..959e757 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -199,6 +199,10 @@
 
     virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
 
+    virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+
+    virtual status_t removeUidDeviceAffinities(uid_t uid);
+
     virtual status_t startAudioSource(const struct audio_port_config *source,
                                       const audio_attributes_t *attributes,
                                       audio_port_handle_t *portId);
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 025f0b2..851dd69 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -83,6 +83,7 @@
         "libhidltransport",
         "libjpeg",
         "libmemunreachable",
+        "libsensorprivacy",
         "libstagefright_foundation",
         "android.frameworks.cameraservice.common@2.0",
         "android.frameworks.cameraservice.service@2.0",
@@ -100,6 +101,7 @@
         "libbinder",
         "libcamera_client",
         "libfmq",
+        "libsensorprivacy",
     ],
 
     include_dirs: [
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6003607..c3113bf 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -54,6 +54,7 @@
 #include <media/IMediaHTTPService.h>
 #include <media/mediaplayer.h>
 #include <mediautils/BatteryNotifier.h>
+#include <sensorprivacy/SensorPrivacyManager.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/String16.h>
@@ -145,6 +146,8 @@
 
     mUidPolicy = new UidPolicy(this);
     mUidPolicy->registerSelf();
+    mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
+    mSensorPrivacyPolicy->registerSelf();
     sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
     if (hcs->registerAsService() != android::OK) {
         ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0",
@@ -230,6 +233,7 @@
 CameraService::~CameraService() {
     VendorTagDescriptor::clearGlobalVendorTagDescriptor();
     mUidPolicy->unregisterSelf();
+    mSensorPrivacyPolicy->unregisterSelf();
 }
 
 void CameraService::onNewProviderRegistered() {
@@ -951,6 +955,14 @@
                 clientName8.string(), clientUid, clientPid, cameraId.string());
     }
 
+    // If sensor privacy is enabled then prevent access to the camera
+    if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
+        ALOGE("Access Denial: cannot use the camera when sensor privacy is enabled");
+        return STATUS_ERROR_FMT(ERROR_DISABLED,
+                "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" when sensor privacy "
+                "is enabled", clientName8.string(), clientUid, clientPid, cameraId.string());
+    }
+
     // Only use passed in clientPid to check permission. Use calling PID as the client PID that's
     // connected to camera service directly.
     originalClientPid = clientPid;
@@ -1603,9 +1615,10 @@
 
     switch(eventId) {
         case ICameraService::EVENT_USER_SWITCHED: {
-            // Try to register for UID policy updates, in case we're recovering
+            // Try to register for UID and sensor privacy policy updates, in case we're recovering
             // from a system server crash
             mUidPolicy->registerSelf();
+            mSensorPrivacyPolicy->registerSelf();
             doUserSwitch(/*newUserIds*/ args);
             break;
         }
@@ -2577,6 +2590,59 @@
 }
 
 // ----------------------------------------------------------------------------
+//                  SensorPrivacyPolicy
+// ----------------------------------------------------------------------------
+void CameraService::SensorPrivacyPolicy::registerSelf() {
+    Mutex::Autolock _l(mSensorPrivacyLock);
+    if (mRegistered) {
+        return;
+    }
+    SensorPrivacyManager spm;
+    spm.addSensorPrivacyListener(this);
+    mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
+    status_t res = spm.linkToDeath(this);
+    if (res == OK) {
+        mRegistered = true;
+        ALOGV("SensorPrivacyPolicy: Registered with SensorPrivacyManager");
+    }
+}
+
+void CameraService::SensorPrivacyPolicy::unregisterSelf() {
+    Mutex::Autolock _l(mSensorPrivacyLock);
+    SensorPrivacyManager spm;
+    spm.removeSensorPrivacyListener(this);
+    spm.unlinkToDeath(this);
+    mRegistered = false;
+    ALOGV("SensorPrivacyPolicy: Unregistered with SensorPrivacyManager");
+}
+
+bool CameraService::SensorPrivacyPolicy::isSensorPrivacyEnabled() {
+    Mutex::Autolock _l(mSensorPrivacyLock);
+    return mSensorPrivacyEnabled;
+}
+
+binder::Status CameraService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool enabled) {
+    {
+        Mutex::Autolock _l(mSensorPrivacyLock);
+        mSensorPrivacyEnabled = enabled;
+    }
+    // if sensor privacy is enabled then block all clients from accessing the camera
+    if (enabled) {
+        sp<CameraService> service = mService.promote();
+        if (service != nullptr) {
+            service->blockAllClients();
+        }
+    }
+    return binder::Status::ok();
+}
+
+void CameraService::SensorPrivacyPolicy::binderDied(const wp<IBinder>& /*who*/) {
+    Mutex::Autolock _l(mSensorPrivacyLock);
+    ALOGV("SensorPrivacyPolicy: SensorPrivacyManager has died");
+    mRegistered = false;
+}
+
+// ----------------------------------------------------------------------------
 //                  CameraState
 // ----------------------------------------------------------------------------
 
@@ -3062,6 +3128,18 @@
     }
 }
 
+void CameraService::blockAllClients() {
+    const auto clients = mActiveClientManager.getAll();
+    for (auto& current : clients) {
+        if (current != nullptr) {
+            const auto basicClient = current->getValue();
+            if (basicClient.get() != nullptr) {
+                basicClient->block();
+            }
+        }
+    }
+}
+
 // NOTE: This is a remote API - make sure all args are validated
 status_t CameraService::shellCommand(int in, int out, int err, const Vector<String16>& args) {
     if (!checkCallingPermission(sManageCameraPermission, nullptr, nullptr)) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d332f6e..a296198 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -18,6 +18,7 @@
 #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
 
 #include <android/hardware/BnCameraService.h>
+#include <android/hardware/BnSensorPrivacyListener.h>
 #include <android/hardware/ICameraServiceListener.h>
 #include <android/hardware/ICameraServiceProxy.h>
 
@@ -554,8 +555,35 @@
         std::unordered_map<uid_t, bool> mOverrideUids;
     }; // class UidPolicy
 
+    // If sensor privacy is enabled then all apps, including those that are active, should be
+    // prevented from accessing the camera.
+    class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener,
+            public virtual IBinder::DeathRecipient {
+        public:
+            explicit SensorPrivacyPolicy(wp<CameraService> service)
+                    : mService(service), mSensorPrivacyEnabled(false), mRegistered(false) {}
+
+            void registerSelf();
+            void unregisterSelf();
+
+            bool isSensorPrivacyEnabled();
+
+            binder::Status onSensorPrivacyChanged(bool enabled);
+
+            // IBinder::DeathRecipient implementation
+            virtual void binderDied(const wp<IBinder> &who);
+
+        private:
+            wp<CameraService> mService;
+            Mutex mSensorPrivacyLock;
+            bool mSensorPrivacyEnabled;
+            bool mRegistered;
+    };
+
     sp<UidPolicy> mUidPolicy;
 
+    sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
+
     // Delay-load the Camera HAL module
     virtual void onFirstRef();
 
@@ -825,6 +853,9 @@
     // Blocks all clients from the UID
     void blockClientsForUid(uid_t uid);
 
+    // Blocks all active clients.
+    void blockAllClients();
+
     // Overrides the UID state as if it is idle
     status_t handleSetUidState(const Vector<String16>& args, int err);
 
diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
index e5e5024..f063506 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
+++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
@@ -139,18 +139,18 @@
     }
     CameraMetadataNative &result = resultWrapper->mResult;
     auto resultExtras = resultWrapper->mResultExtras;
-    auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos;
     HCaptureResultExtras hResultExtras =
             hardware::cameraservice::utils::conversion::convertToHidl(resultExtras);
-    hidl_vec<HPhysicalCaptureResultInfo> hPhysicalCaptureResultInfos =
-            hardware::cameraservice::utils::conversion::convertToHidl(
-                    physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue);
 
     // Convert Metadata into HCameraMetadata;
     FmqSizeOrMetadata hResult;
     const camera_metadata_t *rawMetadata = result.getAndLock();
     converter->convertResultMetadataToHidl(rawMetadata, &hResult);
     result.unlock(rawMetadata);
+    auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos;
+    hidl_vec<HPhysicalCaptureResultInfo> hPhysicalCaptureResultInfos =
+            hardware::cameraservice::utils::conversion::convertToHidl(
+                    physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue);
     auto ret = converter->mBase->onResultReceived(hResult, hResultExtras,
                                                   hPhysicalCaptureResultInfos);
     if (!ret.isOk()) {
diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp
index 582ce34..a87812b 100644
--- a/services/camera/libcameraservice/hidl/Convert.cpp
+++ b/services/camera/libcameraservice/hidl/Convert.cpp
@@ -89,8 +89,9 @@
     for (auto &handle : windowHandles) {
         iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(handle)));
     }
+    String16 physicalCameraId16(hOutputConfiguration.physicalCameraId.c_str());
     hardware::camera2::params::OutputConfiguration outputConfiguration(
-        iGBPs, convertFromHidl(hOutputConfiguration.rotation),
+        iGBPs, convertFromHidl(hOutputConfiguration.rotation), physicalCameraId16,
         hOutputConfiguration.windowGroupId, OutputConfiguration::SURFACE_TYPE_UNKNOWN, 0, 0,
         (windowHandles.size() > 1));
     return outputConfiguration;
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index 653317b..8c40ad1 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -1,5 +1,6 @@
 cc_library_shared {
     name: "libmedia_codecserviceregistrant",
+    vendor_available: true,
     srcs: [
         "CodecServiceRegistrant.cpp",
     ],
@@ -39,6 +40,7 @@
         "libcodec2_soft_opusdec",
         "libcodec2_soft_vp8dec",
         "libcodec2_soft_vp9dec",
+        "libcodec2_soft_av1dec",
         "libcodec2_soft_vp8enc",
         "libcodec2_soft_vp9enc",
         "libcodec2_soft_rawdec",
diff --git a/services/mediadrm/tests/Android.mk b/services/mediadrm/tests/Android.mk
deleted file mode 100644
index e2f7399..0000000
--- a/services/mediadrm/tests/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := DrmSessionManager_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-	DrmSessionManager_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-	liblog \
-	libmediaplayerservice \
-	libutils \
-
-LOCAL_C_INCLUDES := \
-	frameworks/av/include \
-	frameworks/av/media/libmediaplayerservice \
-
-LOCAL_CFLAGS += -Werror -Wall
-
-LOCAL_32_BIT_ONLY := true
-
-include $(BUILD_NATIVE_TEST)
-
diff --git a/services/mediadrm/tests/DrmSessionManager_test.cpp b/services/mediadrm/tests/DrmSessionManager_test.cpp
deleted file mode 100644
index de350a1..0000000
--- a/services/mediadrm/tests/DrmSessionManager_test.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "DrmSessionManager_test"
-#include <utils/Log.h>
-
-#include <gtest/gtest.h>
-
-#include "Drm.h"
-#include "DrmSessionClientInterface.h"
-#include "DrmSessionManager.h"
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/ProcessInfoInterface.h>
-
-namespace android {
-
-struct FakeProcessInfo : public ProcessInfoInterface {
-    FakeProcessInfo() {}
-    virtual ~FakeProcessInfo() {}
-
-    virtual bool getPriority(int pid, int* priority) {
-        // For testing, use pid as priority.
-        // Lower the value higher the priority.
-        *priority = pid;
-        return true;
-    }
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
-};
-
-struct FakeDrm : public DrmSessionClientInterface {
-    FakeDrm() {}
-    virtual ~FakeDrm() {}
-
-    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
-        mReclaimedSessions.push_back(sessionId);
-        return true;
-    }
-
-    const Vector<Vector<uint8_t> >& reclaimedSessions() const {
-        return mReclaimedSessions;
-    }
-
-private:
-    Vector<Vector<uint8_t> > mReclaimedSessions;
-
-    DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
-};
-
-static const int kTestPid1 = 30;
-static const int kTestPid2 = 20;
-static const uint8_t kTestSessionId1[] = {1, 2, 3};
-static const uint8_t kTestSessionId2[] = {4, 5, 6, 7, 8};
-static const uint8_t kTestSessionId3[] = {9, 0};
-
-class DrmSessionManagerTest : public ::testing::Test {
-public:
-    DrmSessionManagerTest()
-        : mDrmSessionManager(new DrmSessionManager(new FakeProcessInfo())),
-          mTestDrm1(new FakeDrm()),
-          mTestDrm2(new FakeDrm()) {
-        GetSessionId(kTestSessionId1, ARRAY_SIZE(kTestSessionId1), &mSessionId1);
-        GetSessionId(kTestSessionId2, ARRAY_SIZE(kTestSessionId2), &mSessionId2);
-        GetSessionId(kTestSessionId3, ARRAY_SIZE(kTestSessionId3), &mSessionId3);
-    }
-
-protected:
-    static void GetSessionId(const uint8_t* ids, size_t num, Vector<uint8_t>* sessionId) {
-        for (size_t i = 0; i < num; ++i) {
-            sessionId->push_back(ids[i]);
-        }
-    }
-
-    static void ExpectEqSessionInfo(const SessionInfo& info, sp<DrmSessionClientInterface> drm,
-            const Vector<uint8_t>& sessionId, int64_t timeStamp) {
-        EXPECT_EQ(drm, info.drm);
-        EXPECT_TRUE(isEqualSessionId(sessionId, info.sessionId));
-        EXPECT_EQ(timeStamp, info.timeStamp);
-    }
-
-    void addSession() {
-        mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mSessionId1);
-        mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId2);
-        mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId3);
-        const PidSessionInfosMap& map = sessionMap();
-        EXPECT_EQ(2u, map.size());
-        ssize_t index1 = map.indexOfKey(kTestPid1);
-        ASSERT_GE(index1, 0);
-        const SessionInfos& infos1 = map[index1];
-        EXPECT_EQ(1u, infos1.size());
-        ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 0);
-
-        ssize_t index2 = map.indexOfKey(kTestPid2);
-        ASSERT_GE(index2, 0);
-        const SessionInfos& infos2 = map[index2];
-        EXPECT_EQ(2u, infos2.size());
-        ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId2, 1);
-        ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 2);
-    }
-
-    const PidSessionInfosMap& sessionMap() {
-        return mDrmSessionManager->mSessionMap;
-    }
-
-    void testGetLowestPriority() {
-        int pid;
-        int priority;
-        EXPECT_FALSE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
-        addSession();
-        EXPECT_TRUE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
-        EXPECT_EQ(kTestPid1, pid);
-        FakeProcessInfo processInfo;
-        int priority1;
-        processInfo.getPriority(kTestPid1, &priority1);
-        EXPECT_EQ(priority1, priority);
-    }
-
-    void testGetLeastUsedSession() {
-        sp<DrmSessionClientInterface> drm;
-        Vector<uint8_t> sessionId;
-        EXPECT_FALSE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
-
-        addSession();
-
-        EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
-        EXPECT_EQ(mTestDrm1, drm);
-        EXPECT_TRUE(isEqualSessionId(mSessionId1, sessionId));
-
-        EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
-        EXPECT_EQ(mTestDrm2, drm);
-        EXPECT_TRUE(isEqualSessionId(mSessionId2, sessionId));
-
-        // mSessionId2 is no longer the least used session.
-        mDrmSessionManager->useSession(mSessionId2);
-        EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
-        EXPECT_EQ(mTestDrm2, drm);
-        EXPECT_TRUE(isEqualSessionId(mSessionId3, sessionId));
-    }
-
-    sp<DrmSessionManager> mDrmSessionManager;
-    sp<FakeDrm> mTestDrm1;
-    sp<FakeDrm> mTestDrm2;
-    Vector<uint8_t> mSessionId1;
-    Vector<uint8_t> mSessionId2;
-    Vector<uint8_t> mSessionId3;
-};
-
-TEST_F(DrmSessionManagerTest, addSession) {
-    addSession();
-}
-
-TEST_F(DrmSessionManagerTest, useSession) {
-    addSession();
-
-    mDrmSessionManager->useSession(mSessionId1);
-    mDrmSessionManager->useSession(mSessionId3);
-
-    const PidSessionInfosMap& map = sessionMap();
-    const SessionInfos& infos1 = map.valueFor(kTestPid1);
-    const SessionInfos& infos2 = map.valueFor(kTestPid2);
-    ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 3);
-    ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 4);
-}
-
-TEST_F(DrmSessionManagerTest, removeSession) {
-    addSession();
-
-    mDrmSessionManager->removeSession(mSessionId2);
-
-    const PidSessionInfosMap& map = sessionMap();
-    EXPECT_EQ(2u, map.size());
-    const SessionInfos& infos1 = map.valueFor(kTestPid1);
-    const SessionInfos& infos2 = map.valueFor(kTestPid2);
-    EXPECT_EQ(1u, infos1.size());
-    EXPECT_EQ(1u, infos2.size());
-    // mSessionId2 has been removed.
-    ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId3, 2);
-}
-
-TEST_F(DrmSessionManagerTest, removeDrm) {
-    addSession();
-
-    sp<FakeDrm> drm = new FakeDrm;
-    const uint8_t ids[] = {123};
-    Vector<uint8_t> sessionId;
-    GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
-    mDrmSessionManager->addSession(kTestPid2, drm, sessionId);
-
-    mDrmSessionManager->removeDrm(mTestDrm2);
-
-    const PidSessionInfosMap& map = sessionMap();
-    const SessionInfos& infos2 = map.valueFor(kTestPid2);
-    EXPECT_EQ(1u, infos2.size());
-    // mTestDrm2 has been removed.
-    ExpectEqSessionInfo(infos2[0], drm, sessionId, 3);
-}
-
-TEST_F(DrmSessionManagerTest, reclaimSession) {
-    EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
-    addSession();
-
-    // calling pid priority is too low
-    EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
-
-    EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
-    EXPECT_EQ(1u, mTestDrm1->reclaimedSessions().size());
-    EXPECT_TRUE(isEqualSessionId(mSessionId1, mTestDrm1->reclaimedSessions()[0]));
-
-    mDrmSessionManager->removeSession(mSessionId1);
-
-    // add a session from a higher priority process.
-    sp<FakeDrm> drm = new FakeDrm;
-    const uint8_t ids[] = {1, 3, 5};
-    Vector<uint8_t> sessionId;
-    GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
-    mDrmSessionManager->addSession(15, drm, sessionId);
-
-    EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
-    EXPECT_EQ(1u, mTestDrm2->reclaimedSessions().size());
-    // mSessionId2 is reclaimed.
-    EXPECT_TRUE(isEqualSessionId(mSessionId2, mTestDrm2->reclaimedSessions()[0]));
-}
-
-TEST_F(DrmSessionManagerTest, getLowestPriority) {
-    testGetLowestPriority();
-}
-
-TEST_F(DrmSessionManagerTest, getLeastUsedSession_l) {
-    testGetLeastUsedSession();
-}
-
-} // namespace android
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index e31eadc..6101c8a 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -40,7 +40,7 @@
 
 LOCAL_SRC_FILES := main_extractorservice.cpp
 LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils \
-    liblog libbase libicuuc libavservices_minijail
+    liblog libbase libandroidicu libavservices_minijail
 LOCAL_STATIC_LIBRARIES := libicuandroid_utils
 LOCAL_MODULE:= mediaextractor
 LOCAL_INIT_RC := mediaextractor.rc
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 8b26178..0665930 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -59,6 +59,10 @@
     return CreateIDataSourceFromDataSource(source);
 }
 
+std::unordered_set<std::string> MediaExtractorService::getSupportedTypes() {
+    return MediaExtractorFactory::getSupportedTypes();
+}
+
 status_t MediaExtractorService::dump(int fd, const Vector<String16>& args) {
     return MediaExtractorFactory::dump(fd, args) || dumpExtractors(fd, args);
 }
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index 6007004..c9cebcf 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -37,6 +37,8 @@
 
     virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length);
 
+    virtual std::unordered_set<std::string> getSupportedTypes();
+
     virtual status_t    dump(int fd, const Vector<String16>& args);
 
     virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
index 6d9ed6f..35ac458 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
@@ -21,6 +21,7 @@
 getuid: 1
 setpriority: 1
 sigaltstack: 1
+fstat: 1
 fstatfs: 1
 newfstatat: 1
 restart_syscall: 1
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 944abcc..fe2ccf2 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -765,10 +765,7 @@
             }
 
             recognitionEvent->capture_session = model->mCaptureSession;
-            // Don't reset the model state if this recognition event is a get-state response
-            if (recognitionEvent->status != RECOGNITION_STATUS_GET_STATE_RESPONSE) {
-                model->mState = Model::STATE_IDLE;
-            }
+            model->mState = Model::STATE_IDLE;
             clients.add(model->mModuleClient);
         }
     } break;