Merge "Clean up AudioTrackThread and AudioRecordThread constructor"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 793cbf4..e584ffb 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -81,6 +81,7 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libstagefright_xmlparser@1.0.so)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libstagefright_soft_*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk/libstagefright_soft_*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libaudiopolicyengineconfig*)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index cd4e06e..c71ac17 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -1,6 +1,9 @@
 cc_library {
     name: "libstagefright_bufferpool@2.0",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     srcs: [
         "Accessor.cpp",
         "AccessorImpl.cpp",
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 2c0a7a0..7045b6a 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@
 namespace android {
 
 class C2SoftHevcEnc::IntfImpl : public C2InterfaceHelper {
-   public:
+  public:
     explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
         : C2InterfaceHelper(helper) {
         setDerivedInstance(this);
@@ -73,6 +73,7 @@
                              0u, (uint64_t)C2MemoryUsage::CPU_READ))
                          .build());
 
+        // matches size limits in codec library
         addParameter(
             DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
                 .withDefault(new C2StreamPictureSizeInfo::input(0u, 320, 240))
@@ -91,6 +92,7 @@
                     Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
                 .build());
 
+        // matches limits in codec library
         addParameter(
             DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
                 .withDefault(new C2StreamBitrateInfo::output(0u, 64000))
@@ -98,6 +100,7 @@
                 .withSetter(BitrateSetter)
                 .build());
 
+        // matches levels allowed within codec library
         addParameter(
             DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
                 .withDefault(new C2StreamProfileLevelInfo::output(
@@ -137,7 +140,7 @@
                              C2P<C2StreamBitrateInfo::output>& me) {
         (void)mayBlock;
         C2R res = C2R::Ok();
-        if (me.v.value <= 4096) {
+        if (me.v.value < 4096) {
             me.set().value = 4096;
         }
         return res;
@@ -278,7 +281,7 @@
         return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.);
     }
 
-   std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const {
+    std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const {
         return mSize;
     }
     std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const {
@@ -304,18 +307,21 @@
     std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
     std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
 };
+
 constexpr char COMPONENT_NAME[] = "c2.android.hevc.encoder";
 
 static size_t GetCPUCoreCount() {
-    long cpuCoreCount = 1;
+    long cpuCoreCount = 0;
+
 #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: %ld", cpuCoreCount);
+
+    if (cpuCoreCount < 1)
+        cpuCoreCount = 1;
     return (size_t)cpuCoreCount;
 }
 
@@ -383,7 +389,7 @@
 
 c2_status_t C2SoftHevcEnc::initEncParams() {
     mCodecCtx = nullptr;
-    mNumCores = MIN(GetCPUCoreCount(), CODEC_MAX_CORES);
+    mNumCores = std::min(GetCPUCoreCount(), (size_t) CODEC_MAX_CORES);
     memset(&mEncParams, 0, sizeof(ihevce_static_cfg_params_t));
 
     // default configuration
@@ -397,7 +403,8 @@
     mEncParams.s_src_prms.i4_width = mSize->width;
     mEncParams.s_src_prms.i4_height = mSize->height;
     mEncParams.s_src_prms.i4_frm_rate_denom = 1000;
-    mEncParams.s_src_prms.i4_frm_rate_num = mFrameRate->value * mEncParams.s_src_prms.i4_frm_rate_denom;
+    mEncParams.s_src_prms.i4_frm_rate_num =
+        mFrameRate->value * mEncParams.s_src_prms.i4_frm_rate_denom;
     mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset = IHEVCE_QUALITY_P5;
     mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_tgt_bitrate[0] =
         mBitrate->value;
@@ -470,7 +477,7 @@
                                          const C2GraphicView* const input,
                                          uint64_t timestamp) {
     ihevce_static_cfg_params_t* params = &mEncParams;
-    memset(ps_encode_ip, 0, sizeof(ihevce_inp_buf_t));
+    memset(ps_encode_ip, 0, sizeof(*ps_encode_ip));
 
     if (!input) {
         return C2_OK;
@@ -495,13 +502,14 @@
     int32_t uStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
     int32_t vStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
 
-    uint32_t width = mSize->width;
-    uint32_t height = mSize->height;
+    const uint32_t width = mSize->width;
+    const uint32_t height = mSize->height;
 
-    // width and height are always even
-    // width and height are always even (as block size is 16x16)
-    CHECK_EQ((width & 1u), 0u);
-    CHECK_EQ((height & 1u), 0u);
+    // width and height must be even
+    if (width & 1u || height & 1u) {
+        ALOGW("height(%u) and width(%u) must both be even", height, width);
+        return C2_BAD_VALUE;
+    }
 
     size_t yPlaneSize = width * height;
 
@@ -650,6 +658,7 @@
         if (view->error() != C2_OK) {
             ALOGE("graphic view map err = %d", view->error());
             mSignalledError = true;
+            work->result = C2_CORRUPTED;
             return;
         }
     }
@@ -687,8 +696,8 @@
 
     status = setEncodeArgs(&s_encode_ip, view.get(), timestamp);
     if (C2_OK != status) {
-        mSignalledError = true;
         ALOGE("setEncodeArgs failed : 0x%x", status);
+        mSignalledError = true;
         work->result = status;
         return;
     }
@@ -761,8 +770,9 @@
         : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
               GetCodec2PlatformComponentStore()->getParamReflector())) {}
 
-    virtual c2_status_t createComponent(
-        c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+    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 C2SoftHevcEnc(
@@ -772,8 +782,9 @@
         return C2_OK;
     }
 
-    virtual c2_status_t createInterface(
-        c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+    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<C2SoftHevcEnc::IntfImpl>(
@@ -783,7 +794,7 @@
         return C2_OK;
     }
 
-    virtual ~C2SoftHevcEncFactory() override = default;
+    ~C2SoftHevcEncFactory() override = default;
 
    private:
     std::shared_ptr<C2ReflectorHelper> mHelper;
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.h b/media/codec2/components/hevc/C2SoftHevcEnc.h
index c22fea2..9d90b95 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.h
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018 The Android Open Source Project
+ * Copyright 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,18 +17,18 @@
 #ifndef ANDROID_C2_SOFT_HEVC_ENC_H_
 #define ANDROID_C2_SOFT_HEVC_ENC_H_
 
-#include <map>
-#include <utils/Vector.h>
-#include <media/stagefright/foundation/ColorUtils.h>
 #include <SimpleC2Component.h>
+#include <algorithm>
+#include <map>
+#include <media/stagefright/foundation/ColorUtils.h>
+#include <utils/Vector.h>
 
 #include "ihevc_typedefs.h"
 
 namespace android {
-#define MIN(a, b) ((a) < (b)) ? (a) : (b)
 
 /** Get time */
-#define GETTIME(a, b) gettimeofday(a, b);
+#define GETTIME(a, b) gettimeofday(a, b)
 
 /** Compute difference between start and end */
 #define TIME_DIFF(start, end, diff)                      \
@@ -55,7 +55,7 @@
                       const std::shared_ptr<C2BlockPool>& pool) override;
 
    protected:
-    virtual ~C2SoftHevcEnc();
+    ~C2SoftHevcEnc() override;
 
    private:
     std::shared_ptr<IntfImpl> mIntf;
diff --git a/media/codec2/components/opus/C2SoftOpusDec.cpp b/media/codec2/components/opus/C2SoftOpusDec.cpp
index 680712e..7dcd53d 100644
--- a/media/codec2/components/opus/C2SoftOpusDec.cpp
+++ b/media/codec2/components/opus/C2SoftOpusDec.cpp
@@ -252,20 +252,25 @@
     const uint8_t *data = rView.data() + inOffset;
     if (mInputBufferCount < 3) {
         if (mInputBufferCount == 0) {
-            size_t opusHeadSize = inSize;
+            size_t opusHeadSize = 0;
             size_t codecDelayBufSize = 0;
             size_t seekPreRollBufSize = 0;
-            void *opusHeadBuf = (void *)data;
+            void *opusHeadBuf = NULL;
             void *codecDelayBuf = NULL;
             void *seekPreRollBuf = NULL;
 
-            GetOpusHeaderBuffers(data, inSize, &opusHeadBuf,
-                                &opusHeadSize, &codecDelayBuf,
-                                &codecDelayBufSize, &seekPreRollBuf,
-                                &seekPreRollBufSize);
+            if (!GetOpusHeaderBuffers(data, inSize, &opusHeadBuf,
+                                     &opusHeadSize, &codecDelayBuf,
+                                     &codecDelayBufSize, &seekPreRollBuf,
+                                     &seekPreRollBufSize)) {
+                ALOGE("%s encountered error in GetOpusHeaderBuffers", __func__);
+                mSignalledError = true;
+                work->result = C2_CORRUPTED;
+                return;
+            }
 
             if (!ParseOpusHeader((uint8_t *)opusHeadBuf, opusHeadSize, &mHeader)) {
-                ALOGE("Encountered error while Parsing Opus Header.");
+                ALOGE("%s Encountered error while Parsing Opus Header.", __func__);
                 mSignalledError = true;
                 work->result = C2_CORRUPTED;
                 return;
@@ -304,16 +309,16 @@
                 return;
             }
 
-            if (codecDelayBuf && codecDelayBufSize == 8) {
+            if (codecDelayBuf && codecDelayBufSize == sizeof(uint64_t)) {
                 uint64_t value;
                 memcpy(&value, codecDelayBuf, sizeof(uint64_t));
                 mCodecDelay = ns_to_samples(value, kRate);
                 mSamplesToDiscard = mCodecDelay;
                 ++mInputBufferCount;
             }
-            if (seekPreRollBuf && seekPreRollBufSize == 8) {
+            if (seekPreRollBuf && seekPreRollBufSize == sizeof(uint64_t)) {
                 uint64_t value;
-                memcpy(&value, codecDelayBuf, sizeof(uint64_t));
+                memcpy(&value, seekPreRollBuf, sizeof(uint64_t));
                 mSeekPreRoll = ns_to_samples(value, kRate);
                 ++mInputBufferCount;
             }
diff --git a/media/codec2/core/Android.bp b/media/codec2/core/Android.bp
index b723755..a7e8997 100644
--- a/media/codec2/core/Android.bp
+++ b/media/codec2/core/Android.bp
@@ -7,6 +7,9 @@
 cc_library_shared {
     name: "libcodec2",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: ["C2.cpp"],
 
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index d0296a5..f5aa65b 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -3,6 +3,9 @@
 cc_library {
     name: "libcodec2_hidl@1.0",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     defaults: ["hidl_defaults"],
 
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index e0b1355..ab6a105 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -14,6 +14,9 @@
 cc_library_shared {
     name: "libcodec2_vndk",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "C2AllocatorIon.cpp",
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 7239302..a399940 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -119,6 +119,9 @@
     const mkvparser::BlockEntry *mBlockEntry;
     long mBlockEntryIndex;
 
+    unsigned long mTrackType;
+    void seekwithoutcue_l(int64_t seekTimeUs, int64_t *actualFrameTimeUs);
+
     void advance_l();
 
     BlockIterator(const BlockIterator &);
@@ -290,6 +293,7 @@
       mCluster(NULL),
       mBlockEntry(NULL),
       mBlockEntryIndex(0) {
+    mTrackType = mExtractor->mSegment->GetTracks()->GetTrackByNumber(trackNum)->GetType();
     reset();
 }
 
@@ -442,12 +446,14 @@
         }
 
         if (!pCues) {
-            ALOGE("No Cues in file");
+            ALOGV("No Cues in file,seek without cue data");
+            seekwithoutcue_l(seekTimeUs, actualFrameTimeUs);
             return;
         }
     }
     else if (!pSH) {
-        ALOGE("No SeekHead");
+        ALOGV("No SeekHead, seek without cue data");
+        seekwithoutcue_l(seekTimeUs, actualFrameTimeUs);
         return;
     }
 
@@ -456,7 +462,9 @@
     while (!pCues->DoneParsing()) {
         pCues->LoadCuePoint();
         pCP = pCues->GetLast();
-        CHECK(pCP);
+        ALOGV("pCP = %s", pCP == NULL ? "NULL" : "not NULL");
+        if (pCP == NULL)
+            continue;
 
         size_t trackCount = mExtractor->mTracks.size();
         for (size_t index = 0; index < trackCount; ++index) {
@@ -494,6 +502,7 @@
     // Always *search* based on the video track, but finalize based on mTrackNum
     if (!pTP) {
         ALOGE("Did not locate the video track for seeking");
+        seekwithoutcue_l(seekTimeUs, actualFrameTimeUs);
         return;
     }
 
@@ -537,6 +546,31 @@
     return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
 }
 
+void BlockIterator::seekwithoutcue_l(int64_t seekTimeUs, int64_t *actualFrameTimeUs) {
+    mCluster = mExtractor->mSegment->FindCluster(seekTimeUs * 1000ll);
+    const long status = mCluster->GetFirst(mBlockEntry);
+    if (status < 0) {  // error
+        ALOGE("get last blockenry failed!");
+        mCluster = NULL;
+        return;
+    }
+    mBlockEntryIndex = 0;
+    while (!eos() && ((block()->GetTrackNumber() != mTrackNum) || (blockTimeUs() < seekTimeUs))) {
+        advance_l();
+    }
+
+    // video track will seek to the next key frame.
+    if (mTrackType == 1) {
+        while (!eos() && ((block()->GetTrackNumber() != mTrackNum) ||
+                      !mBlockEntry->GetBlock()->IsKey())) {
+            advance_l();
+        }
+    }
+    *actualFrameTimeUs = blockTimeUs();
+     ALOGV("seekTimeUs:%lld, actualFrameTimeUs:%lld, tracknum:%lld",
+              (long long)seekTimeUs, (long long)*actualFrameTimeUs, (long long)mTrackNum);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 static unsigned U24_AT(const uint8_t *ptr) {
@@ -956,17 +990,56 @@
         return;
     }
 
-    // from mkvparser::Segment::Load(), but stop at first cluster
-    ret = mSegment->ParseHeaders();
-    if (ret == 0) {
-        long len;
-        ret = mSegment->LoadCluster(pos, len);
-        if (ret >= 1) {
-            // no more clusters
-            ret = 0;
+    if (mIsLiveStreaming) {
+        // from mkvparser::Segment::Load(), but stop at first cluster
+        ret = mSegment->ParseHeaders();
+        if (ret == 0) {
+            long len;
+            ret = mSegment->LoadCluster(pos, len);
+            if (ret >= 1) {
+                // no more clusters
+                ret = 0;
+            }
+        } else if (ret > 0) {
+            ret = mkvparser::E_BUFFER_NOT_FULL;
         }
-    } else if (ret > 0) {
-        ret = mkvparser::E_BUFFER_NOT_FULL;
+    } else {
+        ret = mSegment->ParseHeaders();
+        if (ret < 0) {
+            ALOGE("Segment parse header return fail %lld", ret);
+            delete mSegment;
+            mSegment = NULL;
+            return;
+        } else if (ret == 0) {
+            const mkvparser::Cues* mCues = mSegment->GetCues();
+            const mkvparser::SeekHead* mSH = mSegment->GetSeekHead();
+            if ((mCues == NULL) && (mSH != NULL)) {
+                size_t count = mSH->GetCount();
+                const mkvparser::SeekHead::Entry* mEntry;
+                for (size_t index = 0; index < count; index++) {
+                    mEntry = mSH->GetEntry(index);
+                    if (mEntry->id == 0x0C53BB6B) {  // Cues ID
+                        long len;
+                        long long pos;
+                        mSegment->ParseCues(mEntry->pos, pos, len);
+                        mCues = mSegment->GetCues();
+                        ALOGV("find cue data by seekhead");
+                        break;
+                    }
+                }
+            }
+
+            if (mCues) {
+                long len;
+                ret = mSegment->LoadCluster(pos, len);
+                ALOGV("has Cue data, Cluster num=%ld", mSegment->GetCount());
+            } else  {
+                long status_Load = mSegment->Load();
+                ALOGW("no Cue data,Segment Load status:%ld",status_Load);
+            }
+        } else if (ret > 0) {
+            ret = mkvparser::E_BUFFER_NOT_FULL;
+        }
     }
 
     if (ret < 0) {
diff --git a/media/extractors/mp4/AC4Parser.cpp b/media/extractors/mp4/AC4Parser.cpp
index 59a2e9b..13d60c8 100644
--- a/media/extractors/mp4/AC4Parser.cpp
+++ b/media/extractors/mp4/AC4Parser.cpp
@@ -260,7 +260,7 @@
 
     int32_t short_program_id = -1;
     if (bitstream_version > 1) {
-        if (ac4_dsi_version == 0){
+        if (ac4_dsi_version == 0) {
             ALOGE("invalid ac4 dsi");
             return false;
         }
@@ -295,6 +295,7 @@
         bool b_single_substream_group = false;
         uint32_t presentation_config = 0, presentation_version = 0;
         uint32_t pres_bytes = 0;
+        uint64_t start = 0;
 
         if (ac4_dsi_version == 0) {
             CHECK_BITS_LEFT(1 + 5 + 5);
@@ -315,6 +316,8 @@
                 mBitReader.skipBits(pres_bytes * 8);
                 continue;
             }
+            /* record a marker, less the size of the presentation_config */
+            start = (mDSISize - mBitReader.numBitsLeft()) / 8;
             // ac4_presentation_v0_dsi(), ac4_presentation_v1_dsi() and ac4_presentation_v2_dsi()
             // all start with a presentation_config of 5 bits
             CHECK_BITS_LEFT(5);
@@ -338,9 +341,6 @@
             (presentation_config >= NELEM(PresentationConfig) ?
             "reserved" : PresentationConfig[presentation_config]));
 
-        /* record a marker, less the size of the presentation_config */
-        uint64_t start = (mDSISize - mBitReader.numBitsLeft()) / 8;
-
         bool b_add_emdf_substreams = false;
         if (!b_single_substream_group && presentation_config == 6) {
             b_add_emdf_substreams = true;
@@ -535,14 +535,14 @@
                     }
                     break;
                 }
-                CHECK_BITS_LEFT(1 + 1);
-                bool b_pre_virtualized = (mBitReader.getBits(1) == 1);
-                mPresentations[presentation].mPreVirtualized = b_pre_virtualized;
-                b_add_emdf_substreams = (mBitReader.getBits(1) == 1);
-                ALOGV("%u: b_pre_virtualized = %s\n", presentation, BOOLSTR(b_pre_virtualized));
-                ALOGV("%u: b_add_emdf_substreams = %s\n", presentation,
-                    BOOLSTR(b_add_emdf_substreams));
             }
+            CHECK_BITS_LEFT(1 + 1);
+            bool b_pre_virtualized = (mBitReader.getBits(1) == 1);
+            mPresentations[presentation].mPreVirtualized = b_pre_virtualized;
+            b_add_emdf_substreams = (mBitReader.getBits(1) == 1);
+            ALOGV("%u: b_pre_virtualized = %s\n", presentation, BOOLSTR(b_pre_virtualized));
+            ALOGV("%u: b_add_emdf_substreams = %s\n", presentation,
+                BOOLSTR(b_add_emdf_substreams));
         }
         if (b_add_emdf_substreams) {
             CHECK_BITS_LEFT(7);
@@ -599,10 +599,6 @@
 
         if (ac4_dsi_version == 1) {
             uint64_t end = (mDSISize - mBitReader.numBitsLeft()) / 8;
-            if (mBitReader.numBitsLeft() % 8 != 0) {
-                end += 1;
-            }
-
             uint64_t presentation_bytes = end - start;
             uint64_t skip_bytes = pres_bytes - presentation_bytes;
             ALOGV("skipping = %" PRIu64 " bytes", skip_bytes);
@@ -612,7 +608,7 @@
 
         // we should know this or something is probably wrong
         // with the bitstream (or we don't support it)
-        if (mPresentations[presentation].mChannelMode == -1){
+        if (mPresentations[presentation].mChannelMode == -1) {
             ALOGE("could not determing channel mode of presentation %d", presentation);
             return false;
         }
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index c776c51..4298b57 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -142,6 +142,7 @@
     uint8_t *mSrcBuffer;
 
     bool mIsHeif;
+    bool mIsAudio;
     sp<ItemTable> mItemTable;
 
     // Start offset from composition time to presentation time.
@@ -4530,6 +4531,7 @@
     }
 
     mIsPcm = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW);
+    mIsAudio = !strncasecmp(mime, "audio/", 6);
 
     if (mIsPcm) {
         int32_t numChannels = 0;
@@ -5416,8 +5418,11 @@
                 findFlags = SampleTable::kFlagBefore;
             }
 
-            uint32_t syncSampleIndex;
-            if (err == OK) {
+            uint32_t syncSampleIndex = sampleIndex;
+            // assume every audio sample is a sync sample. This works around
+            // seek issues with files that were incorrectly written with an
+            // empty or single-sample stss block for the audio track
+            if (err == OK && !mIsAudio) {
                 err = mSampleTable->findSyncSampleNear(
                         sampleIndex, &syncSampleIndex, findFlags);
             }
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index cb1517e..8df1921 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -70,70 +70,34 @@
 
 // ---------------------------------------------------------------------------
 
-static std::string audioFormatTypeString(audio_format_t value) {
-    std::string formatType;
-    if (FormatConverter::toString(value, formatType)) {
-        return formatType;
-    }
-    char rawbuffer[16];  // room for "%d"
-    snprintf(rawbuffer, sizeof(rawbuffer), "%d", value);
-    return rawbuffer;
-}
-
-static std::string audioSourceString(audio_source_t value) {
-    std::string source;
-    if (SourceTypeConverter::toString(value, source)) {
-        return source;
-    }
-    char rawbuffer[16];  // room for "%d"
-    snprintf(rawbuffer, sizeof(rawbuffer), "%d", value);
-    return rawbuffer;
-}
-
 void AudioRecord::MediaMetrics::gather(const AudioRecord *record)
 {
-    // key for media statistics is defined in the header
-    // attrs for media statistics
-    // NB: these are matched with public Java API constants defined
-    // in frameworks/base/media/java/android/media/AudioRecord.java
-    // These must be kept synchronized with the constants there.
-    static constexpr char kAudioRecordEncoding[] = "android.media.audiorecord.encoding";
-    static constexpr char kAudioRecordSource[] = "android.media.audiorecord.source";
-    static constexpr char kAudioRecordLatency[] = "android.media.audiorecord.latency";
-    static constexpr char kAudioRecordSampleRate[] = "android.media.audiorecord.samplerate";
-    static constexpr char kAudioRecordChannelCount[] = "android.media.audiorecord.channels";
-    static constexpr char kAudioRecordCreated[] = "android.media.audiorecord.createdMs";
-    static constexpr char kAudioRecordDuration[] = "android.media.audiorecord.durationMs";
-    static constexpr char kAudioRecordCount[] = "android.media.audiorecord.n";
-    static constexpr char kAudioRecordError[] = "android.media.audiorecord.errcode";
-    static constexpr char kAudioRecordErrorFunction[] = "android.media.audiorecord.errfunc";
+#define MM_PREFIX "android.media.audiorecord." // avoid cut-n-paste errors.
 
-    // constructor guarantees mAnalyticsItem is valid
+    // Java API 28 entries, do not change.
+    mAnalyticsItem->setCString(MM_PREFIX "encoding", toString(record->mFormat).c_str());
+    mAnalyticsItem->setCString(MM_PREFIX "source", toString(record->mAttributes.source).c_str());
+    mAnalyticsItem->setInt32(MM_PREFIX "latency", (int32_t)record->mLatency); // bad estimate.
+    mAnalyticsItem->setInt32(MM_PREFIX "samplerate", (int32_t)record->mSampleRate);
+    mAnalyticsItem->setInt32(MM_PREFIX "channels", (int32_t)record->mChannelCount);
 
-    mAnalyticsItem->setInt32(kAudioRecordLatency, record->mLatency);
-    mAnalyticsItem->setInt32(kAudioRecordSampleRate, record->mSampleRate);
-    mAnalyticsItem->setInt32(kAudioRecordChannelCount, record->mChannelCount);
-    mAnalyticsItem->setCString(kAudioRecordEncoding,
-                               audioFormatTypeString(record->mFormat).c_str());
-    mAnalyticsItem->setCString(kAudioRecordSource,
-                               audioSourceString(record->mAttributes.source).c_str());
+    // Non-API entries, these can change.
+    mAnalyticsItem->setInt32(MM_PREFIX "portId", (int32_t)record->mPortId);
+    mAnalyticsItem->setInt32(MM_PREFIX "frameCount", (int32_t)record->mFrameCount);
+    mAnalyticsItem->setCString(MM_PREFIX "attributes", toString(record->mAttributes).c_str());
+    mAnalyticsItem->setInt64(MM_PREFIX "channelMask", (int64_t)record->mChannelMask);
 
-    // log total duration recording, including anything currently running [and count].
-    nsecs_t active = 0;
+    // log total duration recording, including anything currently running.
+    int64_t activeNs = 0;
     if (mStartedNs != 0) {
-        active = systemTime() - mStartedNs;
+        activeNs = systemTime() - mStartedNs;
     }
-    mAnalyticsItem->setInt64(kAudioRecordDuration, (mDurationNs + active) / (1000 * 1000));
-    mAnalyticsItem->setInt32(kAudioRecordCount, mCount);
-
-    // XXX I don't know that this adds a lot of value, long term
-    if (mCreatedNs != 0) {
-        mAnalyticsItem->setInt64(kAudioRecordCreated, mCreatedNs / (1000 * 1000));
-    }
+    mAnalyticsItem->setDouble(MM_PREFIX "durationMs", (mDurationNs + activeNs) * 1e-6);
+    mAnalyticsItem->setInt64(MM_PREFIX "startCount", (int64_t)mCount);
 
     if (mLastError != NO_ERROR) {
-        mAnalyticsItem->setInt32(kAudioRecordError, mLastError);
-        mAnalyticsItem->setCString(kAudioRecordErrorFunction, mLastErrorFunc.c_str());
+        mAnalyticsItem->setInt32(MM_PREFIX "lastError.code", (int32_t)mLastError);
+        mAnalyticsItem->setCString(MM_PREFIX "lastError.at", mLastErrorFunc.c_str());
     }
 }
 
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 60e841c..e59f7e0 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -170,44 +170,8 @@
 
 // ---------------------------------------------------------------------------
 
-static std::string audioContentTypeString(audio_content_type_t value) {
-    std::string contentType;
-    if (AudioContentTypeConverter::toString(value, contentType)) {
-        return contentType;
-    }
-    char rawbuffer[16];  // room for "%d"
-    snprintf(rawbuffer, sizeof(rawbuffer), "%d", value);
-    return rawbuffer;
-}
-
-static std::string audioUsageString(audio_usage_t value) {
-    std::string usage;
-    if (UsageTypeConverter::toString(value, usage)) {
-        return usage;
-    }
-    char rawbuffer[16];  // room for "%d"
-    snprintf(rawbuffer, sizeof(rawbuffer), "%d", value);
-    return rawbuffer;
-}
-
 void AudioTrack::MediaMetrics::gather(const AudioTrack *track)
 {
-
-    // key for media statistics is defined in the header
-    // attrs for media statistics
-    // NB: these are matched with public Java API constants defined
-    // in frameworks/base/media/java/android/media/AudioTrack.java
-    // These must be kept synchronized with the constants there.
-    static constexpr char kAudioTrackStreamType[] = "android.media.audiotrack.streamtype";
-    static constexpr char kAudioTrackContentType[] = "android.media.audiotrack.type";
-    static constexpr char kAudioTrackUsage[] = "android.media.audiotrack.usage";
-    static constexpr char kAudioTrackSampleRate[] = "android.media.audiotrack.samplerate";
-    static constexpr char kAudioTrackChannelMask[] = "android.media.audiotrack.channelmask";
-
-    // NB: These are not yet exposed as public Java API constants.
-    static constexpr char kAudioTrackUnderrunFrames[] = "android.media.audiotrack.underrunframes";
-    static constexpr char kAudioTrackStartupGlitch[] = "android.media.audiotrack.glitch.startup";
-
     // only if we're in a good state...
     // XXX: shall we gather alternative info if failing?
     const status_t lstatus = track->initCheck();
@@ -216,28 +180,22 @@
         return;
     }
 
-    // constructor guarantees mAnalyticsItem is valid
+#define MM_PREFIX "android.media.audiotrack." // avoid cut-n-paste errors.
 
-    const int32_t underrunFrames = track->getUnderrunFrames();
-    if (underrunFrames != 0) {
-        mAnalyticsItem->setInt32(kAudioTrackUnderrunFrames, underrunFrames);
-    }
+    // Java API 28 entries, do not change.
+    mAnalyticsItem->setCString(MM_PREFIX "streamtype", toString(track->streamType()).c_str());
+    mAnalyticsItem->setCString(MM_PREFIX "type",
+            toString(track->mAttributes.content_type).c_str());
+    mAnalyticsItem->setCString(MM_PREFIX "usage", toString(track->mAttributes.usage).c_str());
 
-    if (track->mTimestampStartupGlitchReported) {
-        mAnalyticsItem->setInt32(kAudioTrackStartupGlitch, 1);
-    }
-
-    if (track->mStreamType != -1) {
-        // deprecated, but this will tell us who still uses it.
-        mAnalyticsItem->setInt32(kAudioTrackStreamType, track->mStreamType);
-    }
-    // XXX: consider including from mAttributes: source type
-    mAnalyticsItem->setCString(kAudioTrackContentType,
-                               audioContentTypeString(track->mAttributes.content_type).c_str());
-    mAnalyticsItem->setCString(kAudioTrackUsage,
-                               audioUsageString(track->mAttributes.usage).c_str());
-    mAnalyticsItem->setInt32(kAudioTrackSampleRate, track->mSampleRate);
-    mAnalyticsItem->setInt64(kAudioTrackChannelMask, track->mChannelMask);
+    // Non-API entries, these can change due to a Java string mistake.
+    mAnalyticsItem->setInt32(MM_PREFIX "sampleRate", (int32_t)track->mSampleRate);
+    mAnalyticsItem->setInt64(MM_PREFIX "channelMask", (int64_t)track->mChannelMask);
+    // Non-API entries, these can change.
+    mAnalyticsItem->setInt32(MM_PREFIX "portId", (int32_t)track->mPortId);
+    mAnalyticsItem->setCString(MM_PREFIX "encoding", toString(track->mFormat).c_str());
+    mAnalyticsItem->setInt32(MM_PREFIX "frameCount", (int32_t)track->mFrameCount);
+    mAnalyticsItem->setCString(MM_PREFIX "attributes", toString(track->mAttributes).c_str());
 }
 
 // hand the user a snapshot of the metrics.
diff --git a/media/libaudioclient/include/media/AudioMixer.h b/media/libaudioclient/include/media/AudioMixer.h
index 41b425f..783eef3 100644
--- a/media/libaudioclient/include/media/AudioMixer.h
+++ b/media/libaudioclient/include/media/AudioMixer.h
@@ -273,7 +273,7 @@
             mPostDownmixReformatBufferProvider.reset(nullptr);
             mDownmixerBufferProvider.reset(nullptr);
             mReformatBufferProvider.reset(nullptr);
-            mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
+            mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
             mAdjustChannelsBufferProvider.reset(nullptr);
         }
 
@@ -347,8 +347,12 @@
          * all pre-mixer track buffer conversions outside the AudioMixer class.
          *
          * 1) mInputBufferProvider: The AudioTrack buffer provider.
-         * 2) mAdjustChannelsBufferProvider: Expend or contracts data
-         * 3) mAdjustChannelsNonDestructiveBufferProvider: Non-destructively adjust sample data
+         * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
+         *    channel format to another. Expanded channels are filled with zeros and put at the end
+         *    of each audio frame. Contracted channels are copied to the end of the buffer.
+         * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data.
+         *    This is currently using at audio-haptic coupled playback to separate audio and haptic
+         *    data. Contracted channels could be written to given buffer.
          * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
          *    match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
          *    requires reformat. For example, it may convert floating point input to
@@ -360,9 +364,10 @@
          * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
          */
         AudioBufferProvider*     mInputBufferProvider;    // externally provided buffer provider.
-        // TODO: combine AdjustChannelsBufferProvider and AdjustChannelsNonDestructiveBufferProvider
+        // TODO: combine mAdjustChannelsBufferProvider and
+        // mContractChannelsNonDestructiveBufferProvider
         std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
-        std::unique_ptr<PassthruBufferProvider> mAdjustChannelsNonDestructiveBufferProvider;
+        std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider;
         std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
         std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
         std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 2c57db7..f7cc096 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -408,8 +408,8 @@
 void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive()
 {
     ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive");
-    if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
-        mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
+    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+        mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
         reconfigureBufferProviders();
     }
 }
@@ -426,13 +426,13 @@
                 ? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame(
                         mMixerChannelCount, mMixerFormat)
                 : NULL;
-        mAdjustChannelsNonDestructiveBufferProvider.reset(
-                new AdjustChannelsNonDestructiveBufferProvider(
+        mContractChannelsNonDestructiveBufferProvider.reset(
+                new AdjustChannelsBufferProvider(
                         mFormat,
                         mAdjustNonDestructiveInChannelCount,
                         mAdjustNonDestructiveOutChannelCount,
-                        mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
                         frames,
+                        mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
                         buffer));
         reconfigureBufferProviders();
     }
@@ -441,9 +441,9 @@
 
 void AudioMixer::Track::clearContractedBuffer()
 {
-    if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
-        static_cast<AdjustChannelsNonDestructiveBufferProvider*>(
-                mAdjustChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
+    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+        static_cast<AdjustChannelsBufferProvider*>(
+                mContractChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
     }
 }
 
@@ -455,9 +455,9 @@
         mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
         bufferProvider = mAdjustChannelsBufferProvider.get();
     }
-    if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
-        mAdjustChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
-        bufferProvider = mAdjustChannelsNonDestructiveBufferProvider.get();
+    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+        mContractChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
+        bufferProvider = mContractChannelsNonDestructiveBufferProvider.get();
     }
     if (mReformatBufferProvider.get() != nullptr) {
         mReformatBufferProvider->setBufferProvider(bufferProvider);
@@ -966,8 +966,8 @@
         track->mDownmixerBufferProvider->reset();
     } else if (track->mReformatBufferProvider.get() != nullptr) {
         track->mReformatBufferProvider->reset();
-    } else if (track->mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
-        track->mAdjustChannelsNonDestructiveBufferProvider->reset();
+    } else if (track->mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+        track->mContractChannelsNonDestructiveBufferProvider->reset();
     } else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
         track->mAdjustChannelsBufferProvider->reset();
     }
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index b764ccb..21d25e1 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -627,79 +627,68 @@
     }
 }
 
-AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(audio_format_t format,
-        size_t inChannelCount, size_t outChannelCount, size_t frameCount) :
+AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
+        audio_format_t format, size_t inChannelCount, size_t outChannelCount,
+        size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) :
         CopyBufferProvider(
                 audio_bytes_per_frame(inChannelCount, format),
-                audio_bytes_per_frame(outChannelCount, format),
+                audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
                 frameCount),
         mFormat(format),
         mInChannelCount(inChannelCount),
         mOutChannelCount(outChannelCount),
-        mSampleSizeInBytes(audio_bytes_per_sample(format))
-{
-    ALOGV("AdjustBufferProvider(%p)(%#x, %zu, %zu, %zu)",
-            this, format, inChannelCount, outChannelCount, frameCount);
-}
-
-void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
-{
-    adjust_channels(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
-            frames * mInChannelCount * mSampleSizeInBytes);
-}
-
-AdjustChannelsNonDestructiveBufferProvider::AdjustChannelsNonDestructiveBufferProvider(
-        audio_format_t format, size_t inChannelCount, size_t outChannelCount,
-        audio_format_t contractedFormat, size_t contractedFrameCount, void* contractedBuffer) :
-        CopyBufferProvider(
-                audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
-                audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
-                contractedFrameCount),
-        mFormat(format),
-        mInChannelCount(inChannelCount),
-        mOutChannelCount(outChannelCount),
         mSampleSizeInBytes(audio_bytes_per_sample(format)),
+        mFrameCount(frameCount),
         mContractedChannelCount(inChannelCount - outChannelCount),
         mContractedFormat(contractedFormat),
-        mContractedFrameCount(contractedFrameCount),
         mContractedBuffer(contractedBuffer),
         mContractedWrittenFrames(0)
 {
-    ALOGV("AdjustChannelsNonDestructiveBufferProvider(%p)(%#x, %zu, %zu, %#x, %p)",
-            this, format, inChannelCount, outChannelCount, contractedFormat, contractedBuffer);
+    ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format,
+            inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer);
     if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
         mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
     }
 }
 
-status_t AdjustChannelsNonDestructiveBufferProvider::getNextBuffer(
-        AudioBufferProvider::Buffer* pBuffer)
+status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer* pBuffer)
 {
-    const size_t outFramesLeft = mContractedFrameCount - mContractedWrittenFrames;
-    if (outFramesLeft < pBuffer->frameCount) {
-        // Restrict the frame count so that we don't write over the size of the output buffer.
-        pBuffer->frameCount = outFramesLeft;
+    if (mContractedBuffer != nullptr) {
+        // Restrict frame count only when it is needed to save contracted frames.
+        const size_t outFramesLeft = mFrameCount - mContractedWrittenFrames;
+        if (outFramesLeft < pBuffer->frameCount) {
+            // Restrict the frame count so that we don't write over the size of the output buffer.
+            pBuffer->frameCount = outFramesLeft;
+        }
     }
     return CopyBufferProvider::getNextBuffer(pBuffer);
 }
 
-void AdjustChannelsNonDestructiveBufferProvider::copyFrames(
-        void *dst, const void *src, size_t frames)
+void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
 {
-    adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
-            frames * mInChannelCount * mSampleSizeInBytes);
-    if (mContractedFormat != AUDIO_FORMAT_INVALID && mContractedBuffer != NULL
-            && mInChannelCount > mOutChannelCount) {
-        const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
-        memcpy_by_audio_format(
-                (uint8_t*)mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
-                mContractedFormat, (uint8_t*)dst + contractedIdx, mFormat,
-                mContractedChannelCount * frames);
-        mContractedWrittenFrames += frames;
+    if (mInChannelCount > mOutChannelCount) {
+        // For case multi to mono, adjust_channels has special logic that will mix first two input
+        // channels into a single output channel. In that case, use adjust_channels_non_destructive
+        // to keep only one channel data even when contracting to mono.
+        adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
+                mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
+        if (mContractedFormat != AUDIO_FORMAT_INVALID
+            && mContractedBuffer != nullptr) {
+            const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
+            memcpy_by_audio_format(
+                    (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
+                    mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat,
+                    mContractedChannelCount * frames);
+            mContractedWrittenFrames += frames;
+        }
+    } else {
+        // Prefer expanding data from the end of each audio frame.
+        adjust_channels(src, mInChannelCount, dst, mOutChannelCount,
+                mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
     }
 }
 
-void AdjustChannelsNonDestructiveBufferProvider::reset()
+void AdjustChannelsBufferProvider::reset()
 {
     mContractedWrittenFrames = 0;
     CopyBufferProvider::reset();
diff --git a/media/libeffects/downmix/tests/Android.bp b/media/libeffects/downmix/tests/Android.bp
index e2e7dbd..63afc54 100644
--- a/media/libeffects/downmix/tests/Android.bp
+++ b/media/libeffects/downmix/tests/Android.bp
@@ -24,7 +24,6 @@
     ],
 
     cflags: [
-        "-v",
         "-Werror",
         "-Wextra",
     ],
diff --git a/media/libmedia/include/media/BufferProviders.h b/media/libmedia/include/media/BufferProviders.h
index ea41527..b038854 100644
--- a/media/libmedia/include/media/BufferProviders.h
+++ b/media/libmedia/include/media/BufferProviders.h
@@ -218,33 +218,21 @@
     bool                 mAudioPlaybackRateValid; // flag for current parameters validity
 };
 
-// AdjustBufferProvider derives from CopyBufferProvider to adjust sample data.
+// AdjustChannelsBufferProvider derives from CopyBufferProvider to adjust sample data.
 // Expands or contracts sample data from one interleaved channel format to another.
-// Expanded channels are filled with zeros and put at the end of each audio frame.
-// Contracted channels are omitted from the end of each audio frame.
+// Extra expanded channels are filled with zeros and put at the end of each audio frame.
+// Contracted channels are copied to the end of the output buffer(storage should be
+// allocated appropriately).
+// Contracted channels could be written to output buffer.
 class AdjustChannelsBufferProvider : public CopyBufferProvider {
 public:
     AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
-            size_t outChannelCount, size_t frameCount);
-    //Overrides
-    void copyFrames(void *dst, const void *src, size_t frames) override;
-
-protected:
-    const audio_format_t mFormat;
-    const size_t         mInChannelCount;
-    const size_t         mOutChannelCount;
-    const size_t         mSampleSizeInBytes;
-};
-
-// AdjustChannelsNonDestructiveBufferProvider derives from CopyBufferProvider to adjust sample data.
-// Expands or contracts sample data from one interleaved channel format to another.
-// Extra expanded channels are interleaved in from the end of the input buffer.
-// Contracted channels are copied to the end of the output buffer.
-// Contracted channels could be written to output buffer.
-class AdjustChannelsNonDestructiveBufferProvider : public CopyBufferProvider {
-public:
-    AdjustChannelsNonDestructiveBufferProvider(audio_format_t format, size_t inChannelCount,
-            size_t outChannelCount, audio_format_t contractedFormat, size_t contractedFrameCount,
+            size_t outChannelCount, size_t frameCount) : AdjustChannelsBufferProvider(
+                    format, inChannelCount, outChannelCount,
+                    frameCount, AUDIO_FORMAT_INVALID, nullptr) { }
+    // Contracted data is converted to contractedFormat and put into contractedBuffer.
+    AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
+            size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat,
             void* contractedBuffer);
     //Overrides
     status_t getNextBuffer(Buffer* pBuffer) override;
@@ -258,9 +246,9 @@
     const size_t         mInChannelCount;
     const size_t         mOutChannelCount;
     const size_t         mSampleSizeInBytes;
+    const size_t         mFrameCount;
     const size_t         mContractedChannelCount;
     const audio_format_t mContractedFormat;
-    const size_t         mContractedFrameCount;
     void                *mContractedBuffer;
     size_t               mContractedWrittenFrames;
     size_t               mContractedFrameSize;
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
index 2ea5fcd..9eba7e9 100644
--- a/media/libstagefright/AACWriter.cpp
+++ b/media/libstagefright/AACWriter.cpp
@@ -85,7 +85,7 @@
     CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC));
     CHECK(meta->findInt32(kKeyChannelCount, &mChannelCount));
     CHECK(meta->findInt32(kKeySampleRate, &mSampleRate));
-    CHECK(mChannelCount >= 1 && mChannelCount <= 2);
+    CHECK(mChannelCount >= 1 && mChannelCount <= 7);
 
     // Optionally, we want to check whether AACProfile is also set.
     if (meta->findInt32(kKeyAACProfile, &mAACProfile)) {
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 2bd7288..d8b825d 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -199,7 +199,6 @@
         "libhidlallocatorutils",
         "libhidlbase",
         "libhidlmemory",
-        "libziparchive",
         "android.hidl.allocator@1.0",
         "android.hardware.cas.native@1.0",
         "android.hardware.media.omx@1.0",
diff --git a/media/libstagefright/HevcUtils.cpp b/media/libstagefright/HevcUtils.cpp
index f152a38..0c38f2e 100644
--- a/media/libstagefright/HevcUtils.cpp
+++ b/media/libstagefright/HevcUtils.cpp
@@ -457,8 +457,8 @@
         if (numNalus == 0) {
             continue;
         }
-        // array_completeness set to 0.
-        header[0] = type;
+        // array_completeness set to 1.
+        header[0] = type | 0x80;
         header[1] = (numNalus >> 8) & 0xff;
         header[2] = numNalus & 0xff;
         header += 3;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6259b15..f6ed0f1 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3128,8 +3128,8 @@
         if (!mIsHeic) {
             if (mStszTableEntries->count() == 0) {
                 mFirstSampleTimeRealUs = systemTime() / 1000;
+                mOwner->setStartTimestampUs(timestampUs);
                 mStartTimestampUs = timestampUs;
-                mOwner->setStartTimestampUs(mStartTimestampUs);
                 previousPausedDurationUs = mStartTimestampUs;
             }
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 9c58e05..d4e4000 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1973,10 +1973,11 @@
 
                 case kWhatComponentConfigured:
                 {
-                    if (mState == UNINITIALIZED || mState == INITIALIZED) {
-                        // In case a kWhatError message came in and replied with error,
+                    if (mState == RELEASING || mState == UNINITIALIZED || mState == INITIALIZED) {
+                        // In case a kWhatError or kWhatRelease message came in and replied,
                         // we log a warning and ignore.
-                        ALOGW("configure interrupted by error, current state %d", mState);
+                        ALOGW("configure interrupted by error or release, current state %d",
+                              mState);
                         break;
                     }
                     CHECK_EQ(mState, CONFIGURING);
@@ -2067,6 +2068,13 @@
 
                 case kWhatStartCompleted:
                 {
+                    if (mState == RELEASING || mState == UNINITIALIZED) {
+                        // In case a kWhatRelease message came in and replied,
+                        // we log a warning and ignore.
+                        ALOGW("start interrupted by release, current state %d", mState);
+                        break;
+                    }
+
                     CHECK_EQ(mState, STARTING);
                     if (mIsVideo) {
                         addResource(
@@ -2632,11 +2640,12 @@
                 break;
             }
 
-            // If we're flushing, or we're stopping but received a release
-            // request, post the reply for the pending call first, and consider
-            // it done. The reply token will be replaced after this, and we'll
-            // no longer be able to reply.
-            if (mState == FLUSHING || mState == STOPPING) {
+            // If we're flushing, stopping, configuring or starting  but
+            // received a release request, post the reply for the pending call
+            // first, and consider it done. The reply token will be replaced
+            // after this, and we'll no longer be able to reply.
+            if (mState == FLUSHING || mState == STOPPING
+                    || mState == CONFIGURING || mState == STARTING) {
                 (new AMessage)->postReply(mReplyID);
             }
 
diff --git a/media/libstagefright/OggWriter.cpp b/media/libstagefright/OggWriter.cpp
index 5c13983..cb87b55 100644
--- a/media/libstagefright/OggWriter.cpp
+++ b/media/libstagefright/OggWriter.cpp
@@ -295,6 +295,18 @@
                   mEstimatedSizeBytes, mMaxFileSizeLimitBytes);
             break;
         }
+
+        int32_t isCodecSpecific;
+        if ((buffer->meta_data().findInt32(kKeyIsCodecConfig, &isCodecSpecific)
+             && isCodecSpecific)
+            || IsOpusHeader((uint8_t*)buffer->data() + buffer->range_offset(),
+                         buffer->range_length())) {
+            ALOGV("Drop codec specific info buffer");
+            buffer->release();
+            buffer = nullptr;
+            continue;
+        }
+
         int64_t timestampUs;
         CHECK(buffer->meta_data().findInt64(kKeyTime, &timestampUs));
         if (timestampUs > mEstimatedDurationUs) {
diff --git a/media/libstagefright/foundation/OpusHeader.cpp b/media/libstagefright/foundation/OpusHeader.cpp
index 9faede1..acb9ccf 100644
--- a/media/libstagefright/foundation/OpusHeader.cpp
+++ b/media/libstagefright/foundation/OpusHeader.cpp
@@ -15,9 +15,9 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "SoftOpus"
-#include <algorithm>
+#define LOG_TAG "OpusHeader"
 #include <cstring>
+#include <inttypes.h>
 #include <stdint.h>
 
 #include <log/log.h>
@@ -91,6 +91,9 @@
 
 // Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header
 bool ParseOpusHeader(const uint8_t* data, size_t data_size, OpusHeader* header) {
+    if (data == NULL) {
+        return false;
+    }
     if (data_size < kOpusHeaderSize) {
         ALOGV("Header size is too small.");
         return false;
@@ -183,53 +186,88 @@
         ALOGD("Buffer not large enough to hold unified OPUS CSD");
         return -1;
     }
+    int headerLen = 0;
 
-    int headerLen = WriteOpusHeader(header, inputSampleRate, output,
+    // Add opus header
+    /*
+      Following is the CSD syntax for signalling OpusHeader
+      (http://wiki.xiph.org/OggOpus#ID_Header)
+
+      Marker (8 bytes) | Length (8 bytes) | OpusHeader
+
+      Markers supported:
+      AOPUS_CSD_OPUS_HEADER_MARKER - Signals Opus Header
+
+      Length should be a value within AOPUS_OPUSHEAD_MINSIZE and AOPUS_OPUSHEAD_MAXSIZE.
+    */
+
+    memcpy(output + headerLen, AOPUS_CSD_OPUS_HEADER_MARKER, AOPUS_MARKER_SIZE);
+    headerLen += AOPUS_MARKER_SIZE;
+
+    // Place holder for opusHeader Size
+    headerLen += AOPUS_LENGTH_SIZE;
+
+    int headerSize = WriteOpusHeader(header, inputSampleRate, output + headerLen,
         outputSize);
-    if (headerLen < 0) {
-        ALOGD("WriteOpusHeader failed");
+    if (headerSize < 0) {
+        ALOGD("%s: WriteOpusHeader failed", __func__);
         return -1;
     }
-    if (headerLen >= (outputSize - 2 * AOPUS_TOTAL_CSD_SIZE)) {
-        ALOGD("Buffer not large enough to hold codec delay and seek pre roll");
-        return -1;
-    }
+    headerLen += headerSize;
 
-    uint64_t length = AOPUS_LENGTH;
+    // Update opus headerSize after AOPUS_CSD_OPUS_HEADER_MARKER
+    uint64_t length = headerSize;
+    memcpy(output + AOPUS_MARKER_SIZE, &length, AOPUS_LENGTH_SIZE);
 
     /*
       Following is the CSD syntax for signalling codec delay and
       seek pre-roll which is to be appended after OpusHeader
 
-      Marker (8 bytes) | Length (8 bytes) | Samples (8 bytes)
+      Marker (8 bytes) | Length (8 bytes) | Samples in ns (8 bytes)
 
       Markers supported:
-      AOPUSDLY - Signals Codec Delay
-      AOPUSPRL - Signals seek pre roll
+      AOPUS_CSD_CODEC_DELAY_MARKER - codec delay as samples in ns, represented in 8 bytes
+      AOPUS_CSD_SEEK_PREROLL_MARKER - preroll adjustment as samples in ns, represented in 8 bytes
 
-      Length should be 8.
     */
-
+    length = sizeof(codecDelay);
+    if (headerLen > (outputSize - AOPUS_MARKER_SIZE - AOPUS_LENGTH_SIZE - length)) {
+        ALOGD("Buffer not large enough to hold codec delay");
+        return -1;
+    }
     // Add codec delay
     memcpy(output + headerLen, AOPUS_CSD_CODEC_DELAY_MARKER, AOPUS_MARKER_SIZE);
     headerLen += AOPUS_MARKER_SIZE;
     memcpy(output + headerLen, &length, AOPUS_LENGTH_SIZE);
     headerLen += AOPUS_LENGTH_SIZE;
-    memcpy(output + headerLen, &codecDelay, AOPUS_CSD_SIZE);
-    headerLen += AOPUS_CSD_SIZE;
+    memcpy(output + headerLen, &codecDelay, length);
+    headerLen += length;
 
+    length = sizeof(seekPreRoll);
+    if (headerLen > (outputSize - AOPUS_MARKER_SIZE - AOPUS_LENGTH_SIZE - length)) {
+        ALOGD("Buffer not large enough to hold seek pre roll");
+        return -1;
+    }
     // Add skip pre roll
     memcpy(output + headerLen, AOPUS_CSD_SEEK_PREROLL_MARKER, AOPUS_MARKER_SIZE);
     headerLen += AOPUS_MARKER_SIZE;
     memcpy(output + headerLen, &length, AOPUS_LENGTH_SIZE);
     headerLen += AOPUS_LENGTH_SIZE;
-    memcpy(output + headerLen, &seekPreRoll, AOPUS_CSD_SIZE);
-    headerLen += AOPUS_CSD_SIZE;
+    memcpy(output + headerLen, &seekPreRoll, length);
+    headerLen += length;
 
     return headerLen;
 }
 
-void GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
+bool IsOpusHeader(const uint8_t *data, size_t data_size) {
+    if (data_size < AOPUS_MARKER_SIZE) {
+        return false;
+    }
+
+    return !memcmp(data, AOPUS_CSD_OPUS_HEADER_MARKER, AOPUS_MARKER_SIZE);
+}
+
+bool GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
                           void **opusHeadBuf, size_t *opusHeadSize,
                           void **codecDelayBuf, size_t *codecDelaySize,
                           void **seekPreRollBuf, size_t *seekPreRollSize) {
@@ -237,26 +275,77 @@
     *codecDelaySize = 0;
     *seekPreRollBuf = NULL;
     *seekPreRollSize = 0;
-    *opusHeadBuf = (void *)data;
-    *opusHeadSize = data_size;
-    if (data_size >= AOPUS_UNIFIED_CSD_MINSIZE) {
+    *opusHeadBuf = NULL;
+    *opusHeadSize = 0;
+
+    // AOPUS_MARKER_SIZE is 8 "OpusHead" is of size 8
+    if (data_size < 8)
+        return false;
+
+    // Check if the CSD is in legacy format
+    if (!memcmp("OpusHead", data, 8)) {
+        if (data_size < AOPUS_OPUSHEAD_MINSIZE || data_size > AOPUS_OPUSHEAD_MAXSIZE) {
+            ALOGD("Unexpected size for opusHeadSize %zu", data_size);
+            return false;
+        }
+        *opusHeadBuf = (void *)data;
+        *opusHeadSize = data_size;
+        return true;
+    } else if (memcmp(AOPUS_CSD_MARKER_PREFIX, data, AOPUS_CSD_MARKER_PREFIX_SIZE) == 0) {
         size_t i = 0;
-        while (i < data_size - AOPUS_TOTAL_CSD_SIZE) {
+        bool found = false;
+        while (i <= data_size - AOPUS_MARKER_SIZE - AOPUS_LENGTH_SIZE) {
             uint8_t *csdBuf = (uint8_t *)data + i;
-            if (!memcmp(csdBuf, AOPUS_CSD_CODEC_DELAY_MARKER, AOPUS_MARKER_SIZE)) {
-                *opusHeadSize = std::min(*opusHeadSize, i);
+            if (!memcmp(csdBuf, AOPUS_CSD_OPUS_HEADER_MARKER, AOPUS_MARKER_SIZE)) {
+                uint64_t value;
+                memcpy(&value, csdBuf + AOPUS_MARKER_SIZE, sizeof(value));
+                if (value < AOPUS_OPUSHEAD_MINSIZE || value > AOPUS_OPUSHEAD_MAXSIZE) {
+                    ALOGD("Unexpected size for opusHeadSize %" PRIu64, value);
+                    return false;
+                }
+                i += AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE + value;
+                if (i > data_size) {
+                    ALOGD("Marker signals a header that is larger than input");
+                    return false;
+                }
+                *opusHeadBuf = csdBuf + AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE;
+                *opusHeadSize = value;
+                found = true;
+            } else if (!memcmp(csdBuf, AOPUS_CSD_CODEC_DELAY_MARKER, AOPUS_MARKER_SIZE)) {
+                uint64_t value;
+                memcpy(&value, csdBuf + AOPUS_MARKER_SIZE, sizeof(value));
+                if (value != sizeof(uint64_t)) {
+                    ALOGD("Unexpected size for codecDelay %" PRIu64, value);
+                    return false;
+                }
+                i += AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE + value;
+                if (i > data_size) {
+                    ALOGD("Marker signals a header that is larger than input");
+                    return false;
+                }
                 *codecDelayBuf = csdBuf + AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE;
-                *codecDelaySize = AOPUS_CSD_SIZE;
-                i += AOPUS_TOTAL_CSD_SIZE;
+                *codecDelaySize = value;
             } else if (!memcmp(csdBuf, AOPUS_CSD_SEEK_PREROLL_MARKER, AOPUS_MARKER_SIZE)) {
-                *opusHeadSize = std::min(*opusHeadSize, i);
+                uint64_t value;
+                memcpy(&value, csdBuf + AOPUS_MARKER_SIZE, sizeof(value));
+                if (value != sizeof(uint64_t)) {
+                    ALOGD("Unexpected size for seekPreRollSize %" PRIu64, value);
+                    return false;
+                }
+                i += AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE + value;
+                if (i > data_size) {
+                    ALOGD("Marker signals a header that is larger than input");
+                    return false;
+                }
                 *seekPreRollBuf = csdBuf + AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE;
-                *seekPreRollSize = AOPUS_CSD_SIZE;
-                i += AOPUS_TOTAL_CSD_SIZE;
+                *seekPreRollSize = value;
             } else {
                 i++;
             }
         }
+        return found;
+    } else {
+        return false;  // it isn't in either format
     }
 }
 
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h b/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
index 9bffccb..29037af 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
@@ -25,22 +25,37 @@
 namespace android {
 
 /* Constants used for delimiting Opus CSD */
-#define AOPUS_CSD_CODEC_DELAY_MARKER "AOPUSDLY"
-#define AOPUS_CSD_SEEK_PREROLL_MARKER "AOPUSPRL"
-#define AOPUS_CSD_SIZE 8
-#define AOPUS_LENGTH 8
+#define AOPUS_CSD_MARKER_PREFIX "AOPUS"
+#define AOPUS_CSD_MARKER_PREFIX_SIZE (sizeof(AOPUS_CSD_MARKER_PREFIX) - 1)
+#define AOPUS_CSD_OPUS_HEADER_MARKER AOPUS_CSD_MARKER_PREFIX "HDR"
+#define AOPUS_CSD_CODEC_DELAY_MARKER AOPUS_CSD_MARKER_PREFIX "DLY"
+#define AOPUS_CSD_SEEK_PREROLL_MARKER AOPUS_CSD_MARKER_PREFIX "PRL"
 #define AOPUS_MARKER_SIZE 8
-#define AOPUS_LENGTH_SIZE 8
-#define AOPUS_TOTAL_CSD_SIZE \
-    ((AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + (AOPUS_CSD_SIZE))
-#define AOPUS_CSD0_MINSIZE 19
-#define AOPUS_UNIFIED_CSD_MINSIZE \
-    ((AOPUS_CSD0_MINSIZE) + 2 * (AOPUS_TOTAL_CSD_SIZE))
+#define AOPUS_LENGTH_SIZE sizeof(uint64_t)
+#define AOPUS_CSD_CODEC_DELAY_SIZE \
+     (AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + sizeof(uint64_t)
+#define AOPUS_CSD_SEEK_PREROLL_SIZE \
+     (AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + sizeof(uint64_t)
 
-/* CSD0 at max can be 22 bytes + max number of channels (255) */
-#define AOPUS_CSD0_MAXSIZE 277
+/* OpusHead csd minimum size is 19 */
+#define AOPUS_OPUSHEAD_MINSIZE 19
+#define AOPUS_CSD_OPUSHEAD_MINSIZE \
+    (AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + (AOPUS_OPUSHEAD_MINSIZE)
+
+#define AOPUS_UNIFIED_CSD_MINSIZE \
+    ((AOPUS_CSD_OPUSHEAD_MINSIZE) + \
+     (AOPUS_CSD_CODEC_DELAY_SIZE) + \
+     (AOPUS_CSD_SEEK_PREROLL_SIZE))
+
+/* OpusHead csd at max can be AOPUS_CSD_OPUSHEAD_MINSIZE + 2 + max number of channels (255) */
+#define AOPUS_OPUSHEAD_MAXSIZE ((AOPUS_OPUSHEAD_MINSIZE) + 2 + 255)
+#define AOPUS_CSD_OPUSHEAD_MAXSIZE \
+    (AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + (AOPUS_OPUSHEAD_MAXSIZE)
+
 #define AOPUS_UNIFIED_CSD_MAXSIZE \
-    ((AOPUS_CSD0_MAXSIZE) + 2 * (AOPUS_TOTAL_CSD_SIZE))
+    ((AOPUS_CSD_OPUSHEAD_MAXSIZE) + \
+     (AOPUS_CSD_CODEC_DELAY_SIZE) + \
+     (AOPUS_CSD_SEEK_PREROLL_SIZE))
 
 struct OpusHeader {
     int channels;
@@ -54,13 +69,14 @@
 
 bool ParseOpusHeader(const uint8_t* data, size_t data_size, OpusHeader* header);
 int WriteOpusHeader(const OpusHeader &header, int input_sample_rate, uint8_t* output, size_t output_size);
-void GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
+bool GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
                           void **opusHeadBuf, size_t *opusHeadSize,
                           void **codecDelayBuf, size_t *codecDelaySize,
                           void **seekPreRollBuf, size_t *seekPreRollSize);
 int WriteOpusHeaders(const OpusHeader &header, int inputSampleRate,
                      uint8_t* output, size_t outputSize, uint64_t codecDelay,
                      uint64_t seekPreRoll);
+bool IsOpusHeader(const uint8_t *data, size_t data_size);
 }  // namespace android
 
 #endif  // OPUS_HEADER_H_
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 91b7587..40980a6 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -32,6 +32,7 @@
     libbinder \
     libaudioclient \
     libmedialogservice \
+    libmediametrics \
     libmediautils \
     libnbaio \
     libnblog \
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8f181a4..468676a 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -488,6 +488,8 @@
         sp<IBinder> binder = IInterface::asBinder(mPowerManager);
         binder->unlinkToDeath(mDeathRecipient);
     }
+
+    sendStatistics(true /* force */);
 }
 
 status_t AudioFlinger::ThreadBase::readyToRun()
@@ -571,6 +573,15 @@
 // sendIoConfigEvent_l() must be called with ThreadBase::mLock held
 void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event, pid_t pid)
 {
+    // The audio statistics history is exponentially weighted to forget events
+    // about five or more seconds in the past.  In order to have
+    // crisper statistics for mediametrics, we reset the statistics on
+    // an IoConfigEvent, to reflect different properties for a new device.
+    mIoJitterMs.reset();
+    mLatencyMs.reset();
+    mProcessTimeMs.reset();
+    mTimestampVerifier.discontinuity();
+
     sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, pid);
     sendConfigEvent_l(configEvent);
 }
@@ -1651,6 +1662,65 @@
     mWaitWorkCV.broadcast();
 }
 
+// Call only from threadLoop() or when it is idle.
+// Do not call from high performance code as this may do binder rpc to the MediaMetrics service.
+void AudioFlinger::ThreadBase::sendStatistics(bool force)
+{
+    // Do not log if we have no stats.
+    // We choose the timestamp verifier because it is the most likely item to be present.
+    const int64_t nstats = mTimestampVerifier.getN() - mLastRecordedTimestampVerifierN;
+    if (nstats == 0) {
+        return;
+    }
+
+    // Don't log more frequently than once per 12 hours.
+    // We use BOOTTIME to include suspend time.
+    const int64_t timeNs = systemTime(SYSTEM_TIME_BOOTTIME);
+    const int64_t sinceNs = timeNs - mLastRecordedTimeNs; // ok if mLastRecordedTimeNs = 0
+    if (!force && sinceNs <= 12 * NANOS_PER_HOUR) {
+        return;
+    }
+
+    mLastRecordedTimestampVerifierN = mTimestampVerifier.getN();
+    mLastRecordedTimeNs = timeNs;
+
+    std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("audiothread"));
+
+#define MM_PREFIX "android.media.audiothread." // avoid cut-n-paste errors.
+
+    // thread configuration
+    item->setInt32(MM_PREFIX "id", (int32_t)mId); // IO handle
+    // item->setInt32(MM_PREFIX "portId", (int32_t)mPortId);
+    item->setCString(MM_PREFIX "type", threadTypeToString(mType));
+    item->setInt32(MM_PREFIX "sampleRate", (int32_t)mSampleRate);
+    item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask);
+    item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
+    item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
+    item->setCString(MM_PREFIX "outDevice", toString(mOutDevice).c_str());
+    item->setCString(MM_PREFIX "inDevice", toString(mInDevice).c_str());
+
+    // thread statistics
+    if (mIoJitterMs.getN() > 0) {
+        item->setDouble(MM_PREFIX "ioJitterMs.mean", mIoJitterMs.getMean());
+        item->setDouble(MM_PREFIX "ioJitterMs.std", mIoJitterMs.getStdDev());
+    }
+    if (mProcessTimeMs.getN() > 0) {
+        item->setDouble(MM_PREFIX "processTimeMs.mean", mProcessTimeMs.getMean());
+        item->setDouble(MM_PREFIX "processTimeMs.std", mProcessTimeMs.getStdDev());
+    }
+    const auto tsjitter = mTimestampVerifier.getJitterMs();
+    if (tsjitter.getN() > 0) {
+        item->setDouble(MM_PREFIX "timestampJitterMs.mean", tsjitter.getMean());
+        item->setDouble(MM_PREFIX "timestampJitterMs.std", tsjitter.getStdDev());
+    }
+    if (mLatencyMs.getN() > 0) {
+        item->setDouble(MM_PREFIX "latencyMs.mean", mLatencyMs.getMean());
+        item->setDouble(MM_PREFIX "latencyMs.std", mLatencyMs.getStdDev());
+    }
+
+    item->selfrecord();
+}
+
 // ----------------------------------------------------------------------------
 //      Playback
 // ----------------------------------------------------------------------------
@@ -3447,6 +3517,7 @@
                         LOG_AUDIO_STATE();
                     }
                     mStandby = true;
+                    sendStatistics(false /* force */);
                 }
 
                 if (mActiveTracks.isEmpty() && mConfigEvents.isEmpty()) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 1afea08..97aa9f0 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -399,6 +399,9 @@
 
     virtual     void                dump(int fd, const Vector<String16>& args) = 0;
 
+                // deliver stats to mediametrics.
+                void                sendStatistics(bool force);
+
     mutable     Mutex                   mLock;
 
 protected:
@@ -522,6 +525,10 @@
                 audio_utils::Statistics<double> mProcessTimeMs{0.995 /* alpha */};
                 audio_utils::Statistics<double> mLatencyMs{0.995 /* alpha */};
 
+                // Save the last count when we delivered statistics to mediametrics.
+                int64_t                 mLastRecordedTimestampVerifierN = 0;
+                int64_t                 mLastRecordedTimeNs = 0;  // BOOTTIME to include suspend.
+
                 bool                    mIsMsdDevice = false;
                 // A condition that must be evaluated by the thread loop has changed and
                 // we must not wait for async write callback in the thread loop before evaluating it
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index e6ede07..d0775ad 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -17,3 +17,31 @@
     host_supported: true,
     export_include_dirs: ["include"],
 }
+
+cc_library_static {
+    name: "libaudiopolicyengine_common",
+    srcs: [
+        "src/EngineBase.cpp",
+        "src/ProductStrategy.cpp",
+        "src/VolumeCurve.cpp",
+        "src/VolumeGroup.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    header_libs: [
+        "libbase_headers",
+        "libaudiopolicycommon",
+        "libaudiopolicyengine_common_headers",
+        "libaudiopolicyengine_interface_headers",
+    ],
+    export_header_lib_headers: [
+        "libaudiopolicyengine_common_headers",
+    ],
+    static_libs: [
+        "libaudiopolicycomponents",
+        "libaudiopolicyengine_config",
+    ],
+}
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
new file mode 100644
index 0000000..6e72f2a
--- /dev/null
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -0,0 +1,31 @@
+cc_library_static {
+    name: "libaudiopolicyengine_config",
+    export_include_dirs: ["include"],
+    include_dirs: [
+        "external/libxml2/include",
+        "external/icu/icu4c/source/common",
+    ],
+    srcs: [
+        "src/EngineConfig.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "libmedia_helper",
+        "libandroidicu",
+        "libxml2",
+        "libutils",
+        "liblog",
+        "libcutils",
+    ],
+    static_libs: [
+        "libaudiopolicycomponents",
+    ],
+    header_libs: [
+        "libaudio_system_headers",
+        "libaudiopolicycommon",
+    ],
+}
diff --git a/services/audiopolicy/engine/config/Android.mk b/services/audiopolicy/engine/config/Android.mk
deleted file mode 100644
index 0b292a5..0000000
--- a/services/audiopolicy/engine/config/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-##################################################################
-# Component build
-##################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_EXPORT_C_INCLUDE_DIRS :=  $(LOCAL_PATH)/include
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_EXPORT_C_INCLUDE_DIRS) \
-    external/libxml2/include \
-    external/icu/icu4c/source/common
-
-LOCAL_SRC_FILES := \
-    src/EngineConfig.cpp
-
-LOCAL_CFLAGS += -Wall -Werror -Wextra
-
-LOCAL_SHARED_LIBRARIES := \
-    libmedia_helper \
-    libandroidicu \
-    libxml2 \
-    libutils \
-    liblog \
-    libcutils
-
-LOCAL_STATIC_LIBRARIES := \
-    libaudiopolicycomponents
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_MODULE := libaudiopolicyengineconfig
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_HEADER_LIBRARIES := \
-    libaudio_system_headers \
-    libaudiopolicycommon
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index 4eff6e6..84a4422 100644
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -12,10 +12,6 @@
     src/EngineInstance.cpp \
     src/Stream.cpp \
     src/InputSource.cpp \
-    ../engine/common/src/VolumeCurve.cpp \
-    ../engine/common/src/VolumeGroup.cpp \
-    ../engine/common/src/ProductStrategy.cpp \
-    ../engine/common/src/EngineBase.cpp
 
 audio_policy_engine_includes_common := \
     frameworks/av/services/audiopolicy/engineconfigurable/include \
@@ -37,7 +33,6 @@
 
 LOCAL_HEADER_LIBRARIES := \
     libaudiopolicycommon \
-    libaudiopolicyengine_common_headers \
     libaudiopolicyengine_interface_headers
 
 LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
@@ -47,13 +42,15 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libaudiopolicypfwwrapper \
-    libaudiopolicycomponents
+    libaudiopolicycomponents \
+    libaudiopolicyengine_common \
+    libaudiopolicyengine_config \
 
 LOCAL_SHARED_LIBRARIES := \
-    libaudiopolicyengineconfig \
     liblog \
     libutils \
     liblog \
+    libcutils \
     libaudioutils \
     libparameter \
     libmedia_helper \
diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp
new file mode 100644
index 0000000..7b42c6a
--- /dev/null
+++ b/services/audiopolicy/enginedefault/Android.bp
@@ -0,0 +1,32 @@
+cc_library_shared {
+    name: "libaudiopolicyenginedefault",
+    export_include_dirs: ["include"],
+    srcs: [
+        "src/Engine.cpp",
+        "src/EngineInstance.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    local_include_dirs: ["include"],
+    header_libs: [
+        "libbase_headers",
+        "libaudiopolicycommon",
+        "libaudiopolicyengine_interface_headers",
+    ],
+    static_libs: [
+        "libaudiopolicycomponents",
+        "libaudiopolicyengine_common",
+        "libaudiopolicyengine_config",
+    ],
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libutils",
+        "libmedia_helper",
+        "libaudiopolicy",
+        "libxml2",
+    ],
+}
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
deleted file mode 100644
index ebf383b..0000000
--- a/services/audiopolicy/enginedefault/Android.mk
+++ /dev/null
@@ -1,57 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-# Component build
-#######################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    src/Engine.cpp \
-    src/EngineInstance.cpp \
-    ../engine/common/src/VolumeCurve.cpp \
-    ../engine/common/src/ProductStrategy.cpp \
-    ../engine/common/src/EngineBase.cpp \
-    ../engine/common/src/VolumeGroup.cpp
-
-audio_policy_engine_includes_common := \
-    $(LOCAL_PATH)/include
-
-LOCAL_CFLAGS += \
-    -Wall \
-    -Werror \
-    -Wextra \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(audio_policy_engine_includes_common)
-
-LOCAL_C_INCLUDES := \
-    $(audio_policy_engine_includes_common) \
-    $(TARGET_OUT_HEADERS)/hw \
-    $(call include-path-for, frameworks-av) \
-    $(call include-path-for, audio-utils) \
-    $(call include-path-for, bionic)
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_MODULE := libaudiopolicyenginedefault
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_HEADER_LIBRARIES := libbase_headers
-
-LOCAL_STATIC_LIBRARIES := \
-    libaudiopolicycomponents
-
-LOCAL_SHARED_LIBRARIES := \
-    liblog \
-    libcutils \
-    libutils \
-    libmedia_helper \
-    libaudiopolicyengineconfig \
-    libaudiopolicy
-
-LOCAL_HEADER_LIBRARIES := \
-    libaudiopolicycommon \
-    libaudiopolicyengine_common_headers \
-    libaudiopolicyengine_interface_headers
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c969af3..ea98253 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1022,7 +1022,8 @@
         }
     }
     if (*output == AUDIO_IO_HANDLE_NONE) {
-        *output = getOutputForDevices(outputDevices, session, *stream, config, flags);
+        *output = getOutputForDevices(outputDevices, session, *stream, config,
+                flags, attr->flags & AUDIO_FLAG_MUTE_HAPTIC);
     }
     if (*output == AUDIO_IO_HANDLE_NONE) {
         return INVALID_OPERATION;
@@ -1100,11 +1101,16 @@
         audio_session_t session,
         audio_stream_type_t stream,
         const audio_config_t *config,
-        audio_output_flags_t *flags)
+        audio_output_flags_t *flags,
+        bool forceMutingHaptic)
 {
     audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
     status_t status;
 
+    // Discard haptic channel mask when forcing muting haptic channels.
+    audio_channel_mask_t channelMask = forceMutingHaptic
+            ? (config->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL) : config->channel_mask;
+
     // open a direct output if required by specified parameters
     //force direct flag if offload flag is set: offloading implies a direct output stream
     // and all common behaviors are driven by checking only the direct flag
@@ -1141,7 +1147,7 @@
     // and not explicitly requested
     if (((*flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
             audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
-            audio_channel_count_from_out_mask(config->channel_mask) <= 2) {
+            audio_channel_count_from_out_mask(channelMask) <= 2) {
         goto non_direct_output;
     }
 
@@ -1157,7 +1163,7 @@
         profile = getProfileForOutput(devices,
                                    config->sample_rate,
                                    config->format,
-                                   config->channel_mask,
+                                   channelMask,
                                    (audio_output_flags_t)*flags,
                                    true /* directOnly */);
     }
@@ -1171,7 +1177,7 @@
                 // and configured with same parameters
                 if ((config->sample_rate == desc->mSamplingRate) &&
                     (config->format == desc->mFormat) &&
-                    (config->channel_mask == desc->mChannelMask) &&
+                    (channelMask == desc->mChannelMask) &&
                     (session == desc->mDirectClientSession)) {
                     desc->mDirectOpenCount++;
                     ALOGI("%s reusing direct output %d for session %d", __func__, 
@@ -1213,11 +1219,11 @@
         if (status != NO_ERROR ||
             (config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
             (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->mFormat) ||
-            (config->channel_mask != 0 && config->channel_mask != outputDesc->mChannelMask)) {
+            (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
             ALOGV("%s failed opening direct output: output %d sample rate %d %d," 
                     "format %d %d, channel mask %04x %04x", __func__, output, config->sample_rate,
                     outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
-                    config->channel_mask, outputDesc->mChannelMask);
+                    channelMask, outputDesc->mChannelMask);
             if (output != AUDIO_IO_HANDLE_NONE) {
                 outputDesc->close();
             }
@@ -1258,12 +1264,11 @@
 
         // at this stage we should ignore the DIRECT flag as no direct output could be found earlier
         *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
-        output = selectOutput(outputs, *flags, config->format,
-                config->channel_mask, config->sample_rate);
+        output = selectOutput(outputs, *flags, config->format, channelMask, config->sample_rate);
     }
     ALOGW_IF((output == 0), "getOutputForDevices() could not find output for stream %d, "
             "sampling rate %d, format %#x, channels %#x, flags %#x",
-            stream, config->sample_rate, config->format, config->channel_mask, *flags);
+            stream, config->sample_rate, config->format, channelMask, *flags);
 
     return output;
 }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 641a03a..3a31e1e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -779,7 +779,8 @@
                 audio_session_t session,
                 audio_stream_type_t stream,
                 const audio_config_t *config,
-                audio_output_flags_t *flags);
+                audio_output_flags_t *flags,
+                bool forceMutingHaptic = false);
 
         /**
          * @brief getInputForDevice selects an input handle for a given input device and
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 2794324..22e09e4 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -4391,8 +4391,11 @@
             dst.status = BufferStatus::OK;
             dst.releaseFence = nullptr;
 
-            pushInflightBufferLocked(captureRequest->frameNumber, streamId,
-                    src->buffer, src->acquire_fence);
+            // Output buffers are empty when using HAL buffer manager
+            if (!mUseHalBufManager) {
+                pushInflightBufferLocked(captureRequest->frameNumber, streamId,
+                        src->buffer, src->acquire_fence);
+            }
         }
     }
     return OK;
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 65fcf40..661a475 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -6,7 +6,7 @@
 LOCAL_SRC_FILES := \
     MediaExtractorService.cpp
 
-LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils liblog
+LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils
 LOCAL_MODULE:= libmediaextractorservice
 include $(BUILD_SHARED_LIBRARY)
 
@@ -21,7 +21,7 @@
 
 LOCAL_SRC_FILES := main_extractorservice.cpp
 LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils \
-    liblog libbase libandroidicu libavservices_minijail
+    liblog libandroidicu libavservices_minijail
 LOCAL_STATIC_LIBRARIES := libicuandroid_utils
 LOCAL_MODULE:= mediaextractor
 LOCAL_INIT_RC := mediaextractor.rc