Merge "transcoding: Adding TranscodingJobStats for benchmarking."
diff --git a/apex/testing/test_manifest.json b/apex/testing/test_manifest.json
index ddd642e..e1295a2 100644
--- a/apex/testing/test_manifest.json
+++ b/apex/testing/test_manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.media",
-  "version": 300000000
+  "version": 2147483647
 }
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index 4db94f5..2e85915 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -293,6 +293,30 @@
     return OK;
 }
 
+static void MaybeLogTimestampWarning(
+        long long lastFrameEndTimestampUs, long long inputTimestampUs) {
+    using Clock = std::chrono::steady_clock;
+    thread_local Clock::time_point sLastLogTimestamp{};
+    thread_local int32_t sOverlapCount = -1;
+    if (Clock::now() - sLastLogTimestamp > std::chrono::minutes(1) || sOverlapCount < 0) {
+        AString countMessage = "";
+        if (sOverlapCount > 0) {
+            countMessage = AStringPrintf(
+                    "(%d overlapping timestamp detected since last log)", sOverlapCount);
+        }
+        ALOGI("Correcting overlapping timestamp: last frame ended at %lldus but "
+                "current frame is starting at %lldus. Using the last frame's end timestamp %s",
+                lastFrameEndTimestampUs, inputTimestampUs, countMessage.c_str());
+        sLastLogTimestamp = Clock::now();
+        sOverlapCount = 0;
+    } else {
+        ALOGV("Correcting overlapping timestamp: last frame ended at %lldus but "
+                "current frame is starting at %lldus. Using the last frame's end timestamp",
+                lastFrameEndTimestampUs, inputTimestampUs);
+        ++sOverlapCount;
+    }
+}
+
 void C2SoftAacEnc::process(
         const std::unique_ptr<C2Work> &work,
         const std::shared_ptr<C2BlockPool> &pool) {
@@ -366,9 +390,7 @@
     }
     c2_cntr64_t inputTimestampUs = work->input.ordinal.timestamp;
     if (inputTimestampUs < mLastFrameEndTimestampUs.value_or(inputTimestampUs)) {
-        ALOGW("Correcting overlapping timestamp: last frame ended at %lldus but "
-              "current frame is starting at %lldus. Using the last frame's end timestamp",
-              mLastFrameEndTimestampUs->peekll(), inputTimestampUs.peekll());
+        MaybeLogTimestampWarning(mLastFrameEndTimestampUs->peekll(), inputTimestampUs.peekll());
         inputTimestampUs = *mLastFrameEndTimestampUs;
     }
     if (capacity > 0) {
diff --git a/media/extractors/aac/Android.bp b/media/extractors/aac/Android.bp
index 60d3ae1..c036bb5 100644
--- a/media/extractors/aac/Android.bp
+++ b/media/extractors/aac/Android.bp
@@ -10,4 +10,11 @@
         "libutils",
     ],
 
+    host_supported: true,
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 826c1a0..2593000 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -21,4 +21,12 @@
         "libutils",
     ],
 
+    host_supported: true,
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+
 }
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index 7ad8cc1..330d4fe 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -21,4 +21,12 @@
         "libutils",
     ],
 
+    host_supported: true,
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+
 }
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index 102ac81..7d70548 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -13,4 +13,11 @@
         "libstagefright_foundation",
     ],
 
+    host_supported: true,
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 1d828df..7d16fb4 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -150,6 +150,7 @@
 
     bool mIsHeif;
     bool mIsAudio;
+    bool mIsUsac = false;
     sp<ItemTable> mItemTable;
 
     /* Shift start offset (move to earlier time) when media_time > 0,
@@ -4511,7 +4512,7 @@
     //AOT_SLS              = 38, /**< SLS                                       */
     //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
 
-    //AOT_USAC             = 42, /**< USAC                                      */
+    AOT_USAC               = 42, /**< USAC                                      */
     //AOT_SAOC             = 43, /**< SAOC                                      */
     //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
 
@@ -4659,7 +4660,7 @@
     ABitReader br(csd, csd_size);
     uint32_t objectType = br.getBits(5);
 
-    if (objectType == 31) {  // AAC-ELD => additional 6 bits
+    if (objectType == AOT_ESCAPE) {  // AAC-ELD => additional 6 bits
         objectType = 32 + br.getBits(6);
     }
 
@@ -5035,6 +5036,12 @@
     mIsPcm = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW);
     mIsAudio = !strncasecmp(mime, "audio/", 6);
 
+    int32_t aacObjectType = -1;
+
+    if (AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_AAC_PROFILE, &aacObjectType)) {
+        mIsUsac = (aacObjectType == AOT_USAC);
+    }
+
     if (mIsPcm) {
         int32_t numChannels = 0;
         int32_t bitsPerSample = 0;
@@ -6028,10 +6035,10 @@
             }
 
             uint32_t syncSampleIndex = sampleIndex;
-            // assume every audio sample is a sync sample. This works around
+            // assume every non-USAC 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) {
+            if (err == OK && (!mIsAudio || mIsUsac)) {
                 err = mSampleTable->findSyncSampleNear(
                         sampleIndex, &syncSampleIndex, findFlags);
             }
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index 7aed683..579065e 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -20,4 +20,11 @@
         "libvorbisidec",
     ],
 
+    host_supported: true,
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
diff --git a/media/extractors/tests/ExtractorUnitTest.cpp b/media/extractors/tests/ExtractorUnitTest.cpp
index a18b122..13d4cf6 100644
--- a/media/extractors/tests/ExtractorUnitTest.cpp
+++ b/media/extractors/tests/ExtractorUnitTest.cpp
@@ -50,8 +50,29 @@
 constexpr int32_t kRandomSeed = 700;
 constexpr int32_t kUndefined = -1;
 
