Merge "Log requested sharing mode." into sc-dev
diff --git a/apex/mediatranscoding.rc b/apex/mediatranscoding.rc
index ae9f8ba..87df2d5 100644
--- a/apex/mediatranscoding.rc
+++ b/apex/mediatranscoding.rc
@@ -7,6 +7,7 @@
     group media
     ioprio rt 4
     # Restrict to little cores only with system-background cpuset.
-    writepid /dev/cpuset/system-background/tasks
+    # Lower IO priority to background.
+    writepid /dev/cpuset/system-background/tasks /dev/blkio/background/tasks
     interface aidl media.transcoding
     disabled
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index bab651f..0b121ad 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -28,6 +28,7 @@
 #include <media/stagefright/foundation/AUtils.h>
 
 #include <C2Debug.h>
+#include <Codec2Mapper.h>
 #include <C2PlatformSupport.h>
 #include <Codec2BufferUtils.h>
 #include <SimpleC2Interface.h>
@@ -213,6 +214,42 @@
                 .withFields({C2F(mSyncFramePeriod, value).any()})
                 .withSetter(Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps)
                 .build());
+
+        addParameter(
+                DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+                .withDefault(new C2StreamColorAspectsInfo::input(
+                        0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+                        C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                .withFields({
+                    C2F(mColorAspects, range).inRange(
+                                C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
+                    C2F(mColorAspects, primaries).inRange(
+                                C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+                    C2F(mColorAspects, transfer).inRange(
+                                C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
+                    C2F(mColorAspects, matrix).inRange(
+                                C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
+                })
+                .withSetter(ColorAspectsSetter)
+                .build());
+
+        addParameter(
+                DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+                .withDefault(new C2StreamColorAspectsInfo::output(
+                        0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
+                        C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                .withFields({
+                    C2F(mCodedColorAspects, range).inRange(
+                                C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
+                    C2F(mCodedColorAspects, primaries).inRange(
+                                C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+                    C2F(mCodedColorAspects, transfer).inRange(
+                                C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
+                    C2F(mCodedColorAspects, matrix).inRange(
+                                C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
+                })
+                .withSetter(CodedColorAspectsSetter, mColorAspects)
+                .build());
     }
 
     static C2R InputDelaySetter(
@@ -359,6 +396,33 @@
         return C2R::Ok();
     }
 
+    static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &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 CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
+                                       const C2P<C2StreamColorAspectsInfo::input> &coded) {
+        (void)mayBlock;
+        me.set().range = coded.v.range;
+        me.set().primaries = coded.v.primaries;
+        me.set().transfer = coded.v.transfer;
+        me.set().matrix = coded.v.matrix;
+        return C2R::Ok();
+    }
+
     IV_PROFILE_T getProfile_l() const {
         switch (mProfileLevel->profile) {
         case PROFILE_AVC_CONSTRAINED_BASELINE:  [[fallthrough]];
@@ -418,6 +482,9 @@
     std::shared_ptr<C2StreamGopTuning::output> getGop_l() const { return mGop; }
     std::shared_ptr<C2StreamPictureQuantizationTuning::output> getPictureQuantization_l() const
     { return mPictureQuantization; }
+    std::shared_ptr<C2StreamColorAspectsInfo::output> getCodedColorAspects_l() const {
+        return mCodedColorAspects;
+    }
 
 private:
     std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -430,6 +497,8 @@
     std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
     std::shared_ptr<C2StreamGopTuning::output> mGop;
     std::shared_ptr<C2StreamPictureQuantizationTuning::output> mPictureQuantization;
+    std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
+    std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
 };
 
 #define ive_api_function  ih264e_api_function
@@ -980,6 +1049,55 @@
     return;
 }
 
+c2_status_t C2SoftAvcEnc::setVuiParams()
+{
+    ColorAspects sfAspects;
+    if (!C2Mapper::map(mColorAspects->primaries, &sfAspects.mPrimaries)) {
+        sfAspects.mPrimaries = android::ColorAspects::PrimariesUnspecified;
+    }
+    if (!C2Mapper::map(mColorAspects->range, &sfAspects.mRange)) {
+        sfAspects.mRange = android::ColorAspects::RangeUnspecified;
+    }
+    if (!C2Mapper::map(mColorAspects->matrix, &sfAspects.mMatrixCoeffs)) {
+        sfAspects.mMatrixCoeffs = android::ColorAspects::MatrixUnspecified;
+    }
+    if (!C2Mapper::map(mColorAspects->transfer, &sfAspects.mTransfer)) {
+        sfAspects.mTransfer = android::ColorAspects::TransferUnspecified;
+    }
+    int32_t primaries, transfer, matrixCoeffs;
+    bool range;
+    ColorUtils::convertCodecColorAspectsToIsoAspects(sfAspects,
+            &primaries,
+            &transfer,
+            &matrixCoeffs,
+            &range);
+    ih264e_vui_ip_t s_vui_params_ip {};
+    ih264e_vui_op_t s_vui_params_op {};
+
+    s_vui_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
+    s_vui_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_VUI_PARAMS;
+
+    s_vui_params_ip.u1_video_signal_type_present_flag = 1;
+    s_vui_params_ip.u1_colour_description_present_flag = 1;
+    s_vui_params_ip.u1_colour_primaries = primaries;
+    s_vui_params_ip.u1_transfer_characteristics = transfer;
+    s_vui_params_ip.u1_matrix_coefficients = matrixCoeffs;
+    s_vui_params_ip.u1_video_full_range_flag = range;
+
+    s_vui_params_ip.u4_size = sizeof(ih264e_vui_ip_t);
+    s_vui_params_op.u4_size = sizeof(ih264e_vui_op_t);
+
+    IV_STATUS_T status = ih264e_api_function(mCodecCtx, &s_vui_params_ip,
+                                             &s_vui_params_op);
+    if(status != IV_SUCCESS)
+    {
+        ALOGE("Unable to set vui params = 0x%x\n",
+                s_vui_params_op.u4_error_code);
+        return C2_CORRUPTED;
+    }
+    return C2_OK;
+}
+
 c2_status_t C2SoftAvcEnc::initEncoder() {
     IV_STATUS_T status;
     WORD32 level;
@@ -999,6 +1117,7 @@
         mIInterval = mIntf->getSyncFramePeriod_l();
         mIDRInterval = mIntf->getSyncFramePeriod_l();
         gop = mIntf->getGop_l();
+        mColorAspects = mIntf->getCodedColorAspects_l();
     }
     if (gop && gop->flexCount() > 0) {
         uint32_t syncInterval = 1;
@@ -1223,6 +1342,9 @@
     /* Video control Set Profile params */
     setProfileParams();
 
+    /* Video control Set VUI params */
+    setVuiParams();
+
     /* Video control Set in Encode header mode */
     setEncMode(IVE_ENC_MODE_HEADER);
 
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.h b/media/codec2/components/avc/C2SoftAvcEnc.h
index 673a282..baf33e2 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.h
+++ b/media/codec2/components/avc/C2SoftAvcEnc.h
@@ -196,6 +196,7 @@
     std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
     std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
     std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
+    std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
 
     uint32_t mOutBufferSize;
     UWORD32 mHeaderGenerated;
@@ -229,6 +230,7 @@
     c2_status_t setProfileParams();
     c2_status_t setDeblockParams();
     c2_status_t setVbvParams();
+    c2_status_t setVuiParams();
     void logVersion();
     c2_status_t setEncodeArgs(
             ive_video_encode_ip_t *ps_encode_ip,
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 436a2c4..4bc1777 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -25,6 +25,7 @@
 #include <media/stagefright/foundation/AUtils.h>
 
 #include <C2Debug.h>
+#include <Codec2Mapper.h>
 #include <C2PlatformSupport.h>
 #include <Codec2BufferUtils.h>
 #include <SimpleC2Interface.h>
@@ -208,6 +209,42 @@
                 .withSetter(
                     Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps)
                 .build());
+
+        addParameter(
+                DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+                .withDefault(new C2StreamColorAspectsInfo::input(
+                        0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+                        C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                .withFields({
+                    C2F(mColorAspects, range).inRange(
+                                C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
+                    C2F(mColorAspects, primaries).inRange(
+                                C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+                    C2F(mColorAspects, transfer).inRange(
+                                C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
+                    C2F(mColorAspects, matrix).inRange(
+                                C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
+                })
+                .withSetter(ColorAspectsSetter)
+                .build());
+
+        addParameter(
+                DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+                .withDefault(new C2StreamColorAspectsInfo::output(
+                        0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
+                        C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                .withFields({
+                    C2F(mCodedColorAspects, range).inRange(
+                                C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
+                    C2F(mCodedColorAspects, primaries).inRange(
+                                C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+                    C2F(mCodedColorAspects, transfer).inRange(
+                                C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
+                    C2F(mCodedColorAspects, matrix).inRange(
+                                C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
+                })
+                .withSetter(CodedColorAspectsSetter, mColorAspects)
+                .build());
     }
 
     static C2R InputDelaySetter(
@@ -402,6 +439,34 @@
     std::shared_ptr<C2StreamGopTuning::output> getGop_l() const {
         return mGop;
     }
+    static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &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 CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
+                                       const C2P<C2StreamColorAspectsInfo::input> &coded) {
+        (void)mayBlock;
+        me.set().range = coded.v.range;
+        me.set().primaries = coded.v.primaries;
+        me.set().transfer = coded.v.transfer;
+        me.set().matrix = coded.v.matrix;
+        return C2R::Ok();
+    }
+    std::shared_ptr<C2StreamColorAspectsInfo::output> getCodedColorAspects_l() {
+        return mCodedColorAspects;
+    }
 
    private:
     std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -415,6 +480,8 @@
     std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
     std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
     std::shared_ptr<C2StreamGopTuning::output> mGop;
+    std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
+    std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
 };
 
 static size_t GetCPUCoreCount() {
@@ -533,6 +600,32 @@
             mBframes = maxBframes;
         }
     }
+    ColorAspects sfAspects;
+    if (!C2Mapper::map(mColorAspects->primaries, &sfAspects.mPrimaries)) {
+        sfAspects.mPrimaries = android::ColorAspects::PrimariesUnspecified;
+    }
+    if (!C2Mapper::map(mColorAspects->range, &sfAspects.mRange)) {
+        sfAspects.mRange = android::ColorAspects::RangeUnspecified;
+    }
+    if (!C2Mapper::map(mColorAspects->matrix, &sfAspects.mMatrixCoeffs)) {
+        sfAspects.mMatrixCoeffs = android::ColorAspects::MatrixUnspecified;
+    }
+    if (!C2Mapper::map(mColorAspects->transfer, &sfAspects.mTransfer)) {
+        sfAspects.mTransfer = android::ColorAspects::TransferUnspecified;
+    }
+    int32_t primaries, transfer, matrixCoeffs;
+    bool range;
+    ColorUtils::convertCodecColorAspectsToIsoAspects(sfAspects,
+            &primaries,
+            &transfer,
+            &matrixCoeffs,
+            &range);
+    mEncParams.s_out_strm_prms.i4_vui_enable = 1;
+    mEncParams.s_vui_sei_prms.u1_colour_description_present_flag = 1;
+    mEncParams.s_vui_sei_prms.u1_colour_primaries = primaries;
+    mEncParams.s_vui_sei_prms.u1_transfer_characteristics = transfer;
+    mEncParams.s_vui_sei_prms.u1_matrix_coefficients = matrixCoeffs;
+    mEncParams.s_vui_sei_prms.u1_video_full_range_flag = range;
     // update configuration
     mEncParams.s_src_prms.i4_width = mSize->width;
     mEncParams.s_src_prms.i4_height = mSize->height;
@@ -629,6 +722,7 @@
         mQuality = mIntf->getQuality_l();
         mGop = mIntf->getGop_l();
         mRequestSync = mIntf->getRequestSync_l();
+        mColorAspects = mIntf->getCodedColorAspects_l();
     }
 
     c2_status_t status = initEncParams();
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.h b/media/codec2/components/hevc/C2SoftHevcEnc.h
index 5ea4602..9dbf682 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.h
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.h
@@ -89,6 +89,7 @@
     std::shared_ptr<C2StreamQualityTuning::output> mQuality;
     std::shared_ptr<C2StreamGopTuning::output> mGop;
     std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
+    std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
 #ifdef FILE_DUMP_ENABLE
     char mInFile[200];
     char mOutFile[200];
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.h b/media/codec2/components/vpx/C2SoftVpxEnc.h
index 5e34b8a..c98b802 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.h
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.h
@@ -345,6 +345,42 @@
                 .withFields({C2F(mRequestSync, value).oneOf({ C2_FALSE, C2_TRUE }) })
                 .withSetter(Setter<decltype(*mRequestSync)>::NonStrictValueWithNoDeps)
                 .build());
+
+        addParameter(
+                DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+                .withDefault(new C2StreamColorAspectsInfo::input(
+                        0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+                        C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                .withFields({
+                    C2F(mColorAspects, range).inRange(
+                                C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
+                    C2F(mColorAspects, primaries).inRange(
+                                C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+                    C2F(mColorAspects, transfer).inRange(
+                                C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
+                    C2F(mColorAspects, matrix).inRange(
+                                C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
+                })
+                .withSetter(ColorAspectsSetter)
+                .build());
+
+        addParameter(
+                DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+                .withDefault(new C2StreamColorAspectsInfo::output(
+                        0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
+                        C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                .withFields({
+                    C2F(mCodedColorAspects, range).inRange(
+                                C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
+                    C2F(mCodedColorAspects, primaries).inRange(
+                                C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+                    C2F(mCodedColorAspects, transfer).inRange(
+                                C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
+                    C2F(mCodedColorAspects, matrix).inRange(
+                                C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
+                })
+                .withSetter(CodedColorAspectsSetter, mColorAspects)
+                .build());
     }
 
     static C2R BitrateSetter(bool mayBlock, C2P<C2StreamBitrateInfo::output> &me) {
@@ -415,6 +451,31 @@
         double period = mSyncFramePeriod->value / 1e6 * mFrameRate->value;
         return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.);
     }
+    static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &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 CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
+                                       const C2P<C2StreamColorAspectsInfo::input> &coded) {
+        (void)mayBlock;
+        me.set().range = coded.v.range;
+        me.set().primaries = coded.v.primaries;
+        me.set().transfer = coded.v.transfer;
+        me.set().matrix = coded.v.matrix;
+        return C2R::Ok();
+    }
 
    private:
     std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -427,6 +488,8 @@
     std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
     std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
     std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
+    std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
+    std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
 };
 
 }  // namespace android
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index efc5813..58a568e 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -23,21 +23,18 @@
 #include <stdio.h>
 #include <algorithm>
 
-#include <C2AllocatorIon.h>
 #include <C2Buffer.h>
 #include <C2BufferPriv.h>
 #include <C2Config.h>
 #include <C2Debug.h>
 #include <codec2/hidl/client.h>
 
-using android::C2AllocatorIon;
-
 #include "media_c2_hidl_test_common.h"
 using DecodeTestParameters = std::tuple<std::string, std::string, uint32_t, bool>;
-static std::vector<DecodeTestParameters> kDecodeTestParameters;
+static std::vector<DecodeTestParameters> gDecodeTestParameters;
 
 using CsdFlushTestParameters = std::tuple<std::string, std::string, bool>;
-static std::vector<CsdFlushTestParameters> kCsdFlushTestParameters;
+static std::vector<CsdFlushTestParameters> gCsdFlushTestParameters;
 
 struct CompToURL {
     std::string mime;
@@ -45,7 +42,7 @@
     std::string info;
 };
 
-std::vector<CompToURL> kCompToURL = {
+std::vector<CompToURL> gCompToURL = {
         {"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.info"},
         {"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac",
          "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"},
@@ -290,11 +287,11 @@
 // LookUpTable of clips and metadata for component testing
 void Codec2AudioDecHidlTestBase::GetURLForComponent(char* mURL, char* info, size_t streamIndex) {
     int streamCount = 0;
-    for (size_t i = 0; i < kCompToURL.size(); ++i) {
-        if (mMime.find(kCompToURL[i].mime) != std::string::npos) {
+    for (size_t i = 0; i < gCompToURL.size(); ++i) {
+        if (mMime.find(gCompToURL[i].mime) != std::string::npos) {
             if (streamCount == streamIndex) {
-                strcat(mURL, kCompToURL[i].mURL.c_str());
-                strcat(info, kCompToURL[i].info.c_str());
+                strcat(mURL, gCompToURL[i].mURL.c_str());
+                strcat(info, gCompToURL[i].info.c_str());
                 return;
             }
             streamCount++;
@@ -859,36 +856,36 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioDecHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioDecHidlTest, testing::ValuesIn(gTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 // DecodeTest with StreamIndex and EOS / No EOS
 INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2AudioDecDecodeTest,
-                         testing::ValuesIn(kDecodeTestParameters),
+                         testing::ValuesIn(gDecodeTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 INSTANTIATE_TEST_SUITE_P(CsdInputs, Codec2AudioDecCsdInputTests,
-                         testing::ValuesIn(kCsdFlushTestParameters),
+                         testing::ValuesIn(gCsdFlushTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 }  // anonymous namespace
 
 int main(int argc, char** argv) {
     parseArgs(argc, argv);
-    kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER);
-    for (auto params : kTestParameters) {
-        kDecodeTestParameters.push_back(
+    gTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER);
+    for (auto params : gTestParameters) {
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false));
-        kDecodeTestParameters.push_back(
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true));
-        kDecodeTestParameters.push_back(
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 1, false));
-        kDecodeTestParameters.push_back(
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 1, true));
 
-        kCsdFlushTestParameters.push_back(
+        gCsdFlushTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), true));
-        kCsdFlushTestParameters.push_back(
+        gCsdFlushTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), false));
     }
 
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
index 562c77f..92b53a0 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
@@ -24,20 +24,17 @@
 #include <algorithm>
 #include <fstream>
 
-#include <C2AllocatorIon.h>
 #include <C2Buffer.h>
 #include <C2BufferPriv.h>
 #include <C2Config.h>
 #include <C2Debug.h>
 #include <codec2/hidl/client.h>
 
-using android::C2AllocatorIon;
-
 #include "media_c2_hidl_test_common.h"
 
 using EncodeTestParameters = std::tuple<std::string, std::string, bool, int32_t>;
 
-static std::vector<EncodeTestParameters> kEncodeTestParameters;
+static std::vector<EncodeTestParameters> gEncodeTestParameters;
 
 class LinearBuffer : public C2Buffer {
   public:
@@ -45,6 +42,8 @@
         : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
 };
 
+constexpr uint32_t kMaxSamplesPerFrame = 256;
+
 namespace {
 
 class Codec2AudioEncHidlTestBase : public ::testing::Test {
@@ -98,7 +97,7 @@
     // Get the test parameters from GetParam call.
     virtual void getParams() {}
 
-    void GetURLForComponent(char* mURL);
+    void GetURLForComponent(char* mURL, int32_t channelCount, int32_t sampleRate);
 
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
@@ -223,53 +222,105 @@
     return false;
 }
 
+c2_status_t getChannelCount(const std::shared_ptr<android::Codec2Client::Component>& component,
+                            int32_t* nChannels) {
+    std::unique_ptr<C2StreamChannelCountInfo::input> channelCount =
+            std::make_unique<C2StreamChannelCountInfo::input>();
+    std::vector<C2FieldSupportedValuesQuery> validValueInfos = {
+            C2FieldSupportedValuesQuery::Current(
+                    C2ParamField(channelCount.get(), &C2StreamChannelCountInfo::value))};
+    c2_status_t c2err = component->querySupportedValues(validValueInfos, C2_DONT_BLOCK);
+    if (c2err != C2_OK || validValueInfos.size() != 1u) {
+        ALOGE("querySupportedValues_vb failed for channelCount");
+        return c2err;
+    }
+
+    // setting default value of channelCount
+    *nChannels = 1;
+    const auto& c2FSV = validValueInfos[0].values;
+    switch (c2FSV.type) {
+        case C2FieldSupportedValues::type_t::RANGE: {
+            const auto& range = c2FSV.range;
+            uint32_t rmax = (uint32_t)(range.max).ref<uint32_t>();
+            if (rmax >= 2) {
+                *nChannels = 2;
+            } else {
+                *nChannels = 1;
+            }
+            break;
+        }
+        case C2FieldSupportedValues::type_t::VALUES: {
+            for (const C2Value::Primitive& prim : c2FSV.values) {
+                if ((uint32_t)prim.ref<uint32_t>() == 2) {
+                    *nChannels = 2;
+                } else if ((uint32_t)prim.ref<uint32_t>() == 1) {
+                    *nChannels = 1;
+                }
+            }
+            break;
+        }
+        default:
+            break;
+    }
+    return C2_OK;
+}
+
+c2_status_t getSampleRate(const std::shared_ptr<android::Codec2Client::Component>& component,
+                          int32_t* nSampleRate) {
+    // Use the default sample rate for components
+    std::vector<std::unique_ptr<C2Param>> queried;
+    c2_status_t c2err = component->query({}, {C2StreamSampleRateInfo::input::PARAM_TYPE},
+                                         C2_DONT_BLOCK, &queried);
+    if (c2err != C2_OK || queried.size() == 0) return c2err;
+
+    size_t offset = sizeof(C2Param);
+    C2Param* param = queried[0].get();
+    *nSampleRate = *(int32_t*)((uint8_t*)param + offset);
+
+    return C2_OK;
+}
+
+c2_status_t getSamplesPerFrame(const std::shared_ptr<android::Codec2Client::Component>& component,
+                               int32_t nChannels, int32_t* samplesPerFrame) {
+    std::vector<std::unique_ptr<C2Param>> queried;
+    c2_status_t c2err = component->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE},
+                                         C2_DONT_BLOCK, &queried);
+    if (c2err != C2_OK || queried.size() == 0) return c2err;
+
+    size_t offset = sizeof(C2Param);
+    C2Param* param = queried[0].get();
+    uint32_t maxInputSize = *(uint32_t*)((uint8_t*)param + offset);
+    *samplesPerFrame = std::min((maxInputSize / (nChannels * 2)), kMaxSamplesPerFrame);
+
+    return C2_OK;
+}
+
 // Get config params for a component
-bool getConfigParams(std::string mime, int32_t* nChannels, int32_t* nSampleRate,
-                     int32_t* samplesPerFrame) {
-    if (mime.find("mp4a-latm") != std::string::npos) {
-        *nChannels = 2;
-        *nSampleRate = 48000;
-        *samplesPerFrame = 1024;
-    } else if (mime.find("flac") != std::string::npos) {
-        *nChannels = 2;
-        *nSampleRate = 48000;
-        *samplesPerFrame = 1152;
-    } else if (mime.find("opus") != std::string::npos) {
-        *nChannels = 2;
-        *nSampleRate = 48000;
-        *samplesPerFrame = 960;
-    } else if (mime.find("3gpp") != std::string::npos) {
-        *nChannels = 1;
-        *nSampleRate = 8000;
-        *samplesPerFrame = 160;
-    } else if (mime.find("amr-wb") != std::string::npos) {
-        *nChannels = 1;
-        *nSampleRate = 16000;
-        *samplesPerFrame = 160;
-    } else
-        return false;
+bool getConfigParams(const std::shared_ptr<android::Codec2Client::Component>& component,
+                     int32_t* nChannels, int32_t* nSampleRate, int32_t* samplesPerFrame) {
+    c2_status_t status = getChannelCount(component, nChannels);
+    if (status != C2_OK) return false;
+
+    status = getSampleRate(component, nSampleRate);
+    if (status != C2_OK) return false;
+
+    status = getSamplesPerFrame(component, *nChannels, samplesPerFrame);
+    if (status != C2_OK) return false;
 
     return true;
 }
 
 // LookUpTable of clips and metadata for component testing
-void Codec2AudioEncHidlTestBase::GetURLForComponent(char* mURL) {
-    struct CompToURL {
-        std::string mime;
-        const char* mURL;
-    };
-    static const CompToURL kCompToURL[] = {
-            {"mp4a-latm", "bbb_raw_2ch_48khz_s16le.raw"}, {"3gpp", "bbb_raw_1ch_8khz_s16le.raw"},
-            {"amr-wb", "bbb_raw_1ch_16khz_s16le.raw"},    {"flac", "bbb_raw_2ch_48khz_s16le.raw"},
-            {"opus", "bbb_raw_2ch_48khz_s16le.raw"},
-    };
-
-    for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
-        if (mMime.find(kCompToURL[i].mime) != std::string::npos) {
-            strcat(mURL, kCompToURL[i].mURL);
-            return;
-        }
+void Codec2AudioEncHidlTestBase::GetURLForComponent(char* mURL, int32_t channelCount,
+                                                    int32_t sampleRate) {
+    std::string rawInput = "bbb_raw_1ch_8khz_s16le.raw";
+    if (channelCount == 1 && sampleRate == 16000) {
+        rawInput = "bbb_raw_1ch_16khz_s16le.raw";
+    } else if (channelCount == 2) {
+        rawInput = "bbb_raw_2ch_48khz_s16le.raw";
     }
+
+    strcat(mURL, rawInput.c_str());
 }
 
 void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
@@ -283,9 +334,17 @@
 
     uint32_t frameID = 0;
     uint32_t maxRetry = 0;
-    int bytesCount = samplesPerFrame * nChannels * 2;
+    uint32_t bytesCount = samplesPerFrame * nChannels * 2;
     int32_t timestampIncr = (int)(((float)samplesPerFrame / nSampleRate) * 1000000);
     uint64_t timestamp = 0;
+
+    // get length of file:
+    int32_t currPos = eleStream.tellg();
+    eleStream.seekg(0, eleStream.end);
+    uint32_t remainingBytes = (uint32_t)eleStream.tellg() - currPos;
+    eleStream.seekg(currPos, eleStream.beg);
+
+    nFrames = std::min(nFrames, remainingBytes / bytesCount);
     while (1) {
         if (nFrames == 0) break;
         uint32_t flags = 0;
@@ -319,7 +378,12 @@
         char* data = (char*)malloc(bytesCount);
         ASSERT_NE(data, nullptr);
         eleStream.read(data, bytesCount);
-        ASSERT_EQ(eleStream.gcount(), bytesCount);
+        // if we have reached at the end of input stream, signal eos
+        if (eleStream.gcount() < bytesCount) {
+            bytesCount = eleStream.gcount();
+            if (signalEOS) flags |= C2FrameData::FLAG_END_OF_STREAM;
+        }
+
         std::shared_ptr<C2LinearBlock> block;
         ASSERT_EQ(C2_OK,
                   linearPool->fetchLinearBlock(
@@ -373,9 +437,6 @@
 TEST_P(Codec2AudioEncEncodeTest, EncodeTest) {
     ALOGV("EncodeTest");
     if (mDisableTest) GTEST_SKIP() << "Test is disabled";
-    char mURL[512];
-    strcpy(mURL, sResourceDir.c_str());
-    GetURLForComponent(mURL);
     bool signalEOS = std::get<2>(GetParam());
     // Ratio w.r.t to mInputMaxBufSize
     int32_t inputMaxBufRatio = std::get<3>(GetParam());
@@ -384,7 +445,7 @@
     int32_t nSampleRate;
     int32_t samplesPerFrame;
 
-    if (!getConfigParams(mMime, &nChannels, &nSampleRate, &samplesPerFrame)) {
+    if (!getConfigParams(mComponent, &nChannels, &nSampleRate, &samplesPerFrame)) {
         std::cout << "Failed to get the config params for " << mComponentName << "\n";
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
@@ -398,6 +459,10 @@
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
+    char mURL[512];
+    strcpy(mURL, sResourceDir.c_str());
+    GetURLForComponent(mURL, nChannels, nSampleRate);
+
     ASSERT_EQ(mComponent->start(), C2_OK);
     std::ifstream eleStream;
     uint32_t numFrames = 16;
@@ -479,16 +544,12 @@
     description("Test Request for flush");
     if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
-    char mURL[512];
-    strcpy(mURL, sResourceDir.c_str());
-    GetURLForComponent(mURL);
-
     mFlushedIndices.clear();
     int32_t nChannels;
     int32_t nSampleRate;
     int32_t samplesPerFrame;
 
-    if (!getConfigParams(mMime, &nChannels, &nSampleRate, &samplesPerFrame)) {
+    if (!getConfigParams(mComponent, &nChannels, &nSampleRate, &samplesPerFrame)) {
         std::cout << "Failed to get the config params for " << mComponentName << "\n";
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
@@ -498,6 +559,10 @@
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
+    char mURL[512];
+    strcpy(mURL, sResourceDir.c_str());
+    GetURLForComponent(mURL, nChannels, nSampleRate);
+
     ASSERT_EQ(mComponent->start(), C2_OK);
 
     std::ifstream eleStream;
@@ -544,26 +609,25 @@
     description("Encodes input file for different channel count");
     if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
-    char mURL[512];
-    strcpy(mURL, sResourceDir.c_str());
-    GetURLForComponent(mURL);
-
-    std::ifstream eleStream;
-    eleStream.open(mURL, std::ifstream::binary);
-    ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
-    ALOGV("mURL : %s", mURL);
-
     int32_t nSampleRate;
     int32_t samplesPerFrame;
     int32_t nChannels;
     int32_t numFrames = 16;
     int32_t maxChannelCount = 8;
 
-    if (!getConfigParams(mMime, &nChannels, &nSampleRate, &samplesPerFrame)) {
+    if (!getConfigParams(mComponent, &nChannels, &nSampleRate, &samplesPerFrame)) {
         std::cout << "Failed to get the config params for " << mComponentName << "\n";
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
+    char mURL[512];
+    strcpy(mURL, sResourceDir.c_str());
+    GetURLForComponent(mURL, nChannels, nSampleRate);
+
+    std::ifstream eleStream;
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
+    ALOGV("mURL : %s", mURL);
 
     uint64_t prevOutputSize = 0u;
     uint32_t prevChannelCount = 0u;
@@ -591,8 +655,11 @@
         }
 
         // To check if the input stream is sufficient to encode for the higher channel count
+        struct stat buf;
+        stat(mURL, &buf);
+        size_t fileSize = buf.st_size;
         int32_t bytesCount = (samplesPerFrame * nChannels * 2) * numFrames;
-        if (eleStream.gcount() < bytesCount) {
+        if (fileSize < bytesCount) {
             std::cout << "[   WARN   ] Test Skipped for ChannelCount " << nChannels
                       << " because of insufficient input data\n";
             continue;
@@ -616,9 +683,6 @@
         // blocking call to ensures application to Wait till all the inputs are consumed
         waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
 
-        // Validate output size based on chosen ChannelCount
-        EXPECT_GE(mOutputSize, prevOutputSize);
-
         prevChannelCount = nChannels;
         prevOutputSize = mOutputSize;
 
@@ -633,7 +697,8 @@
             ASSERT_TRUE(mCsd) << "CSD buffer missing";
         }
         ASSERT_TRUE(mEos);
-        ASSERT_EQ(mComponent->stop(), C2_OK);
+        // TODO(b/147348711) Use reset instead of stop when using the same instance of codec.
+        ASSERT_EQ(mComponent->reset(), C2_OK);
         mFramesReceived = 0;
         mOutputSize = 0;
         mEos = false;
@@ -646,25 +711,24 @@
     description("Encodes input file for different SampleRate");
     if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
-    char mURL[512];
-    strcpy(mURL, sResourceDir.c_str());
-    GetURLForComponent(mURL);
-
-    std::ifstream eleStream;
-    eleStream.open(mURL, std::ifstream::binary);
-    ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
-    ALOGV("mURL : %s", mURL);
-
     int32_t nSampleRate;
     int32_t samplesPerFrame;
     int32_t nChannels;
     int32_t numFrames = 16;
 
-    if (!getConfigParams(mMime, &nChannels, &nSampleRate, &samplesPerFrame)) {
+    if (!getConfigParams(mComponent, &nChannels, &nSampleRate, &samplesPerFrame)) {
         std::cout << "Failed to get the config params for " << mComponentName << "\n";
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
+    char mURL[512];
+    strcpy(mURL, sResourceDir.c_str());
+    GetURLForComponent(mURL, nChannels, nSampleRate);
+
+    std::ifstream eleStream;
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
+    ALOGV("mURL : %s", mURL);
 
     int32_t sampleRateValues[] = {1000, 8000, 16000, 24000, 48000, 96000, 192000};
 
@@ -694,8 +758,11 @@
         }
 
         // To check if the input stream is sufficient to encode for the higher SampleRate
+        struct stat buf;
+        stat(mURL, &buf);
+        size_t fileSize = buf.st_size;
         int32_t bytesCount = (samplesPerFrame * nChannels * 2) * numFrames;
-        if (eleStream.gcount() < bytesCount) {
+        if (fileSize < bytesCount) {
             std::cout << "[   WARN   ] Test Skipped for SampleRate " << nSampleRate
                       << " because of insufficient input data\n";
             continue;
@@ -719,12 +786,6 @@
         // blocking call to ensures application to Wait till all the inputs are consumed
         waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
 
-        // Validate output size based on chosen samplerate
-        if (prevSampleRate >= nSampleRate) {
-            EXPECT_LE(mOutputSize, prevOutputSize);
-        } else {
-            EXPECT_GT(mOutputSize, prevOutputSize);
-        }
         prevSampleRate = nSampleRate;
         prevOutputSize = mOutputSize;
 
@@ -739,7 +800,8 @@
             ASSERT_TRUE(mCsd) << "CSD buffer missing";
         }
         ASSERT_TRUE(mEos);
-        ASSERT_EQ(mComponent->stop(), C2_OK);
+        // TODO(b/147348711) Use reset instead of stop when using the same instance of codec.
+        ASSERT_EQ(mComponent->reset(), C2_OK);
         mFramesReceived = 0;
         mOutputSize = 0;
         mEos = false;
@@ -748,28 +810,28 @@
     }
 }
 
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioEncHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioEncHidlTest, testing::ValuesIn(gTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 // EncodeTest with EOS / No EOS and inputMaxBufRatio
 // inputMaxBufRatio is ratio w.r.t. to mInputMaxBufSize
 INSTANTIATE_TEST_SUITE_P(EncodeTest, Codec2AudioEncEncodeTest,
-                         testing::ValuesIn(kEncodeTestParameters),
+                         testing::ValuesIn(gEncodeTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 }  // anonymous namespace
 
 int main(int argc, char** argv) {
     parseArgs(argc, argv);
-    kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_ENCODER);
-    for (auto params : kTestParameters) {
-        kEncodeTestParameters.push_back(
+    gTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_ENCODER);
+    for (auto params : gTestParameters) {
+        gEncodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), false, 1));
-        kEncodeTestParameters.push_back(
+        gEncodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), false, 2));
-        kEncodeTestParameters.push_back(
+        gEncodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), true, 1));
-        kEncodeTestParameters.push_back(
+        gEncodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), true, 2));
     }
 
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index e74f247..2222aaf 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -41,7 +41,7 @@
 using namespace ::std::chrono;
 
 using TestParameters = std::tuple<std::string, std::string>;
-static std::vector<TestParameters> kTestParameters;
+static std::vector<TestParameters> gTestParameters;
 
 // Resource directory
 extern std::string sResourceDir;
diff --git a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
index 29acd33..ffec897 100644
--- a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
@@ -54,7 +54,7 @@
 
 namespace {
 using InputTestParameters = std::tuple<std::string, std::string, uint32_t, bool>;
-static std::vector<InputTestParameters> kInputTestParameters;
+static std::vector<InputTestParameters> gInputTestParameters;
 
 // google.codec2 Component test setup
 class Codec2ComponentHidlTestBase : public ::testing::Test {
@@ -345,28 +345,28 @@
     ASSERT_EQ(mComponent->reset(), C2_OK);
 }
 
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2ComponentHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2ComponentHidlTest, testing::ValuesIn(gTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 INSTANTIATE_TEST_CASE_P(NonStdInputs, Codec2ComponentInputTests,
-                        testing::ValuesIn(kInputTestParameters), PrintInstanceTupleNameToString<>);
+                        testing::ValuesIn(gInputTestParameters), PrintInstanceTupleNameToString<>);
 }  // anonymous namespace
 
 // TODO: Add test for Invalid work,
 // TODO: Add test for Invalid states
 int main(int argc, char** argv) {
     parseArgs(argc, argv);
-    kTestParameters = getTestParameters();
-    for (auto params : kTestParameters) {
-        kInputTestParameters.push_back(
+    gTestParameters = getTestParameters();
+    for (auto params : gTestParameters) {
+        gInputTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true));
-        kInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
+        gInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
                                                        C2FrameData::FLAG_END_OF_STREAM, true));
-        kInputTestParameters.push_back(
+        gInputTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false));
-        kInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
+        gInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
                                                        C2FrameData::FLAG_CODEC_CONFIG, false));
-        kInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
+        gInputTestParameters.push_back(std::make_tuple(std::get<0>(params), std::get<1>(params),
                                                        C2FrameData::FLAG_END_OF_STREAM, false));
     }
 
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index d0a1c31..8d917b3 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -24,7 +24,6 @@
 
 #include <openssl/md5.h>
 
-#include <C2AllocatorIon.h>
 #include <C2Buffer.h>
 #include <C2BufferPriv.h>
 #include <C2Config.h>
@@ -35,16 +34,14 @@
 #include <gui/IProducerListener.h>
 #include <system/window.h>
 
-using android::C2AllocatorIon;
-
 #include "media_c2_hidl_test_common.h"
 #include "media_c2_video_hidl_test_common.h"
 
 using DecodeTestParameters = std::tuple<std::string, std::string, uint32_t, bool>;
-static std::vector<DecodeTestParameters> kDecodeTestParameters;
+static std::vector<DecodeTestParameters> gDecodeTestParameters;
 
 using CsdFlushTestParameters = std::tuple<std::string, std::string, bool>;
-static std::vector<CsdFlushTestParameters> kCsdFlushTestParameters;
+static std::vector<CsdFlushTestParameters> gCsdFlushTestParameters;
 
 struct CompToURL {
     std::string mime;
@@ -52,7 +49,7 @@
     std::string info;
     std::string chksum;
 };
-std::vector<CompToURL> kCompToURL = {
+std::vector<CompToURL> gCompToURL = {
         {"avc", "bbb_avc_176x144_300kbps_60fps.h264", "bbb_avc_176x144_300kbps_60fps.info",
          "bbb_avc_176x144_300kbps_60fps_chksum.md5"},
         {"avc", "bbb_avc_640x360_768kbps_30fps.h264", "bbb_avc_640x360_768kbps_30fps.info",
@@ -365,12 +362,12 @@
 void Codec2VideoDecHidlTestBase::GetURLChksmForComponent(char* mURL, char* info, char* chksum,
                                                          size_t streamIndex) {
     int streamCount = 0;
-    for (size_t i = 0; i < kCompToURL.size(); ++i) {
-        if (mMime.find(kCompToURL[i].mime) != std::string::npos) {
+    for (size_t i = 0; i < gCompToURL.size(); ++i) {
+        if (mMime.find(gCompToURL[i].mime) != std::string::npos) {
             if (streamCount == streamIndex) {
-                strcat(mURL, kCompToURL[i].mURL.c_str());
-                strcat(info, kCompToURL[i].info.c_str());
-                strcat(chksum, kCompToURL[i].chksum.c_str());
+                strcat(mURL, gCompToURL[i].mURL.c_str());
+                strcat(info, gCompToURL[i].info.c_str());
+                strcat(chksum, gCompToURL[i].chksum.c_str());
                 return;
             }
             streamCount++;
@@ -1074,16 +1071,16 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoDecHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoDecHidlTest, testing::ValuesIn(gTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 // DecodeTest with StreamIndex and EOS / No EOS
 INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2VideoDecDecodeTest,
-                         testing::ValuesIn(kDecodeTestParameters),
+                         testing::ValuesIn(gDecodeTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 INSTANTIATE_TEST_SUITE_P(CsdInputs, Codec2VideoDecCsdInputTests,
-                         testing::ValuesIn(kCsdFlushTestParameters),
+                         testing::ValuesIn(gCsdFlushTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 }  // anonymous namespace
@@ -1091,24 +1088,24 @@
 // TODO : Video specific configuration Test
 int main(int argc, char** argv) {
     parseArgs(argc, argv);
-    kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER);
-    for (auto params : kTestParameters) {
-        kDecodeTestParameters.push_back(
+    gTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER);
+    for (auto params : gTestParameters) {
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false));
-        kDecodeTestParameters.push_back(
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true));
-        kDecodeTestParameters.push_back(
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 1, false));
-        kDecodeTestParameters.push_back(
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 1, true));
-        kDecodeTestParameters.push_back(
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 2, false));
-        kDecodeTestParameters.push_back(
+        gDecodeTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 2, true));
 
-        kCsdFlushTestParameters.push_back(
+        gCsdFlushTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), true));
-        kCsdFlushTestParameters.push_back(
+        gCsdFlushTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), false));
     }
 
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index 23ceff4..dfd649d 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -23,15 +23,12 @@
 #include <stdio.h>
 #include <fstream>
 
-#include <C2AllocatorIon.h>
 #include <C2Buffer.h>
 #include <C2BufferPriv.h>
 #include <C2Config.h>
 #include <C2Debug.h>
 #include <codec2/hidl/client.h>
 
-using android::C2AllocatorIon;
-
 #include "media_c2_hidl_test_common.h"
 #include "media_c2_video_hidl_test_common.h"
 
@@ -42,10 +39,10 @@
 };
 
 using EncodeTestParameters = std::tuple<std::string, std::string, bool, bool, bool>;
-static std::vector<EncodeTestParameters> kEncodeTestParameters;
+static std::vector<EncodeTestParameters> gEncodeTestParameters;
 
 using EncodeResolutionTestParameters = std::tuple<std::string, std::string, int32_t, int32_t>;
-static std::vector<EncodeResolutionTestParameters> kEncodeResolutionTestParameters;
+static std::vector<EncodeResolutionTestParameters> gEncodeResolutionTestParameters;
 
 namespace {
 
@@ -706,16 +703,16 @@
     ASSERT_EQ(mComponent->reset(), C2_OK);
 }
 
-INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoEncHidlTest, testing::ValuesIn(kTestParameters),
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoEncHidlTest, testing::ValuesIn(gTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 INSTANTIATE_TEST_SUITE_P(NonStdSizes, Codec2VideoEncResolutionTest,
-                         ::testing::ValuesIn(kEncodeResolutionTestParameters),
+                         ::testing::ValuesIn(gEncodeResolutionTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 // EncodeTest with EOS / No EOS
 INSTANTIATE_TEST_SUITE_P(EncodeTestwithEOS, Codec2VideoEncEncodeTest,
-                         ::testing::ValuesIn(kEncodeTestParameters),
+                         ::testing::ValuesIn(gEncodeTestParameters),
                          PrintInstanceTupleNameToString<>);
 
 TEST_P(Codec2VideoEncHidlTest, AdaptiveBitrateTest) {
@@ -808,24 +805,24 @@
 
 int main(int argc, char** argv) {
     parseArgs(argc, argv);
-    kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_ENCODER);
-    for (auto params : kTestParameters) {
+    gTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_ENCODER);
+    for (auto params : gTestParameters) {
         for (size_t i = 0; i < 1 << 3; ++i) {
-            kEncodeTestParameters.push_back(std::make_tuple(
+            gEncodeTestParameters.push_back(std::make_tuple(
                     std::get<0>(params), std::get<1>(params), i & 1, (i >> 1) & 1, (i >> 2) & 1));
         }
 
-        kEncodeResolutionTestParameters.push_back(
+        gEncodeResolutionTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 52, 18));
-        kEncodeResolutionTestParameters.push_back(
+        gEncodeResolutionTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 365, 365));
-        kEncodeResolutionTestParameters.push_back(
+        gEncodeResolutionTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 484, 362));
-        kEncodeResolutionTestParameters.push_back(
+        gEncodeResolutionTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 244, 488));
-        kEncodeResolutionTestParameters.push_back(
+        gEncodeResolutionTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 852, 608));
-        kEncodeResolutionTestParameters.push_back(
+        gEncodeResolutionTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), 1400, 442));
     }
 
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index e33a5ba..c6ff825 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1780,7 +1780,7 @@
         {
             Mutexed<Output>::Locked output(mOutput);
             numOutputSlots = output->numSlots;
-            reorderDepth = output->buffers->getReorderDepth();
+            reorderDepth = output->buffers ? output->buffers->getReorderDepth() : 0;
         }
         {
             Mutexed<OutputSurface>::Locked output(mOutputSurface);
diff --git a/media/libdatasource/DataSourceFactory.cpp b/media/libdatasource/DataSourceFactory.cpp
index bb6a08c..f91e3ea 100644
--- a/media/libdatasource/DataSourceFactory.cpp
+++ b/media/libdatasource/DataSourceFactory.cpp
@@ -65,6 +65,9 @@
         sp<HTTPBase> mediaHTTP = httpSource;
         if (mediaHTTP == NULL) {
             mediaHTTP = static_cast<HTTPBase *>(CreateMediaHTTP(httpService).get());
+            if (mediaHTTP == NULL) {
+                return NULL;
+            }
         }
 
         String8 cacheConfig;
diff --git a/media/libmediatranscoding/TranscoderWrapper.cpp b/media/libmediatranscoding/TranscoderWrapper.cpp
index 5e4c671..60b780f 100644
--- a/media/libmediatranscoding/TranscoderWrapper.cpp
+++ b/media/libmediatranscoding/TranscoderWrapper.cpp
@@ -478,7 +478,7 @@
     media_status_t err =
             setupTranscoder(clientId, sessionId, request, callingUid, clientCb, &reason);
     if (err != AMEDIA_OK) {
-        ALOGI("%s: failed to setup transcoder", __FUNCTION__);
+        ALOGE("%s: failed to setup transcoder", __FUNCTION__);
         logSessionEnded(reason, err);
         return err;
     }
@@ -613,7 +613,7 @@
         Event event = *mQueue.begin();
         mQueue.pop_front();
 
-        ALOGD("%s: %s", __FUNCTION__, toString(event).c_str());
+        ALOGV("%s: %s", __FUNCTION__, toString(event).c_str());
 
         if (event.type == Event::Abandon) {
             break;
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index c19fe38..e3931b1 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -73,6 +73,8 @@
       return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
     case AUDIO_SOURCE_REMOTE_SUBMIX:
       return AppOpsManager::OP_RECORD_AUDIO_OUTPUT;
+    case AUDIO_SOURCE_VOICE_DOWNLINK:
+      return AppOpsManager::OP_RECORD_INCOMING_PHONE_AUDIO;
     case AUDIO_SOURCE_DEFAULT:
     default:
       return AppOpsManager::OP_RECORD_AUDIO;
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index b953c0b..451c198 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -70,7 +70,7 @@
                                 audio_input_flags_t flags,
                                 track_type type,
                                 audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
-                                int64_t startTimeMs = -1);
+                                int32_t startFrames = -1);
     virtual             ~RecordTrack();
     virtual status_t    initCheck() const;
 
@@ -110,7 +110,7 @@
             status_t    setPreferredMicrophoneFieldDimension(float zoom);
             status_t    shareAudioHistory(const std::string& sharedAudioPackageName,
                                           int64_t sharedAudioStartMs);
-            int64_t     startTimeMs() { return mStartTimeMs; }
+            int32_t     startFrames() { return mStartFrames; }
 
     static  bool        checkServerLatencySupported(
                                 audio_format_t format, audio_input_flags_t flags) {
@@ -152,7 +152,7 @@
             // used to enforce OP_RECORD_AUDIO
             sp<OpRecordAudioMonitor>           mOpRecordAudioMonitor;
             std::string                        mSharedAudioPackageName = {};
-            int64_t                            mStartTimeMs = -1;
+            int32_t                            mStartFrames = -1;
 };
 
 // playback track, used by PatchPanel
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6da4543..51f3032 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -124,12 +124,26 @@
 // 50 * ~20msecs = 1 second
 static const int8_t kMaxTrackRetries = 50;
 static const int8_t kMaxTrackStartupRetries = 50;
+
 // allow less retry attempts on direct output thread.
 // direct outputs can be a scarce resource in audio hardware and should
 // be released as quickly as possible.
-static const int8_t kMaxTrackRetriesDirect = 2;
-
-
+// Notes:
+// 1) The retry duration kMaxTrackRetriesDirectMs may be increased
+//    in case the data write is bursty for the AudioTrack.  The application
+//    should endeavor to write at least once every kMaxTrackRetriesDirectMs
+//    to prevent an underrun situation.  If the data is bursty, then
+//    the application can also throttle the data sent to be even.
+// 2) For compressed audio data, any data present in the AudioTrack buffer
+//    will be sent and reset the retry count.  This delivers data as
+//    it arrives, with approximately kDirectMinSleepTimeUs = 10ms checking interval.
+// 3) For linear PCM or proportional PCM, we wait one period for a period's worth
+//    of data to be available, then any remaining data is delivered.
+//    This is required to ensure the last bit of data is delivered before underrun.
+//
+// Sleep time per cycle is kDirectMinSleepTimeUs for compressed tracks
+// or the size of the HAL period for proportional / linear PCM tracks.
+static const int32_t kMaxTrackRetriesDirectMs = 200;
 
 // don't warn about blocked writes or record buffer overflows more often than this
 static const nsecs_t kWarningThrottleNs = seconds(5);
@@ -5931,11 +5945,19 @@
         // Allow draining the buffer in case the client
         // app does not call stop() and relies on underrun to stop:
         // hence the test on (track->mRetryCount > 1).
-        // If retryCount<=1 then track is about to underrun and be removed.
+        // If track->mRetryCount <= 1 then track is about to be disabled, paused, removed,
+        // so we accept any nonzero amount of data delivered by the AudioTrack (which will
+        // reset the retry counter).
         // Do not use a high threshold for compressed audio.
+
+        // target retry count that we will use is based on the time we wait for retries.
+        const int32_t targetRetryCount = kMaxTrackRetriesDirectMs * 1000 / mActiveSleepTimeUs;
+        // the retry threshold is when we accept any size for PCM data.  This is slightly
+        // smaller than the retry count so we can push small bits of data without a glitch.
+        const int32_t retryThreshold = targetRetryCount > 2 ? targetRetryCount - 1 : 1;
         uint32_t minFrames;
         if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing()
-            && (track->mRetryCount > 1) && audio_has_proportional_frames(mFormat)) {
+            && (track->mRetryCount > retryThreshold) && audio_has_proportional_frames(mFormat)) {
             minFrames = mNormalFrameCount;
         } else {
             minFrames = 1;
@@ -5979,7 +6001,7 @@
                 mPreviousTrack = track;
 
                 // reset retry count
-                track->mRetryCount = kMaxTrackRetriesDirect;
+                track->mRetryCount = targetRetryCount;
                 mActiveTrack = t;
                 mixerStatus = MIXER_TRACKS_READY;
                 if (mHwPaused) {
@@ -6033,15 +6055,17 @@
                     // indicate to client process that the track was disabled because of underrun;
                     // it will then automatically call start() when data is available
                     track->disable();
-                } else if (last) {
+                    // only do hw pause when track is going to be removed due to BUFFER TIMEOUT.
+                    // unlike mixerthread, HAL can be paused for direct output
                     ALOGW("pause because of UNDERRUN, framesReady = %zu,"
                             "minFrames = %u, mFormat = %#x",
                             framesReady, minFrames, mFormat);
-                    mixerStatus = MIXER_TRACKS_ENABLED;
-                    if (mHwSupportsPause && !mHwPaused && !mStandby) {
+                    if (last && mHwSupportsPause && !mHwPaused && !mStandby) {
                         doHwPause = true;
                         mHwPaused = true;
                     }
+                } else if (last) {
+                    mixerStatus = MIXER_TRACKS_ENABLED;
                 }
             }
         }
@@ -6113,16 +6137,13 @@
         mSleepTimeUs = mIdleSleepTimeUs;
         return;
     }
-    if (mSleepTimeUs == 0) {
-        if (mMixerStatus == MIXER_TRACKS_ENABLED) {
-            mSleepTimeUs = mActiveSleepTimeUs;
-        } else {
-            mSleepTimeUs = mIdleSleepTimeUs;
-        }
-    } else if (mBytesWritten != 0 && audio_has_proportional_frames(mFormat)) {
-        memset(mSinkBuffer, 0, mFrameCount * mFrameSize);
-        mSleepTimeUs = 0;
+    if (mMixerStatus == MIXER_TRACKS_ENABLED) {
+        mSleepTimeUs = mActiveSleepTimeUs;
+    } else {
+        mSleepTimeUs = mIdleSleepTimeUs;
     }
+    // Note: In S or later, we do not write zeroes for
+    // linear or proportional PCM direct tracks in underrun.
 }
 
 void AudioFlinger::DirectOutputThread::threadLoop_exit()
@@ -7932,18 +7953,18 @@
 
     { // scope for mLock
         Mutex::Autolock _l(mLock);
-        long startTimeMs = -1;
+        int32_t startFrames = -1;
         if (!mSharedAudioPackageName.empty()
                 && mSharedAudioPackageName == checkedIdentity.packageName
                 && mSharedAudioSessionId == sessionId
                 && captureHotwordAllowed(checkedIdentity)) {
-            startTimeMs = mSharedAudioStartMs;
+            startFrames = mSharedAudioStartFrames;
         }
 
         track = new RecordTrack(this, client, attr, sampleRate,
                       format, channelMask, frameCount,
                       nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid,
-                      checkedIdentity, *flags, TrackBase::TYPE_DEFAULT, portId, startTimeMs);
+                      checkedIdentity, *flags, TrackBase::TYPE_DEFAULT, portId, startFrames);
 
         lStatus = track->initCheck();
         if (lStatus != NO_ERROR) {
@@ -8200,17 +8221,32 @@
     if ((hasAudioSession_l(sharedSessionId) & ThreadBase::TRACK_SESSION) == 0) {
         return BAD_VALUE;
     }
-    if (sharedAudioStartMs < 0 || sharedAudioStartMs * mSampleRate / 1000 > mRsmpInRear) {
+
+    if (sharedAudioStartMs < 0
+        || sharedAudioStartMs > INT64_MAX / mSampleRate) {
         return BAD_VALUE;
     }
 
+    // Current implementation of the input resampling buffer wraps around indexes at 32 bit.
+    // As we cannot detect more than one wraparound, only accept values up current write position
+    // after one wraparound
+    // We assume recent wraparounds on mRsmpInRear only given it is unlikely that the requesting
+    // app waits several hours after the start time was computed.
+    const int64_t sharedAudioStartFrames = sharedAudioStartMs * mSampleRate / 1000;
+    const int32_t sharedOffset = audio_utils::safe_sub_overflow(mRsmpInRear,
+          (int32_t)sharedAudioStartFrames);
+    if (sharedOffset < 0
+          || sharedOffset > mRsmpInFrames) {
+      return BAD_VALUE;
+    }
+
     mSharedAudioPackageName = sharedAudioPackageName;
     if (mSharedAudioPackageName.empty()) {
         mSharedAudioSessionId = AUDIO_SESSION_NONE;
-        mSharedAudioStartMs = -1;
+        mSharedAudioStartFrames = -1;
     } else {
         mSharedAudioSessionId = sharedSessionId;
-        mSharedAudioStartMs = sharedAudioStartMs;
+        mSharedAudioStartFrames = (int32_t)sharedAudioStartFrames;
     }
     return NO_ERROR;
 }
@@ -8357,14 +8393,14 @@
     mRsmpInUnrel = 0;
     const int32_t rear = recordThread->mRsmpInRear;
     ssize_t deltaFrames = 0;
-    if (mRecordTrack->startTimeMs() >= 0) {
-        int32_t startFrames = mRecordTrack->startTimeMs() * recordThread->sampleRate()  / 1000;
-        // start frame has to be in the past
-        //TODO: b/185972521 fix in case rear or startFrames wrap around
-        if (startFrames > rear) {
-            startFrames = rear;
+    if (mRecordTrack->startFrames() >= 0) {
+        int32_t startFrames = mRecordTrack->startFrames();
+        // Accept a recent wraparound of mRsmpInRear
+        if (startFrames <= rear) {
+            deltaFrames = rear - startFrames;
+        } else {
+            deltaFrames = (int32_t)((int64_t)rear + UINT32_MAX + 1 - startFrames);
         }
-        deltaFrames = rear - startFrames;
         // start frame cannot be further in the past than start of resampling buffer
         if ((size_t) deltaFrames > recordThread->mRsmpInFrames) {
             deltaFrames = recordThread->mRsmpInFrames;
@@ -8826,17 +8862,22 @@
     if (mTracks.size() == 0) {
         return 0;
     }
-    //TODO: b/185972521 fix in case of wrap around on one track:
-    //  want the max(rear - front) for all tracks.
-    int32_t front = INT_MAX;
+    int32_t oldestFront = mRsmpInRear;
+    int32_t maxFilled = 0;
     for (size_t i = 0; i < mTracks.size(); i++) {
-        front = std::min(front, mTracks[i]->mResamplerBufferProvider->getFront());
+        int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
+        int32_t filled;
+        if (front <= mRsmpInRear) {
+            filled = mRsmpInRear - front;
+        } else {
+            filled = (int32_t)((int64_t)mRsmpInRear + UINT32_MAX + 1 - front);
+        }
+        if (filled > maxFilled) {
+            oldestFront = front;
+            maxFilled = filled;
+        }
     }
-    // discard any audio past the buffer size
-    if (audio_utils::safe_add_overflow(front, (int32_t)mRsmpInFrames) < mRsmpInRear) {
-        front = audio_utils::safe_sub_overflow(mRsmpInRear, (int32_t)mRsmpInFrames);
-    }
-    return front;
+    return oldestFront;
 }
 
 void AudioFlinger::RecordThread::updateFronts_l(int32_t offset)
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 03ed6fd..b6f7f24 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1863,7 +1863,7 @@
             DeviceDescriptorBaseVector          mOutDevices;
 
             std::string                         mSharedAudioPackageName = {};
-            long                                mSharedAudioStartMs = 0;
+            int32_t                             mSharedAudioStartFrames = -1;
             audio_session_t                     mSharedAudioSessionId = AUDIO_SESSION_NONE;
 };
 
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 6549236..3e04804 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2378,7 +2378,7 @@
             audio_input_flags_t flags,
             track_type type,
             audio_port_handle_t portId,
-            int64_t startTimeMs)
+            int32_t startFrames)
     :   TrackBase(thread, client, attr, sampleRate, format,
                   channelMask, frameCount, buffer, bufferSize, sessionId,
                   creatorPid,
@@ -2396,7 +2396,7 @@
         mFlags(flags),
         mSilenced(false),
         mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(identity, attr)),
-        mStartTimeMs(startTimeMs)
+        mStartFrames(startFrames)
 {
     if (mCblk == NULL) {
         return;
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index 4539ad5..2cfdf24 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -294,6 +294,12 @@
         metrics_proto.set_video_input_frames(inputFrames);
     }
 
+    // android.media.mediacodec.original.bitrate
+    int32_t originalBitrate = -1;
+    if ( item->getInt32("android.media.mediacodec.original.bitrate", &originalBitrate)) {
+        metrics_proto.set_original_bitrate(originalBitrate);
+    }
+
     std::string serialized;
     if (!metrics_proto.SerializeToString(&serialized)) {
         ALOGE("Failed to serialize codec metrics");