+enum inputID {
+    // audio streams
+    AAC_1,
+    AMR_NB_1,
+    AMR_WB_1,
+    FLAC_1,
+    GSM_1,
+    MIDI_1,
+    MP3_1,
+    OPUS_1,
+    VORBIS_1,
+    // video streams
+    HEVC_1,
+    MPEG2_PS_1,
+    MPEG2_TS_1,
+    MPEG4_1,
+    VP9_1,
+    UNKNOWN_ID,
+};
+
 // LookUpTable of clips and metadata for component testing
 static const struct InputData {
+    inputID inpId;
     string mime;
     string inputFile;
     int32_t firstParam;
@@ -59,26 +80,34 @@
     int32_t profile;
     int32_t frameRate;
 } kInputData[] = {
-        {MEDIA_MIMETYPE_AUDIO_AAC, "test_mono_44100Hz_aac.aac", 44100, 1, AACObjectLC, kUndefined},
-        {MEDIA_MIMETYPE_AUDIO_AMR_NB, "bbb_mono_8kHz_amrnb.amr", 8000, 1, kUndefined, kUndefined},
-        {MEDIA_MIMETYPE_AUDIO_AMR_WB, "bbb_mono_16kHz_amrwb.amr", 16000, 1, kUndefined, kUndefined},
-        {MEDIA_MIMETYPE_AUDIO_VORBIS, "bbb_stereo_48kHz_vorbis.ogg", 48000, 2, kUndefined,
+        {AAC_1, MEDIA_MIMETYPE_AUDIO_AAC, "test_mono_44100Hz_aac.aac", 44100, 1, AACObjectLC,
          kUndefined},
-        {MEDIA_MIMETYPE_AUDIO_MSGSM, "test_mono_8kHz_gsm.wav", 8000, 1, kUndefined, kUndefined},
-        {MEDIA_MIMETYPE_AUDIO_RAW, "bbb_stereo_48kHz_flac.flac", 48000, 2, kUndefined, kUndefined},
-        {MEDIA_MIMETYPE_AUDIO_OPUS, "test_stereo_48kHz_opus.opus", 48000, 2, kUndefined,
+        {AMR_NB_1, MEDIA_MIMETYPE_AUDIO_AMR_NB, "bbb_mono_8kHz_amrnb.amr", 8000, 1, kUndefined,
          kUndefined},
-        {MEDIA_MIMETYPE_AUDIO_MPEG, "bbb_stereo_48kHz_mp3.mp3", 48000, 2, kUndefined, kUndefined},
-        {MEDIA_MIMETYPE_AUDIO_RAW, "midi_a.mid", 22050, 2, kUndefined, kUndefined},
-        {MEDIA_MIMETYPE_VIDEO_MPEG2, "bbb_cif_768kbps_30fps_mpeg2.ts", 352, 288, MPEG2ProfileMain,
-         30},
-        {MEDIA_MIMETYPE_VIDEO_MPEG4, "bbb_cif_768kbps_30fps_mpeg4.mkv", 352, 288,
-         MPEG4ProfileSimple, 30},
+        {AMR_WB_1, MEDIA_MIMETYPE_AUDIO_AMR_WB, "bbb_mono_16kHz_amrwb.amr", 16000, 1, kUndefined,
+         kUndefined},
+        {FLAC_1, MEDIA_MIMETYPE_AUDIO_RAW, "bbb_stereo_48kHz_flac.flac", 48000, 2, kUndefined,
+         kUndefined},
+        {GSM_1, MEDIA_MIMETYPE_AUDIO_MSGSM, "test_mono_8kHz_gsm.wav", 8000, 1, kUndefined,
+         kUndefined},
+        {MIDI_1, MEDIA_MIMETYPE_AUDIO_RAW, "midi_a.mid", 22050, 2, kUndefined, kUndefined},
+        {MP3_1, MEDIA_MIMETYPE_AUDIO_MPEG, "bbb_stereo_48kHz_mp3.mp3", 48000, 2, kUndefined,
+         kUndefined},
+        {OPUS_1, MEDIA_MIMETYPE_AUDIO_OPUS, "test_stereo_48kHz_opus.opus", 48000, 2, kUndefined,
+         kUndefined},
+        {VORBIS_1, MEDIA_MIMETYPE_AUDIO_VORBIS, "bbb_stereo_48kHz_vorbis.ogg", 48000, 2, kUndefined,
+         kUndefined},
+
         // Test (b/151677264) for MP4 extractor
-        {MEDIA_MIMETYPE_VIDEO_HEVC, "crowd_508x240_25fps_hevc.mp4", 508, 240, HEVCProfileMain,
-         25},
-        {MEDIA_MIMETYPE_VIDEO_VP9, "bbb_340x280_30fps_vp9.webm", 340, 280, VP9Profile0, 30},
-        {MEDIA_MIMETYPE_VIDEO_MPEG2, "swirl_144x136_mpeg2.mpg", 144, 136, MPEG2ProfileMain, 12},
+        {HEVC_1, MEDIA_MIMETYPE_VIDEO_HEVC, "crowd_508x240_25fps_hevc.mp4", 508, 240,
+         HEVCProfileMain, 25},
+        {MPEG2_PS_1, MEDIA_MIMETYPE_VIDEO_MPEG2, "swirl_144x136_mpeg2.mpg", 144, 136,
+         MPEG2ProfileMain, 12},
+        {MPEG2_TS_1, MEDIA_MIMETYPE_VIDEO_MPEG2, "bbb_cif_768kbps_30fps_mpeg2.ts", 352, 288,
+         MPEG2ProfileMain, 30},
+        {MPEG4_1, MEDIA_MIMETYPE_VIDEO_MPEG4, "bbb_cif_768kbps_30fps_mpeg4.mkv", 352, 288,
+         MPEG4ProfileSimple, 30},
+        {VP9_1, MEDIA_MIMETYPE_VIDEO_VP9, "bbb_340x280_30fps_vp9.webm", 340, 280, VP9Profile0, 30},
 };
 
 static ExtractorUnitTestEnvironment *gEnv = nullptr;
@@ -148,14 +177,23 @@
     MediaExtractorPluginHelper *mExtractor;
 };
 
-class ExtractorFunctionalityTest : public ExtractorUnitTest,
-                                   public ::testing::TestWithParam<pair<string, string>> {
+class ExtractorFunctionalityTest
+    : public ExtractorUnitTest,
+      public ::testing::TestWithParam<tuple<string /* container */, string /* InputFile */,
+                                            int32_t /* numTracks */, bool /* seekSupported */>> {
   public:
-    virtual void SetUp() override { setupExtractor(GetParam().first); }
+    virtual void SetUp() override {
+        tuple<string, string, int32_t, bool> params = GetParam();
+        mContainer = get<0>(params);
+        mNumTracks = get<2>(params);
+        setupExtractor(mContainer);
+    }
+    string mContainer;
+    int32_t mNumTracks;
 };
 
 class ConfigParamTest : public ExtractorUnitTest,
-                        public ::testing::TestWithParam<pair<string, int32_t>> {
+                        public ::testing::TestWithParam<pair<string, inputID>> {
   public:
     virtual void SetUp() override { setupExtractor(GetParam().first); }
 
@@ -169,7 +207,7 @@
         int32_t frameRate;
     };
 
-    void getFileProperties(int32_t inputIdx, string &inputFile, configFormat &configParam);
+    void getFileProperties(inputID inputId, string &inputFile, configFormat &configParam);
 };
 
 int32_t ExtractorUnitTest::setDataSource(string inputFileName) {
@@ -228,9 +266,16 @@
     return 0;
 }
 
-void ConfigParamTest::getFileProperties(int32_t inputIdx, string &inputFile,
+void ConfigParamTest::getFileProperties(inputID inputId, string &inputFile,
                                         configFormat &configParam) {
-    if (inputIdx >= sizeof(kInputData) / sizeof(kInputData[0])) {
+    int32_t inputDataSize = sizeof(kInputData) / sizeof(kInputData[0]);
+    int32_t inputIdx = 0;
+    for (; inputIdx < inputDataSize; inputIdx++) {
+        if (inputId == kInputData[inputIdx].inpId) {
+            break;
+        }
+    }
+    if (inputIdx == inputDataSize) {
         return;
     }
     inputFile += kInputData[inputIdx].inputFile;
@@ -316,16 +361,17 @@
     if (mDisableTest) return;
 
     ALOGV("Checks if a valid extractor is created for a given input file");
-    string inputFileName = gEnv->getRes() + GetParam().second;
+    string inputFileName = gEnv->getRes() + get<1>(GetParam());
 
-    ASSERT_EQ(setDataSource(inputFileName), 0)
-            << "SetDataSource failed for" << GetParam().first << "extractor";
+    int32_t status = setDataSource(inputFileName);
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
 
-    ASSERT_EQ(createExtractor(), 0)
-            << "Extractor creation failed for" << GetParam().first << "extractor";
+    status = createExtractor();
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
 
-    // A valid extractor instace should return success for following calls
-    ASSERT_GT(mExtractor->countTracks(), 0);
+    int32_t numTracks = mExtractor->countTracks();
+    ASSERT_EQ(numTracks, mNumTracks)
+            << "Extractor reported wrong number of track for the given clip";
 
     AMediaFormat *format = AMediaFormat_new();
     ASSERT_NE(format, nullptr) << "AMediaFormat_new returned null AMediaformat";
@@ -337,17 +383,18 @@
 TEST_P(ExtractorFunctionalityTest, ExtractorTest) {
     if (mDisableTest) return;
 
-    ALOGV("Validates %s Extractor for a given input file", GetParam().first.c_str());
-    string inputFileName = gEnv->getRes() + GetParam().second;
+    ALOGV("Validates %s Extractor for a given input file", mContainer.c_str());
+    string inputFileName = gEnv->getRes() + get<1>(GetParam());
 
     int32_t status = setDataSource(inputFileName);
-    ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
 
     status = createExtractor();
-    ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
 
     int32_t numTracks = mExtractor->countTracks();
-    ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+    ASSERT_EQ(numTracks, mNumTracks)
+            << "Extractor reported wrong number of track for the given clip";
 
     for (int32_t idx = 0; idx < numTracks; idx++) {
         MediaTrackHelper *track = mExtractor->getTrack(idx);
@@ -388,16 +435,17 @@
     if (mDisableTest) return;
 
     ALOGV("Validates Extractor's meta data for a given input file");
-    string inputFileName = gEnv->getRes() + GetParam().second;
+    string inputFileName = gEnv->getRes() + get<1>(GetParam());
 
     int32_t status = setDataSource(inputFileName);
-    ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
 
     status = createExtractor();
-    ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
 
     int32_t numTracks = mExtractor->countTracks();
-    ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+    ASSERT_EQ(numTracks, mNumTracks)
+            << "Extractor reported wrong number of track for the given clip";
 
     AMediaFormat *extractorFormat = AMediaFormat_new();
     ASSERT_NE(extractorFormat, nullptr) << "AMediaFormat_new returned null AMediaformat";
@@ -462,17 +510,18 @@
 TEST_P(ExtractorFunctionalityTest, MultipleStartStopTest) {
     if (mDisableTest) return;
 
-    ALOGV("Test %s extractor for multiple start and stop calls", GetParam().first.c_str());
-    string inputFileName = gEnv->getRes() + GetParam().second;
+    ALOGV("Test %s extractor for multiple start and stop calls", mContainer.c_str());
+    string inputFileName = gEnv->getRes() + get<1>(GetParam());
 
     int32_t status = setDataSource(inputFileName);
-    ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
 
     status = createExtractor();
-    ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
 
     int32_t numTracks = mExtractor->countTracks();
-    ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+    ASSERT_EQ(numTracks, mNumTracks)
+            << "Extractor reported wrong number of track for the given clip";
 
     // start/stop the tracks multiple times
     for (int32_t count = 0; count < kMaxCount; count++) {
@@ -504,22 +553,25 @@
 TEST_P(ExtractorFunctionalityTest, SeekTest) {
     if (mDisableTest) return;
 
-    ALOGV("Validates %s Extractor behaviour for different seek modes", GetParam().first.c_str());
-    string inputFileName = gEnv->getRes() + GetParam().second;
+    ALOGV("Validates %s Extractor behaviour for different seek modes", mContainer.c_str());
+    string inputFileName = gEnv->getRes() + get<1>(GetParam());
 
     int32_t status = setDataSource(inputFileName);
-    ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
 
     status = createExtractor();
-    ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
 
     int32_t numTracks = mExtractor->countTracks();
-    ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+    ASSERT_EQ(numTracks, mNumTracks)
+            << "Extractor reported wrong number of track for the given clip";
 
     uint32_t seekFlag = mExtractor->flags();
-    if (!(seekFlag & MediaExtractorPluginHelper::CAN_SEEK)) {
-        cout << "[   WARN   ] Test Skipped. " << GetParam().first
-             << " Extractor doesn't support seek\n";
+    bool seekSupported = get<3>(GetParam());
+    bool seekable = seekFlag & MediaExtractorPluginHelper::CAN_SEEK;
+    if (!seekable) {
+        ASSERT_FALSE(seekSupported) << mContainer << "Extractor is expected to support seek ";
+        cout << "[   WARN   ] Test Skipped. " << mContainer << " Extractor doesn't support seek\n";
         return;
     }
 
@@ -563,7 +615,7 @@
         // next/previous sync frames but not to samples between two sync frames.
         getSeekablePoints(seekablePoints, track);
         ASSERT_GT(seekablePoints.size(), 0)
-                << "Failed to get seekable points for " << GetParam().first << " extractor";
+                << "Failed to get seekable points for " << mContainer << " extractor";
 
         AMediaFormat *trackFormat = AMediaFormat_new();
         ASSERT_NE(trackFormat, nullptr) << "AMediaFormat_new returned null format";
@@ -664,23 +716,148 @@
     seekablePoints.clear();
 }
 
+// Tests the extractors for seek beyond range : (0, ClipDuration)
+TEST_P(ExtractorFunctionalityTest, MonkeySeekTest) {
+    if (mDisableTest) return;
+    // TODO(b/155630778): Enable test for wav extractors
+    if (mExtractorName == WAV) return;
+
+    ALOGV("Validates %s Extractor behaviour for invalid seek points", mContainer.c_str());
+    string inputFileName = gEnv->getRes() + get<1>(GetParam());
+
+    int32_t status = setDataSource(inputFileName);
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
+
+    status = createExtractor();
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
+
+    int32_t numTracks = mExtractor->countTracks();
+    ASSERT_EQ(numTracks, mNumTracks)
+            << "Extractor reported wrong number of track for the given clip";
+
+    uint32_t seekFlag = mExtractor->flags();
+    bool seekSupported = get<3>(GetParam());
+    bool seekable = seekFlag & MediaExtractorPluginHelper::CAN_SEEK;
+    if (!seekable) {
+        ASSERT_FALSE(seekSupported) << mContainer << "Extractor is expected to support seek ";
+        cout << "[   WARN   ] Test Skipped. " << mContainer << " Extractor doesn't support seek\n";
+        return;
+    }
+
+    for (int32_t idx = 0; idx < numTracks; idx++) {
+        MediaTrackHelper *track = mExtractor->getTrack(idx);
+        ASSERT_NE(track, nullptr) << "Failed to get track for index " << idx;
+
+        CMediaTrack *cTrack = wrap(track);
+        ASSERT_NE(cTrack, nullptr) << "Failed to get track wrapper for index " << idx;
+
+        MediaBufferGroup *bufferGroup = new MediaBufferGroup();
+        status = cTrack->start(track, bufferGroup->wrap());
+        ASSERT_EQ(OK, (media_status_t)status) << "Failed to start the track";
+
+        AMediaFormat *trackMeta = AMediaFormat_new();
+        ASSERT_NE(trackMeta, nullptr) << "AMediaFormat_new returned null AMediaformat";
+
+        status = mExtractor->getTrackMetaData(
+                trackMeta, idx, MediaExtractorPluginHelper::kIncludeExtensiveMetaData);
+        ASSERT_EQ(OK, (media_status_t)status) << "Failed to get trackMetaData";
+
+        int64_t clipDuration = 0;
+        AMediaFormat_getInt64(trackMeta, AMEDIAFORMAT_KEY_DURATION, &clipDuration);
+        ASSERT_GT(clipDuration, 0) << "Invalid clip duration ";
+        AMediaFormat_delete(trackMeta);
+
+        int64_t seekToTimeStampUs[] = {-clipDuration, clipDuration / 2, clipDuration,
+                                       clipDuration * 2};
+        for (int32_t mode = CMediaTrackReadOptions::SEEK_PREVIOUS_SYNC;
+             mode <= CMediaTrackReadOptions::SEEK_CLOSEST; mode++) {
+            for (int64_t seekTimeUs : seekToTimeStampUs) {
+                MediaTrackHelper::ReadOptions *options = new MediaTrackHelper::ReadOptions(
+                        mode | CMediaTrackReadOptions::SEEK, seekTimeUs);
+                ASSERT_NE(options, nullptr) << "Cannot create read option";
+
+                MediaBufferHelper *buffer = nullptr;
+                status = track->read(&buffer, options);
+                if (status == AMEDIA_ERROR_END_OF_STREAM) {
+                    delete options;
+                    continue;
+                }
+                if (buffer) {
+                    AMediaFormat *metaData = buffer->meta_data();
+                    int64_t timeStamp;
+                    AMediaFormat_getInt64(metaData, AMEDIAFORMAT_KEY_TIME_US, &timeStamp);
+                    ALOGV("Seeked to timestamp : %lld, requested : %lld", (long long)timeStamp,
+                          (long long)seekTimeUs);
+                    buffer->release();
+                }
+                delete options;
+            }
+        }
+        status = cTrack->stop(track);
+        ASSERT_EQ(OK, status) << "Failed to stop the track";
+        delete bufferGroup;
+        delete track;
+    }
+}
+
+// Tests extractors for invalid tracks
+TEST_P(ExtractorFunctionalityTest, SanityTest) {
+    if (mDisableTest) return;
+    // TODO(b/155626946): Enable test for MPEG2 TS/PS extractors
+    if (mExtractorName == MPEG2TS || mExtractorName == MPEG2PS) return;
+
+    ALOGV("Validates %s Extractor behaviour for invalid tracks", mContainer.c_str());
+    string inputFileName = gEnv->getRes() + get<1>(GetParam());
+
+    int32_t status = setDataSource(inputFileName);
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
+
+    status = createExtractor();
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
+
+    int32_t numTracks = mExtractor->countTracks();
+    ASSERT_EQ(numTracks, mNumTracks)
+            << "Extractor reported wrong number of track for the given clip";
+
+    int32_t trackIdx[] = {-1, numTracks};
+    for (int32_t idx : trackIdx) {
+        MediaTrackHelper *track = mExtractor->getTrack(idx);
+        ASSERT_EQ(track, nullptr) << "Failed to get track for index " << idx << "\n";
+
+        AMediaFormat *extractorFormat = AMediaFormat_new();
+        ASSERT_NE(extractorFormat, nullptr) << "AMediaFormat_new returned null AMediaformat";
+
+        status = mExtractor->getTrackMetaData(
+                extractorFormat, idx, MediaExtractorPluginHelper::kIncludeExtensiveMetaData);
+        ASSERT_NE(OK, status) << "getTrackMetaData should return error for invalid index " << idx;
+        AMediaFormat_delete(extractorFormat);
+    }
+
+    // Validate Extractor's getTrackMetaData for null format
+    AMediaFormat *mediaFormat = nullptr;
+    status = mExtractor->getTrackMetaData(mediaFormat, 0,
+                                          MediaExtractorPluginHelper::kIncludeExtensiveMetaData);
+    ASSERT_NE(OK, status) << "getTrackMetaData should return error for null Media format";
+}
+
 // This test validates config params for a given input file.
 // For this test we only take single track files since the focus of this test is
 // to validate the file properties reported by Extractor and not multi-track behavior
 TEST_P(ConfigParamTest, ConfigParamValidation) {
     if (mDisableTest) return;
 
-    ALOGV("Validates %s Extractor for input's file properties", GetParam().first.c_str());
+    string container = GetParam().first;
+    ALOGV("Validates %s Extractor for input's file properties", container.c_str());
     string inputFileName = gEnv->getRes();
-    int32_t inputFileIdx = GetParam().second;
+    inputID inputFileId = GetParam().second;
     configFormat configParam;
-    getFileProperties(inputFileIdx, inputFileName, configParam);
+    getFileProperties(inputFileId, inputFileName, configParam);
 
     int32_t status = setDataSource(inputFileName);
-    ASSERT_EQ(status, 0) << "SetDataSource failed for " << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "SetDataSource failed for " << container << "extractor";
 
     status = createExtractor();
-    ASSERT_EQ(status, 0) << "Extractor creation failed for " << GetParam().first << "extractor";
+    ASSERT_EQ(status, 0) << "Extractor creation failed for " << container << "extractor";
 
     int32_t numTracks = mExtractor->countTracks();
     ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
@@ -907,50 +1084,55 @@
                                            make_pair("loudsoftaac.aac", "loudsoftaac.mkv")));
 
 INSTANTIATE_TEST_SUITE_P(ConfigParamTestAll, ConfigParamTest,
-                         ::testing::Values(make_pair("aac", 0),
-                                           make_pair("amr", 1),
-                                           make_pair("amr", 2),
-                                           make_pair("ogg", 3),
-                                           make_pair("wav", 4),
-                                           make_pair("flac", 5),
-                                           make_pair("ogg", 6),
-                                           make_pair("mp3", 7),
-                                           make_pair("midi", 8),
-                                           make_pair("mpeg2ts", 9),
-                                           make_pair("mkv", 10),
-                                           make_pair("mpeg4", 11),
-                                           make_pair("mkv", 12),
-                                           make_pair("mpeg2ps", 13)));
+                         ::testing::Values(make_pair("aac", AAC_1),
+                                           make_pair("amr", AMR_NB_1),
+                                           make_pair("amr", AMR_WB_1),
+                                           make_pair("flac", FLAC_1),
+                                           make_pair("wav", GSM_1),
+                                           make_pair("midi", MIDI_1),
+                                           make_pair("mp3", MP3_1),
+                                           make_pair("ogg", OPUS_1),
+                                           make_pair("ogg", VORBIS_1),
 
-INSTANTIATE_TEST_SUITE_P(ExtractorUnitTestAll, ExtractorFunctionalityTest,
-                         ::testing::Values(make_pair("aac", "loudsoftaac.aac"),
-                                           make_pair("amr", "testamr.amr"),
-                                           make_pair("amr", "amrwb.wav"),
-                                           make_pair("ogg", "john_cage.ogg"),
-                                           make_pair("wav", "monotestgsm.wav"),
-                                           make_pair("mpeg2ts", "segment000001.ts"),
-                                           make_pair("mpeg2ts", "testac3ts.ts"),
-                                           make_pair("mpeg2ts", "testac4ts.ts"),
-                                           make_pair("mpeg2ts", "testeac3ts.ts"),
-                                           make_pair("flac", "sinesweepflac.flac"),
-                                           make_pair("ogg", "testopus.opus"),
-                                           make_pair("ogg", "sinesweepoggalbumart.ogg"),
-                                           make_pair("midi", "midi_a.mid"),
-                                           make_pair("mkv", "sinesweepvorbis.mkv"),
-                                           make_pair("mkv", "sinesweepmp3lame.mkv"),
-                                           make_pair("mkv", "loudsoftaac.mkv"),
-                                           make_pair("mpeg4", "sinesweepoggmp4.mp4"),
-                                           make_pair("mp3", "sinesweepmp3lame.mp3"),
-                                           make_pair("mp3", "id3test10.mp3"),
-                                           make_pair("mkv", "swirl_144x136_vp9.webm"),
-                                           make_pair("mkv", "swirl_144x136_vp8.webm"),
-                                           make_pair("mkv", "swirl_144x136_avc.mkv"),
-                                           make_pair("mkv", "withoutcues.mkv"),
-                                           make_pair("mpeg2ps", "swirl_144x136_mpeg2.mpg"),
-                                           make_pair("mpeg2ps", "programstream.mpeg"),
-                                           make_pair("mpeg4", "testac3mp4.mp4"),
-                                           make_pair("mpeg4", "testeac3mp4.mp4"),
-                                           make_pair("mpeg4", "swirl_132x130_mpeg4.mp4")));
+                                           make_pair("mpeg4", HEVC_1),
+                                           make_pair("mpeg2ps", MPEG2_PS_1),
+                                           make_pair("mpeg2ts", MPEG2_TS_1),
+                                           make_pair("mkv", MPEG4_1),
+                                           make_pair("mkv", VP9_1)));
+
+// Validate extractors for container format, input file and supports seek flag
+INSTANTIATE_TEST_SUITE_P(
+        ExtractorUnitTestAll, ExtractorFunctionalityTest,
+        ::testing::Values(
+                make_tuple("aac", "loudsoftaac.aac", 1, true),
+                make_tuple("amr", "testamr.amr", 1, true),
+                make_tuple("amr", "amrwb.wav", 1, true),
+                make_tuple("flac", "sinesweepflac.flac", 1, true),
+                make_tuple("midi", "midi_a.mid", 1, true),
+                make_tuple("mkv", "sinesweepvorbis.mkv", 1, true),
+                make_tuple("mkv", "sinesweepmp3lame.mkv", 1, true),
+                make_tuple("mkv", "loudsoftaac.mkv", 1, true),
+                make_tuple("mp3", "sinesweepmp3lame.mp3", 1, true),
+                make_tuple("mp3", "id3test10.mp3", 1, true),
+                make_tuple("mpeg2ts", "segment000001.ts", 2, false),
+                make_tuple("mpeg2ts", "testac3ts.ts", 1, false),
+                make_tuple("mpeg2ts", "testac4ts.ts", 1, false),
+                make_tuple("mpeg2ts", "testeac3ts.ts", 1, false),
+                make_tuple("mpeg4", "sinesweepoggmp4.mp4", 1, true),
+                make_tuple("mpeg4", "testac3mp4.mp4", 1, true),
+                make_tuple("mpeg4", "testeac3mp4.mp4", 1, true),
+                make_tuple("ogg", "john_cage.ogg", 1, true),
+                make_tuple("ogg", "testopus.opus", 1, true),
+                make_tuple("ogg", "sinesweepoggalbumart.ogg", 1, true),
+                make_tuple("wav", "monotestgsm.wav", 1, true),
+
+                make_tuple("mkv", "swirl_144x136_avc.mkv", 1, true),
+                make_tuple("mkv", "withoutcues.mkv", 2, true),
+                make_tuple("mkv", "swirl_144x136_vp9.webm", 1, true),
+                make_tuple("mkv", "swirl_144x136_vp8.webm", 1, true),
+                make_tuple("mpeg2ps", "swirl_144x136_mpeg2.mpg", 1, false),
+                make_tuple("mpeg2ps", "programstream.mpeg", 2, false),
+                make_tuple("mpeg4", "swirl_132x130_mpeg4.mp4", 1, true)));
 
 int main(int argc, char **argv) {
     gEnv = new ExtractorUnitTestEnvironment();
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index bc973bd..2699dfe 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -314,8 +314,11 @@
 
 void AudioStream::setState(aaudio_stream_state_t state) {
     ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
+    if (state == mState) {
+        return; // no change
+    }
     // Track transition to DISCONNECTED state.
-    if (state == AAUDIO_STREAM_STATE_DISCONNECTED && mState != state) {
+    if (state == AAUDIO_STREAM_STATE_DISCONNECTED) {
         android::mediametrics::LogItem(mMetricsId)
                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
                 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
@@ -323,18 +326,18 @@
     }
     // CLOSED is a final state
     if (mState == AAUDIO_STREAM_STATE_CLOSED) {
-        ALOGE("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
+        ALOGW("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
 
     // Once CLOSING, we can only move to CLOSED state.
     } else if (mState == AAUDIO_STREAM_STATE_CLOSING
                && state != AAUDIO_STREAM_STATE_CLOSED) {
-        ALOGE("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
+        ALOGW("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
 
     // Once DISCONNECTED, we can only move to CLOSING or CLOSED state.
     } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
                && !(state == AAUDIO_STREAM_STATE_CLOSING
                    || state == AAUDIO_STREAM_STATE_CLOSED)) {
-        ALOGE("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
+        ALOGW("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
 
     } else {
         mState = state;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 6e5110f..d50a74b 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -212,9 +212,6 @@
     setSamplesPerFrame(mAudioRecord->channelCount());
 
     int32_t actualSampleRate = mAudioRecord->getSampleRate();
-    ALOGW_IF(actualSampleRate != getSampleRate(),
-             "open() sampleRate changed from %d to %d",
-             getSampleRate(), actualSampleRate);
     setSampleRate(actualSampleRate);
 
     // We may need to pass the data through a block size adapter to guarantee constant size.
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index ea08361..74292dd 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -195,9 +195,6 @@
     setDeviceFormat(mAudioTrack->format());
 
     int32_t actualSampleRate = mAudioTrack->getSampleRate();
-    ALOGW_IF(actualSampleRate != getSampleRate(),
-             "open() sampleRate changed from %d to %d",
-             getSampleRate(), actualSampleRate);
     setSampleRate(actualSampleRate);
 
     // We may need to pass the data through a block size adapter to guarantee constant size.
@@ -240,11 +237,11 @@
 
     setSharingMode(AAUDIO_SHARING_MODE_SHARED); // EXCLUSIVE mode not supported in legacy
 
-    // Log warning if we did not get what we asked for.
-    ALOGW_IF(actualFlags != flags,
+    // Log if we did not get what we asked for.
+    ALOGD_IF(actualFlags != flags,
              "open() flags changed from 0x%08X to 0x%08X",
              flags, actualFlags);
-    ALOGW_IF(actualPerformanceMode != perfMode,
+    ALOGD_IF(actualPerformanceMode != perfMode,
              "open() perfMode changed from %d to %d",
              perfMode, actualPerformanceMode);
 
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index c87635f..16cd0ad 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -8,12 +8,6 @@
 
     srcs: ["PreProcessing.cpp"],
 
-    include_dirs: [
-        "external/webrtc",
-        "external/webrtc/webrtc/modules/include",
-        "external/webrtc/webrtc/modules/audio_processing/include",
-    ],
-
     shared_libs: [
         "libwebrtc_audio_preprocessing",
         "libspeexresampler",
diff --git a/media/libmediatranscoding/tests/assets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4 b/media/libmediatranscoding/tests/assets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
new file mode 100644
index 0000000..df42a15
--- /dev/null
+++ b/media/libmediatranscoding/tests/assets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/push_assets.sh b/media/libmediatranscoding/tests/assets/push_assets.sh
index 2fcb233..8c85e58 100755
--- a/media/libmediatranscoding/tests/assets/push_assets.sh
+++ b/media/libmediatranscoding/tests/assets/push_assets.sh
@@ -21,5 +21,5 @@
 
 #TODO(hkuang): Check if the destination folder already exists. If so, skip the copying.
 echo "Copying files to device"
-adb push $ANDROID_BUILD_TOP/frameworks/av/media/libmediatranscoding/tests/assets /data/local/tmp/TranscodingTestAssets
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libmediatranscoding/tests/assets/* /data/local/tmp/TranscodingTestAssets
 echo "Copy done"
diff --git a/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp b/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp
index aaa2adb..0fdb0b7 100644
--- a/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp
+++ b/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp
@@ -26,7 +26,19 @@
 class DefaultMuxer : public MediaSampleWriterMuxerInterface {
 public:
     // MediaSampleWriterMuxerInterface
-    ssize_t addTrack(const AMediaFormat* trackFormat) override {
+    ssize_t addTrack(AMediaFormat* trackFormat) override {
+        // If the track format has rotation, need to call AMediaMuxer_setOrientationHint
+        // to set the rotation. Muxer doesn't take rotation specified on the track.
+        const char* mime;
+        if (AMediaFormat_getString(trackFormat, AMEDIAFORMAT_KEY_MIME, &mime) &&
+            strncmp(mime, "video/", 6) == 0) {
+            int32_t rotation;
+            if (AMediaFormat_getInt32(trackFormat, AMEDIAFORMAT_KEY_ROTATION, &rotation) &&
+                (rotation != 0)) {
+                AMediaMuxer_setOrientationHint(mMuxer, rotation);
+            }
+        }
+
         return AMediaMuxer_addTrack(mMuxer, trackFormat);
     }
     media_status_t start() override { return AMediaMuxer_start(mMuxer); }
@@ -213,4 +225,4 @@
 
     return AMEDIA_OK;
 }
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index 96e2e61..4df3296 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -139,6 +139,10 @@
     }
     AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, kColorFormatSurface);
 
+    // Always encode without rotation. The rotation degree will be transferred directly to
+    // MediaSampleWriter track format, and MediaSampleWriter will call AMediaMuxer_setOrientationHint.
+    AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_ROTATION, 0);
+
     mDestinationFormat = std::shared_ptr<AMediaFormat>(encoderFormat, &AMediaFormat_delete);
 
     // Create and configure the encoder.
@@ -339,25 +343,35 @@
     // at container level. This is supposed to override any SAR settings in the bitstream,
     // thus should always be transferred to the container of the transcoded file.
     int32_t sarWidth, sarHeight;
-    if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_WIDTH, &sarWidth) &&
+    if (AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_SAR_WIDTH, &sarWidth) &&
         (sarWidth > 0) &&
-        AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_HEIGHT, &sarHeight) &&
+        AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_SAR_HEIGHT, &sarHeight) &&
         (sarHeight > 0)) {
         AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_WIDTH, sarWidth);
         AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_HEIGHT, sarHeight);
     }
     // Transfer DAR settings.
     int32_t displayWidth, displayHeight;
-    if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_WIDTH,
-                              &displayWidth) &&
+    if (AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_WIDTH, &displayWidth) &&
         (displayWidth > 0) &&
-        AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_HEIGHT,
+        AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_HEIGHT,
                               &displayHeight) &&
         (displayHeight > 0)) {
         AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_WIDTH, displayWidth);
         AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, displayHeight);
     }
 
+    // Transfer rotation settings.
+    // Note that muxer itself doesn't take rotation from the track format. It requires
+    // AMediaMuxer_setOrientationHint to set the rotation. Here we pass the rotation to
+    // MediaSampleWriter using the track format. MediaSampleWriter will then call
+    // AMediaMuxer_setOrientationHint as needed.
+    int32_t rotation;
+    if (AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_ROTATION, &rotation) &&
+        (rotation != 0)) {
+        AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_ROTATION, rotation);
+    }
+
     // TODO: transfer other fields as required.
 
     mActualOutputFormat = std::shared_ptr<AMediaFormat>(formatCopy, &AMediaFormat_delete);
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h b/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
index 4d0264b..da83167 100644
--- a/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
+++ b/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
@@ -41,7 +41,7 @@
      * @param trackFormat Format of the new track.
      * @return A non-negative track index on success, or a negative number on failure.
      */
-    virtual ssize_t addTrack(const AMediaFormat* trackFormat) = 0;
+    virtual ssize_t addTrack(AMediaFormat* trackFormat) = 0;
 
     /** Starts the muxer. */
     virtual media_status_t start() = 0;
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
index 9ffb32b..98813e7 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
@@ -58,7 +58,7 @@
 class TestMuxer : public MediaSampleWriterMuxerInterface {
 public:
     // MuxerInterface
-    ssize_t addTrack(const AMediaFormat* trackFormat) override {
+    ssize_t addTrack(AMediaFormat* trackFormat) override {
         mEventQueue.push_back(AddTrack(trackFormat));
         return mTrackCount++;
     }
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
index 4d9386a..71d3a4e 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
@@ -67,7 +67,7 @@
 
     void initSampleReader() {
         const char* sourcePath =
-                "/data/local/tmp/TranscoderTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
+                "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
 
         const int sourceFd = open(sourcePath, O_RDONLY);
         ASSERT_GT(sourceFd, 0);
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
index 6bf6562..67f1ca1 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
@@ -40,7 +40,7 @@
 
 struct FormatVerifierEntry {
     const char* key;
-    bool (*equal)(const char* key, AMediaFormat* src, AMediaFormat* dst);
+    std::function<bool(const char*, AMediaFormat*, AMediaFormat*)> equal;
 };
 
 static const FormatVerifierEntry kFieldsToPreserve[] = {
@@ -92,11 +92,6 @@
     bool mFinished = false;
 };
 
-static const char* SOURCE_PATH_AVC =
-        "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
-static const char* SOURCE_PATH_HEVC =
-        "/data/local/tmp/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4";
-
 // Write-only, create file if non-existent, don't overwrite existing file.
 static constexpr int kOpenFlags = O_WRONLY | O_CREAT | O_EXCL;
 // User R+W permission.
@@ -161,6 +156,44 @@
         return mCallbacks->mStatus;
     }
 
+    void testTranscodeVideo(const char* srcPath, const char* destPath, const char* dstMime) {
+        const int32_t kBitRate = 8 * 1000 * 1000;  // 8Mbs
+
+        EXPECT_EQ(
+                transcodeHelper(
+                        srcPath, destPath,
+                        [dstMime](AMediaFormat* sourceFormat) {
+                            AMediaFormat* format = nullptr;
+                            const char* mime = nullptr;
+                            AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
+
+                            if (strncmp(mime, "video/", 6) == 0) {
+                                format = AMediaFormat_new();
+                                AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
+
+                                if (dstMime != nullptr) {
+                                    AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, dstMime);
+                                }
+                            }
+                            return format;
+                        }),
+                AMEDIA_OK);
+
+        if (dstMime != nullptr) {
+            std::vector<FormatVerifierEntry> extraVerifiers = {
+                    {AMEDIAFORMAT_KEY_MIME,
+                     [dstMime](const char* key, AMediaFormat* src __unused, AMediaFormat* dst) {
+                         const char* mime = nullptr;
+                         AMediaFormat_getString(dst, key, &mime);
+                         return !strcmp(mime, dstMime);
+                     }},
+            };
+            verifyOutputFormat(destPath, &extraVerifiers);
+        } else {
+            verifyOutputFormat(destPath);
+        }
+    }
+
     void verifyOutputFormat(const char* destPath,
                             const std::vector<FormatVerifierEntry>* extraVerifiers = nullptr) {
         int dstFd = open(destPath, O_RDONLY);
@@ -194,7 +227,8 @@
 
         for (int i = 0; i < (sizeof(kFieldsToPreserve) / sizeof(kFieldsToPreserve[0])); ++i) {
             EXPECT_TRUE(kFieldsToPreserve[i].equal(kFieldsToPreserve[i].key,
-                                                   mSourceVideoFormat.get(), videoFormat.get()));
+                                                   mSourceVideoFormat.get(), videoFormat.get()))
+                    << "Failed at key " << kFieldsToPreserve[i].key;
         }
 
         if (extraVerifiers != nullptr) {
@@ -212,76 +246,31 @@
 };
 
 TEST_F(MediaTranscoderTests, TestPassthrough) {
+    const char* srcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
     const char* destPath = "/data/local/tmp/MediaTranscoder_Passthrough.MP4";
 
-    EXPECT_EQ(transcodeHelper(SOURCE_PATH_AVC, destPath, [](AMediaFormat*) { return nullptr; }),
-              AMEDIA_OK);
+    EXPECT_EQ(transcodeHelper(srcPath, destPath, [](AMediaFormat*) { return nullptr; }), AMEDIA_OK);
 
     verifyOutputFormat(destPath);
 }
 
-TEST_F(MediaTranscoderTests, TestBasicVideoTranscodeAvcToAvc) {
-    const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscodeAvcToAvc.MP4";
-    const int32_t kBitRate = 8 * 1000 * 1000;  // 8Mbs
-
-    EXPECT_EQ(transcodeHelper(
-                      SOURCE_PATH_AVC, destPath,
-                      [](AMediaFormat* sourceFormat) {
-                          AMediaFormat* format = nullptr;
-                          const char* mime = nullptr;
-                          AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
-
-                          if (strncmp(mime, "video/", 6) == 0) {
-                              format = AMediaFormat_new();
-                              AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
-                          }
-                          return format;
-                      }),
-              AMEDIA_OK);
-
-    std::vector<FormatVerifierEntry> extraVerifiers = {
-            {AMEDIAFORMAT_KEY_MIME,
-             [](const char* key, AMediaFormat* src __unused, AMediaFormat* dst) {
-                 const char* mime = nullptr;
-                 AMediaFormat_getString(dst, key, &mime);
-                 return !strcmp(mime, AMEDIA_MIMETYPE_VIDEO_AVC);
-             }},
-    };
-
-    verifyOutputFormat(destPath, &extraVerifiers);
+TEST_F(MediaTranscoderTests, TestVideoTranscode_AvcToAvc_Basic) {
+    const char* srcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
+    const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscode_AvcToAvc_Basic.MP4";
+    testTranscodeVideo(srcPath, destPath, nullptr /*dstMime*/);
 }
 
-TEST_F(MediaTranscoderTests, TestBasicVideoTranscodeHevcToAvc) {
-    const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscodeHevcToAvc.MP4";
+TEST_F(MediaTranscoderTests, TestVideoTranscode_HevcToAvc_Basic) {
+    const char* srcPath = "/data/local/tmp/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4";
+    const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscode_HevcToAvc_Basic.MP4";
+    testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
+}
 
-    EXPECT_EQ(transcodeHelper(
-                      SOURCE_PATH_HEVC, destPath,
-                      [](AMediaFormat* sourceFormat) {
-                          AMediaFormat* format = nullptr;
-                          const char* mime = nullptr;
-                          AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
-
-                          if (strncmp(mime, "video/", 6) == 0) {
-                              const int32_t kBitRate = 8 * 1000 * 1000;  // 8Mbs
-                              format = AMediaFormat_new();
-                              AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
-                              AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME,
-                                                     AMEDIA_MIMETYPE_VIDEO_AVC);
-                          }
-                          return format;
-                      }),
-              AMEDIA_OK);
-
-    std::vector<FormatVerifierEntry> extraVerifiers = {
-            {AMEDIAFORMAT_KEY_MIME,
-             [](const char* key, AMediaFormat* src __unused, AMediaFormat* dst) {
-                 const char* mime = nullptr;
-                 AMediaFormat_getString(dst, key, &mime);
-                 return !strcmp(mime, AMEDIA_MIMETYPE_VIDEO_AVC);
-             }},
-    };
-
-    verifyOutputFormat(destPath, &extraVerifiers);
+TEST_F(MediaTranscoderTests, TestVideoTranscode_HevcToAvc_Rotation) {
+    const char* srcPath =
+            "/data/local/tmp/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4";
+    const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscode_HevcToAvc_Rotation.MP4";
+    testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 2f149de..c180edf 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -70,9 +70,18 @@
     },
 
     header_libs: [
+        "libaudioclient_headers",
         "libstagefright_foundation_headers",
+        "media_ndk_headers",
     ],
-    shared_libs: ["libmediandk"],
+
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+
     export_include_dirs: ["include"],
 }
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 823c010..4da85a2 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -567,7 +567,7 @@
         release();
     }
 
-    if (fallocate(mFd, FALLOC_FL_KEEP_SIZE, 0, 1) == 0) {
+    if (fallocate64(mFd, FALLOC_FL_KEEP_SIZE, 0, 1) == 0) {
         ALOGD("PreAllocation enabled");
         mPreAllocationEnabled = true;
     } else {
@@ -1896,7 +1896,7 @@
     ALOGV("preAllocateSize :%" PRIu64 " lastFileEndOffset:%" PRIu64, preAllocateSize,
           lastFileEndOffset);
 
-    int res = fallocate(mFd, FALLOC_FL_KEEP_SIZE, lastFileEndOffset, preAllocateSize);
+    int res = fallocate64(mFd, FALLOC_FL_KEEP_SIZE, lastFileEndOffset, preAllocateSize);
     if (res == -1) {
         ALOGE("fallocate err:%s, %d, fd:%d", strerror(errno), errno, mFd);
         sp<AMessage> msg = new AMessage(kWhatFallocateError, mReflector);
@@ -1923,7 +1923,7 @@
     ALOGD("ftruncate mPreAllocateFileEndOffset:%" PRId64 " mOffset:%" PRIu64
           " mMdatEndOffset:%" PRIu64 " diff:%" PRId64, mPreAllocateFileEndOffset, mOffset,
           mMdatEndOffset, mPreAllocateFileEndOffset - endOffset);
-    if (ftruncate(mFd, endOffset) == -1) {
+    if (ftruncate64(mFd, endOffset) == -1) {
         ALOGE("ftruncate err:%s, %d, fd:%d", strerror(errno), errno, mFd);
         status = false;
         /* No need to post and handle(stop & notify client) error like it's done in preAllocate(),
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index d5272bc..d6d472b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -690,7 +690,9 @@
         const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
         if (outputDesc->isActive(volumeSource, inPastMs, sysTime)
                 && (!(outputDesc->devices()
-                        .containsDeviceAmongTypes(getAllOutRemoteDevices())))) {
+                        .containsDeviceAmongTypes(getAllOutRemoteDevices())
+                        || outputDesc->devices()
+                            .onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)))) {
             return true;
         }
     }
@@ -722,7 +724,11 @@
         const sp<SwAudioOutputDescriptor> otherDesc = valueAt(i);
         if (desc->sharesHwModuleWith(otherDesc) &&
                 otherDesc->isStrategyActive(ps, inPastMs, sysTime)) {
-            return true;
+            if (desc == otherDesc
+                    || !otherDesc->devices()
+                            .onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
+                return true;
+            }
         }
     }
     return false;
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
index 2b97c2e..b0ea0db 100644
--- a/services/mediatranscoding/MediaTranscodingService.cpp
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -84,7 +84,7 @@
 //static
 void MediaTranscodingService::instantiate() {
     std::shared_ptr<TranscoderInterface> transcoder;
-    if (property_get_bool("debug.transcoding.simulated_transcoder", true)) {
+    if (property_get_bool("debug.transcoding.simulated_transcoder", false)) {
         transcoder = std::make_shared<SimulatedTranscoder>();
     } else {
         transcoder = std::make_shared<TranscoderWrapper>();