Merge "Camera: Improve documentation for android.control.zoomRatio" into rvc-dev am: 8f612b453b am: ac3ea9ccbd

Change-Id: Ic01df295eb879633532eb297ca6081abccbb9802
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index f408b6a..3a678be 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -695,7 +695,7 @@
     // No way to get package name from native.
     // Send a zero length package name and let camera service figure it out from UID
     binder::Status serviceRet = cs->connectDevice(
-            callbacks, String16(cameraId), String16(""), std::unique_ptr<String16>(),
+            callbacks, String16(cameraId), String16(""), {},
             hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
 
     if (!serviceRet.isOk()) {
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 8ccded2..eee05ff 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -378,7 +378,7 @@
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
         sp<hardware::camera2::ICameraDeviceUser> device;
         res = service->connectDevice(callbacks, cameraId, String16("meeeeeeeee!"),
-                std::unique_ptr<String16>(), hardware::ICameraService::USE_CALLING_UID,
+                {}, hardware::ICameraService::USE_CALLING_UID,
                 /*out*/&device);
         EXPECT_TRUE(res.isOk()) << res;
         ASSERT_NE(nullptr, device.get());
@@ -421,7 +421,7 @@
         {
             SCOPED_TRACE("openNewDevice");
             binder::Status res = service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
-                    std::unique_ptr<String16>(), hardware::ICameraService::USE_CALLING_UID,
+                    {}, hardware::ICameraService::USE_CALLING_UID,
                     /*out*/&device);
             EXPECT_TRUE(res.isOk()) << res;
         }
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index 5292705..e31395d 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -66,7 +66,7 @@
     std::vector<MediaResourceParcel> resources;
     MediaResourceParcel resource{
             Type::kDrmSession, SubType::kUnspecifiedSubType,
-            toStdVec<int8_t>(sessionId), value};
+            toStdVec<>(sessionId), value};
     resources.push_back(resource);
     return resources;
 }
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index cc132de..2e9bdd9 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1829,7 +1829,7 @@
                 // copy standard infos to graphic buffers if not already present (otherwise, we
                 // may overwrite the actual intermediate value with a final value)
                 stream = 0;
-                const static std::vector<C2Param::Index> stdGfxInfos = {
+                const static C2Param::Index stdGfxInfos[] = {
                     C2StreamRotationInfo::output::PARAM_TYPE,
                     C2StreamColorAspectsInfo::output::PARAM_TYPE,
                     C2StreamDataSpaceInfo::output::PARAM_TYPE,
diff --git a/media/codec2/vndk/util/C2InterfaceUtils.cpp b/media/codec2/vndk/util/C2InterfaceUtils.cpp
index 61ec911..0c1729b 100644
--- a/media/codec2/vndk/util/C2InterfaceUtils.cpp
+++ b/media/codec2/vndk/util/C2InterfaceUtils.cpp
@@ -216,9 +216,14 @@
     if (limit.contains(minMask) && contains(minMask)) {
         values[0] = minMask;
         // keep only flags that are covered by limit
-        std::remove_if(values.begin(), values.end(), [&limit, minMask](const C2Value::Primitive &v) -> bool {
-            T value = v.ref<ValueType>() | minMask;
-            return value == minMask || !limit.contains(value); });
+        values.erase(std::remove_if(values.begin(), values.end(),
+                                    [&limit, minMask](
+                                        const C2Value::Primitive &v) -> bool {
+                                      T value = v.ref<ValueType>() | minMask;
+                                      return value == minMask ||
+                                             !limit.contains(value);
+                                    }),
+                     values.end());
         // we also need to do it vice versa
         for (const C2Value::Primitive &v : _mValues) {
             T value = v.ref<ValueType>() | minMask;
@@ -264,24 +269,33 @@
 template<typename T>
 C2SupportedValueSet<T> C2SupportedValueSet<T>::limitedTo(const C2SupportedValueSet<T> &limit) const {
     std::vector<C2Value::Primitive> values = _mValues; // make a copy
-    std::remove_if(values.begin(), values.end(), [&limit](const C2Value::Primitive &v) -> bool {
-        return !limit.contains(v.ref<ValueType>()); });
+    values.erase(std::remove_if(values.begin(), values.end(),
+                                [&limit](const C2Value::Primitive &v) -> bool {
+                                  return !limit.contains(v.ref<ValueType>());
+                                }),
+                 values.end());
     return C2SupportedValueSet(std::move(values));
 }
 
 template<typename T>
 C2SupportedValueSet<T> C2SupportedValueSet<T>::limitedTo(const C2SupportedRange<T> &limit) const {
     std::vector<C2Value::Primitive> values = _mValues; // make a copy
-    std::remove_if(values.begin(), values.end(), [&limit](const C2Value::Primitive &v) -> bool {
-        return !limit.contains(v.ref<ValueType>()); });
+    values.erase(std::remove_if(values.begin(), values.end(),
+                                [&limit](const C2Value::Primitive &v) -> bool {
+                                  return !limit.contains(v.ref<ValueType>());
+                                }),
+                 values.end());
     return C2SupportedValueSet(std::move(values));
 }
 
 template<typename T>
 C2SupportedValueSet<T> C2SupportedValueSet<T>::limitedTo(const C2SupportedFlags<T> &limit) const {
     std::vector<C2Value::Primitive> values = _mValues; // make a copy
-    std::remove_if(values.begin(), values.end(), [&limit](const C2Value::Primitive &v) -> bool {
-        return !limit.contains(v.ref<ValueType>()); });
+    values.erase(std::remove_if(values.begin(), values.end(),
+                                [&limit](const C2Value::Primitive &v) -> bool {
+                                  return !limit.contains(v.ref<ValueType>());
+                                }),
+                 values.end());
     return C2SupportedValueSet(std::move(values));
 }
 
diff --git a/media/extractors/tests/ExtractorUnitTest.cpp b/media/extractors/tests/ExtractorUnitTest.cpp
index 518166e..fca66a4 100644
--- a/media/extractors/tests/ExtractorUnitTest.cpp
+++ b/media/extractors/tests/ExtractorUnitTest.cpp
@@ -22,6 +22,7 @@
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaDataUtils.h>
+#include <media/stagefright/foundation/OpusHeader.h>
 
 #include "aac/AACExtractor.h"
 #include "amr/AMRExtractor.h"
@@ -43,7 +44,9 @@
 #define OUTPUT_DUMP_FILE "/data/local/tmp/extractorOutput"
 
 constexpr int32_t kMaxCount = 10;
-constexpr int32_t kOpusSeekPreRollUs = 80000;  // 80 ms;
+constexpr int32_t kAudioDefaultSampleDuration = 20000;                       // 20ms
+constexpr int32_t kRandomSeekToleranceUs = 2 * kAudioDefaultSampleDuration;  // 40 ms;
+constexpr int32_t kRandomSeed = 700;
 
 static ExtractorUnitTestEnvironment *gEnv = nullptr;
 
@@ -168,6 +171,47 @@
     return 0;
 }
 
+void randomSeekTest(MediaTrackHelper *track, int64_t clipDuration) {
+    int32_t status = 0;
+    int32_t seekCount = 0;
+    bool hasTimestamp = false;
+    vector<int64_t> seekToTimeStamp;
+    string seekPtsString;
+
+    srand(kRandomSeed);
+    while (seekCount < kMaxCount) {
+        int64_t timeStamp = ((double)rand() / RAND_MAX) * clipDuration;
+        seekToTimeStamp.push_back(timeStamp);
+        seekPtsString.append(to_string(timeStamp));
+        seekPtsString.append(", ");
+        seekCount++;
+    }
+
+    for (int64_t seekPts : seekToTimeStamp) {
+        MediaTrackHelper::ReadOptions *options = new MediaTrackHelper::ReadOptions(
+                CMediaTrackReadOptions::SEEK_CLOSEST | CMediaTrackReadOptions::SEEK, seekPts);
+        ASSERT_NE(options, nullptr) << "Cannot create read option";
+
+        MediaBufferHelper *buffer = nullptr;
+        status = track->read(&buffer, options);
+        if (buffer) {
+            AMediaFormat *metaData = buffer->meta_data();
+            int64_t timeStamp = 0;
+            hasTimestamp = AMediaFormat_getInt64(metaData, AMEDIAFORMAT_KEY_TIME_US, &timeStamp);
+            ASSERT_TRUE(hasTimestamp) << "Extractor didn't set timestamp for the given sample";
+
+            buffer->release();
+            EXPECT_LE(abs(timeStamp - seekPts), kRandomSeekToleranceUs)
+                    << "Seek unsuccessful. Expected timestamp range ["
+                    << seekPts - kRandomSeekToleranceUs << ", " << seekPts + kRandomSeekToleranceUs
+                    << "] "
+                    << "received " << timeStamp << ", list of input seek timestamps ["
+                    << seekPtsString << "]";
+        }
+        delete options;
+    }
+}
+
 void getSeekablePoints(vector<int64_t> &seekablePoints, MediaTrackHelper *track) {
     int32_t status = 0;
     if (!seekablePoints.empty()) {
@@ -380,9 +424,7 @@
 }
 
 TEST_P(ExtractorUnitTest, SeekTest) {
-    // Both Flac and Wav extractor can give samples from any pts and mark the given sample as
-    // sync frame. So, this seek test is not applicable to FLAC and WAV extractors
-    if (mDisableTest || mExtractorName == FLAC || mExtractorName == WAV) return;
+    if (mDisableTest) return;
 
     ALOGV("Validates %s Extractor behaviour for different seek modes", GetParam().first.c_str());
     string inputFileName = gEnv->getRes() + GetParam().second;
@@ -415,6 +457,32 @@
         MediaBufferGroup *bufferGroup = new MediaBufferGroup();
         status = cTrack->start(track, bufferGroup->wrap());
         ASSERT_EQ(OK, (media_status_t)status) << "Failed to start the track";
+
+        // For Flac, Wav and Midi extractor, all samples are seek points.
+        // We cannot create list of all seekable points for these.
+        // This means that if we pass a seekToTimeStamp between two seek points, we may
+        // end up getting the timestamp of next sample as a seekable timestamp.
+        // This timestamp may/may not be a part of the seekable point vector thereby failing the
+        // test. So we test these extractors using random seek test.
+        if (mExtractorName == FLAC || mExtractorName == WAV || mExtractorName == MIDI) {
+            AMediaFormat *trackMeta = AMediaFormat_new();
+            ASSERT_NE(trackMeta, nullptr) << "AMediaFormat_new returned null AMediaformat";
+
+            status = mExtractor->getTrackMetaData(trackMeta, idx, 1);
+            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 ";
+            randomSeekTest(track, clipDuration);
+            AMediaFormat_delete(trackMeta);
+            continue;
+        }
+        // Request seekable points for remaining extractors which will be used to validate the seek
+        // accuracy for the extractors. Depending on SEEK Mode, we expect the extractors to return
+        // the expected sync frame. We don't prefer random seek test for these extractors because
+        // they aren't expected to seek to random samples. MP4 for instance can seek to
+        // 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";
@@ -425,9 +493,31 @@
         ASSERT_EQ(OK, (media_status_t)status) << "Failed to get track meta data";
 
         bool isOpus = false;
+        int64_t opusSeekPreRollUs = 0;
         const char *mime;
         AMediaFormat_getString(trackFormat, AMEDIAFORMAT_KEY_MIME, &mime);
-        if (!strcmp(mime, "audio/opus")) isOpus = true;
+        if (!strcmp(mime, "audio/opus")) {
+            isOpus = true;
+            void *seekPreRollBuf = nullptr;
+            size_t size = 0;
+            if (!AMediaFormat_getBuffer(trackFormat, "csd-2", &seekPreRollBuf, &size)) {
+                size_t opusHeadSize = 0;
+                size_t codecDelayBufSize = 0;
+                size_t seekPreRollBufSize = 0;
+                void *csdBuffer = nullptr;
+                void *opusHeadBuf = nullptr;
+                void *codecDelayBuf = nullptr;
+                AMediaFormat_getBuffer(trackFormat, "csd-0", &csdBuffer, &size);
+                ASSERT_NE(csdBuffer, nullptr);
+
+                GetOpusHeaderBuffers((uint8_t *)csdBuffer, size, &opusHeadBuf, &opusHeadSize,
+                                     &codecDelayBuf, &codecDelayBufSize, &seekPreRollBuf,
+                                     &seekPreRollBufSize);
+            }
+            ASSERT_NE(seekPreRollBuf, nullptr)
+                    << "Invalid track format. SeekPreRoll info missing for Opus file";
+            opusSeekPreRollUs = *((int64_t *)seekPreRollBuf);
+        }
         AMediaFormat_delete(trackFormat);
 
         int32_t seekIdx = 0;
@@ -448,7 +538,7 @@
                 // extractor is calculated based on (seekPts - seekPreRollUs).
                 // So we add the preRoll value to the timeStamp we want to seek to.
                 if (isOpus) {
-                    seekToTimeStamp += kOpusSeekPreRollUs;
+                    seekToTimeStamp += opusSeekPreRollUs;
                 }
 
                 MediaTrackHelper::ReadOptions *options = new MediaTrackHelper::ReadOptions(
@@ -496,8 +586,6 @@
     seekablePoints.clear();
 }
 
-// TODO: (b/145332185)
-// Add MIDI inputs
 INSTANTIATE_TEST_SUITE_P(ExtractorUnitTestAll, ExtractorUnitTest,
                          ::testing::Values(make_pair("aac", "loudsoftaac.aac"),
                                            make_pair("amr", "testamr.amr"),
@@ -507,6 +595,7 @@
                                            make_pair("mpeg2ts", "segment000001.ts"),
                                            make_pair("flac", "sinesweepflac.flac"),
                                            make_pair("ogg", "testopus.opus"),
+                                           make_pair("midi", "midi_a.mid"),
                                            make_pair("mkv", "sinesweepvorbis.mkv"),
                                            make_pair("mpeg4", "sinesweepoggmp4.mp4"),
                                            make_pair("mp3", "sinesweepmp3lame.mp3"),
diff --git a/media/libaudioclient/AudioAttributes.cpp b/media/libaudioclient/AudioAttributes.cpp
index 1ee6930..ff4ba06 100644
--- a/media/libaudioclient/AudioAttributes.cpp
+++ b/media/libaudioclient/AudioAttributes.cpp
@@ -57,7 +57,7 @@
         parcel->writeInt32(0);
     } else {
         parcel->writeInt32(1);
-        parcel->writeUtf8AsUtf16(mAttributes.tags);
+        parcel->writeUtf8AsUtf16(std::string(mAttributes.tags));
     }
     parcel->writeInt32(static_cast<int32_t>(mStreamType));
     parcel->writeUint32(static_cast<uint32_t>(mGroupId));
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
index 6508b73..4170b3c 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
@@ -18,7 +18,7 @@
 #ifndef _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
 #define _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
 
-#define DC_FLOAT_STEP   0.0000002384f;
+#define DC_FLOAT_STEP   0.0000002384f
 
 /* The internal state variables are implemented in a (for the user)  hidden structure */
 /* In this (private) file, the internal structure is declared fro private use.*/
diff --git a/media/libmedia/MediaResource.cpp b/media/libmedia/MediaResource.cpp
index 0936a99..fe86d27 100644
--- a/media/libmedia/MediaResource.cpp
+++ b/media/libmedia/MediaResource.cpp
@@ -35,7 +35,7 @@
     this->value = value;
 }
 
-MediaResource::MediaResource(Type type, const std::vector<int8_t> &id, int64_t value) {
+MediaResource::MediaResource(Type type, const std::vector<uint8_t> &id, int64_t value) {
     this->type = type;
     this->subType = SubType::kUnspecifiedSubType;
     this->id = id;
@@ -66,11 +66,11 @@
 }
 
 //static
-MediaResource MediaResource::DrmSessionResource(const std::vector<int8_t> &id, int64_t value) {
+MediaResource MediaResource::DrmSessionResource(const std::vector<uint8_t> &id, int64_t value) {
     return MediaResource(Type::kDrmSession, id, value);
 }
 
-static String8 bytesToHexString(const std::vector<int8_t> &bytes) {
+static String8 bytesToHexString(const std::vector<uint8_t> &bytes) {
     String8 str;
     for (auto &b : bytes) {
         str.appendFormat("%02x", b);
diff --git a/media/libmedia/include/media/MediaResource.h b/media/libmedia/include/media/MediaResource.h
index e7362c1..4927d28 100644
--- a/media/libmedia/include/media/MediaResource.h
+++ b/media/libmedia/include/media/MediaResource.h
@@ -35,13 +35,13 @@
     MediaResource() = delete;
     MediaResource(Type type, int64_t value);
     MediaResource(Type type, SubType subType, int64_t value);
-    MediaResource(Type type, const std::vector<int8_t> &id, int64_t value);
+    MediaResource(Type type, const std::vector<uint8_t> &id, int64_t value);
 
     static MediaResource CodecResource(bool secure, bool video);
     static MediaResource GraphicMemoryResource(int64_t value);
     static MediaResource CpuBoostResource();
     static MediaResource VideoBatteryResource();
-    static MediaResource DrmSessionResource(const std::vector<int8_t> &id, int64_t value);
+    static MediaResource DrmSessionResource(const std::vector<uint8_t> &id, int64_t value);
 };
 
 inline static const char *asString(MediaResource::Type i, const char *def = "??") {
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 94267a1..af7da06 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -59,7 +59,7 @@
             sp<IMediaExtractor> ex;
             mediaExService->makeExtractor(
                     CreateIDataSourceFromDataSource(source),
-                    mime ? std::make_unique<std::string>(mime) : nullptr,
+                    mime ? std::optional<std::string>(mime) : std::nullopt,
                     &ex);
             return ex;
         } else {
diff --git a/media/libstagefright/codecs/amrnb/dec/test/AndroidTest.xml b/media/libstagefright/codecs/amrnb/dec/test/AndroidTest.xml
new file mode 100644
index 0000000..1a9e678
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for Amr-nb Decoder unit test">
+    <option name="test-suite-tag" value="AmrnbDecoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="AmrnbDecoderTest->/data/local/tmp/AmrnbDecoderTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip?unzip=true"
+            value="/data/local/tmp/AmrnbDecoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="AmrnbDecoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/AmrnbDecoderTestRes/" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/codecs/amrnb/dec/test/README.md b/media/libstagefright/codecs/amrnb/dec/test/README.md
index 62e13ae..e9073e4 100644
--- a/media/libstagefright/codecs/amrnb/dec/test/README.md
+++ b/media/libstagefright/codecs/amrnb/dec/test/README.md
@@ -22,13 +22,18 @@
 adb push ${OUT}/data/nativetest/AmrnbDecoderTest/AmrnbDecoderTest /data/local/tmp/
 ```
 
-The resource file for the tests is taken from [here](https://drive.google.com/drive/folders/13cM4tAaVFrmr-zGFqaAzFBbKs75pnm9b). Push these files into device for testing.
-Download amr-nb folder and push all the files in this folder to /data/local/tmp/ on the device.
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip). Download, unzip and push these files into device for testing.
+
 ```
-adb push amr-nb/. /data/local/tmp/
+adb push AmrnbDecoderTestRes/. /data/local/tmp/
 ```
 
 usage: AmrnbDecoderTest -P \<path_to_folder\>
 ```
-adb shell /data/local/tmp/AmrnbDecoderTest -P /data/local/tmp/
+adb shell /data/local/tmp/AmrnbDecoderTest -P /data/local/tmp/AmrnbDecoderTestRes/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest AmrnbDecoderTest -- --enable-module-dynamic-download=true
 ```
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.bp b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
index c67dc2b..0e18c10 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
@@ -1,6 +1,7 @@
 cc_library_static {
     name: "libstagefright_m4vh263dec",
     vendor_available: true,
+    host_supported: true,
     shared_libs: ["liblog"],
 
     srcs: [
@@ -38,11 +39,6 @@
         "src/zigzag_tab.cpp",
     ],
 
-    header_libs: [
-        "media_plugin_headers",
-        "libstagefright_headers"
-    ],
-
     local_include_dirs: ["src"],
     export_include_dirs: ["include"],
 
@@ -58,6 +54,12 @@
         ],
         cfi: true,
     },
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 //###############################################################################
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/Android.bp b/media/libstagefright/codecs/m4v_h263/fuzzer/Android.bp
new file mode 100644
index 0000000..aa79d37
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/fuzzer/Android.bp
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+    name: "mpeg4_dec_fuzzer",
+    host_supported: true,
+    srcs: [
+        "mpeg4_h263_dec_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libstagefright_m4vh263dec",
+        "liblog",
+    ],
+    cflags: [
+        "-DOSCL_IMPORT_REF=",
+        "-DMPEG4",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+cc_fuzz {
+    name: "h263_dec_fuzzer",
+    host_supported: true,
+    srcs: [
+        "mpeg4_h263_dec_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libstagefright_m4vh263dec",
+        "liblog",
+    ],
+    cflags: [
+        "-DOSCL_IMPORT_REF=",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/README.md b/media/libstagefright/codecs/m4v_h263/fuzzer/README.md
new file mode 100644
index 0000000..c2a4f69
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/fuzzer/README.md
@@ -0,0 +1,57 @@
+# Fuzzer for libstagefright_m4vh263dec decoder
+
+## Plugin Design Considerations
+The fuzzer plugin for MPEG4/H263 is designed based on the understanding of the
+codec and tries to achieve the following:
+
+##### Maximize code coverage
+Dict files (dictionary files) are created for MPEG4 and H263 to ensure that the required start
+bytes are present in every input file that goes to the fuzzer.
+This ensures that decoder does not reject any input file in the first check
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the codec using a loop.
+ * If the decode operation was successful, the input is advanced by the number of bytes consumed
+   in the decode call.
+ * If the decode operation was un-successful, the input is advanced by 1 byte so that the fuzzer
+   can proceed to feed the next frame.
+
+This ensures that the plugin tolerates any kind of input (empty, huge, malformed, etc)
+and doesnt `exit()` on any input and thereby increasing the chance of identifying vulnerabilities.
+
+##### Other considerations
+ * Two fuzzer binaries - mpeg4_dec_fuzzer and h263_dec_fuzzer are generated based on the presence
+   of a flag - 'MPEG4'
+ * The number of decode calls are kept to a maximum of 100 so that the fuzzer does not timeout.
+
+## Build
+
+This describes steps to build mpeg4_dec_fuzzer and h263_dec_fuzzer binary.
+
+### Android
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) mpeg4_dec_fuzzer
+  $ mm -j$(nproc) h263_dec_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some MPEG4 or H263 files to that folder
+Push this directory to device.
+
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mpeg4_dec_fuzzer/mpeg4_dec_fuzzer CORPUS_DIR
+  $ adb shell /data/fuzz/arm64/h263_dec_fuzzer/h263_dec_fuzzer CORPUS_DIR
+```
+To run on host
+```
+  $ $ANDROID_HOST_OUT/fuzz/x86_64/mpeg4_dec_fuzzer/mpeg4_dec_fuzzer CORPUS_DIR
+  $ $ANDROID_HOST_OUT/fuzz/x86_64/h263_dec_fuzzer/h263_dec_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict b/media/libstagefright/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
new file mode 100644
index 0000000..591d37e
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
@@ -0,0 +1,2 @@
+# Start code (bytes 0-3)
+kw1="\x00\x00\x80\x02"
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict b/media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
new file mode 100644
index 0000000..76241a6
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
@@ -0,0 +1,2 @@
+# Start code (bytes 0-3)
+kw1="\x00\x00\x01\xB0"
diff --git a/media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp b/media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
new file mode 100644
index 0000000..912c821
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
@@ -0,0 +1,205 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include "mp4dec_api.h"
+#define MPEG4_MAX_WIDTH 1920
+#define MPEG4_MAX_HEIGHT 1080
+#define H263_MAX_WIDTH 352
+#define H263_MAX_HEIGHT 288
+#define DEFAULT_WIDTH 352
+#define DEFAULT_HEIGHT 288
+
+constexpr size_t kMaxNumDecodeCalls = 100;
+constexpr uint8_t kNumOutputBuffers = 2;
+constexpr int kLayer = 1;
+
+struct tagvideoDecControls;
+
+/* == ceil(num / den) * den. T must be integer type, alignment must be positive power of 2 */
+template <class T, class U>
+inline static const T align(const T &num, const U &den) {
+  return (num + (T)(den - 1)) & (T) ~(den - 1);
+}
+
+class Codec {
+ public:
+  Codec() = default;
+  ~Codec() { deInitDecoder(); }
+  bool initDecoder();
+  bool allocOutputBuffer(size_t outputBufferSize);
+  void freeOutputBuffer();
+  void handleResolutionChange();
+  void decodeFrames(const uint8_t *data, size_t size);
+  void deInitDecoder();
+
+ private:
+  tagvideoDecControls *mDecHandle = nullptr;
+  uint8_t *mOutputBuffer[kNumOutputBuffers];
+  bool mInitialized = false;
+  bool mFramesConfigured = false;
+#ifdef MPEG4
+  MP4DecodingMode mInputMode = MPEG4_MODE;
+  size_t mMaxWidth = MPEG4_MAX_WIDTH;
+  size_t mMaxHeight = MPEG4_MAX_HEIGHT;
+#else
+  MP4DecodingMode mInputMode = H263_MODE;
+  size_t mMaxWidth = H263_MAX_WIDTH;
+  size_t mMaxHeight = H263_MAX_HEIGHT;
+#endif
+  uint32_t mNumSamplesOutput = 0;
+  uint32_t mWidth = DEFAULT_WIDTH;
+  uint32_t mHeight = DEFAULT_HEIGHT;
+};
+
+bool Codec::initDecoder() {
+  mDecHandle = new tagvideoDecControls;
+  if (!mDecHandle) {
+    return false;
+  }
+  memset(mDecHandle, 0, sizeof(tagvideoDecControls));
+  return true;
+}
+
+bool Codec::allocOutputBuffer(size_t outputBufferSize) {
+  for (uint8_t i = 0; i < kNumOutputBuffers; ++i) {
+    if (!mOutputBuffer[i]) {
+      mOutputBuffer[i] = static_cast<uint8_t *>(malloc(outputBufferSize));
+      if (!mOutputBuffer[i]) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+void Codec::freeOutputBuffer() {
+  for (uint8_t i = 0; i < kNumOutputBuffers; ++i) {
+    if (mOutputBuffer[i]) {
+      free(mOutputBuffer[i]);
+      mOutputBuffer[i] = nullptr;
+    }
+  }
+}
+
+void Codec::handleResolutionChange() {
+  int32_t dispWidth, dispHeight;
+  PVGetVideoDimensions(mDecHandle, &dispWidth, &dispHeight);
+
+  int32_t bufWidth, bufHeight;
+  PVGetBufferDimensions(mDecHandle, &bufWidth, &bufHeight);
+
+  if (dispWidth != mWidth || dispHeight != mHeight) {
+    mWidth = dispWidth;
+    mHeight = dispHeight;
+  }
+}
+
+void Codec::decodeFrames(const uint8_t *data, size_t size) {
+  size_t outputBufferSize = align(mMaxWidth, 16) * align(mMaxHeight, 16) * 3 / 2;
+  uint8_t *start_code = const_cast<uint8_t *>(data);
+  static const uint8_t volInfo[] = {0x00, 0x00, 0x01, 0xB0};
+  bool volHeader = memcmp(start_code, volInfo, 4) == 0;
+  if (volHeader) {
+    PVCleanUpVideoDecoder(mDecHandle);
+    mInitialized = false;
+  }
+
+  if (!mInitialized) {
+    uint8_t *volData[1]{};
+    int32_t volSize = 0;
+
+    if (volHeader) { /* removed some codec config part */
+      volData[0] = const_cast<uint8_t *>(data);
+      volSize = size;
+    }
+
+    if (!PVInitVideoDecoder(mDecHandle, volData, &volSize, kLayer, mMaxWidth, mMaxHeight,
+                            mInputMode)) {
+      return;
+    }
+    mInitialized = true;
+    MP4DecodingMode actualMode = PVGetDecBitstreamMode(mDecHandle);
+    if (mInputMode != actualMode) {
+      return;
+    }
+
+    PVSetPostProcType(mDecHandle, 0);
+  }
+  size_t yFrameSize = sizeof(uint8) * mDecHandle->size;
+  if (outputBufferSize < yFrameSize * 3 / 2) {
+    return;
+  }
+  if (!allocOutputBuffer(outputBufferSize)) {
+    return;
+  }
+  size_t numDecodeCalls = 0;
+  while ((size > 0) && (numDecodeCalls < kMaxNumDecodeCalls)) {
+    if (!mFramesConfigured) {
+      PVSetReferenceYUV(mDecHandle, mOutputBuffer[1]);
+      mFramesConfigured = true;
+    }
+
+    // Need to check if header contains new info, e.g., width/height, etc.
+    VopHeaderInfo header_info;
+    uint32_t useExtTimestamp = (numDecodeCalls == 0);
+    int32_t tempSize = (int32_t)size;
+    uint8_t *bitstreamTmp = const_cast<uint8_t *>(data);
+    uint32_t timestamp = 0;
+    if (PVDecodeVopHeader(mDecHandle, &bitstreamTmp, &timestamp, &tempSize, &header_info,
+                          &useExtTimestamp, mOutputBuffer[mNumSamplesOutput & 1]) != PV_TRUE) {
+      return;
+    }
+
+    handleResolutionChange();
+
+    PVDecodeVopBody(mDecHandle, &tempSize);
+    uint32_t bytesConsumed = 1;
+    if (size > tempSize) {
+      bytesConsumed = size - tempSize;
+    }
+    data += bytesConsumed;
+    size -= bytesConsumed;
+    ++mNumSamplesOutput;
+    ++numDecodeCalls;
+  }
+  freeOutputBuffer();
+}
+
+void Codec::deInitDecoder() {
+  PVCleanUpVideoDecoder(mDecHandle);
+  delete mDecHandle;
+  mDecHandle = nullptr;
+  mInitialized = false;
+  freeOutputBuffer();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size < 4) {
+    return 0;
+  }
+  Codec *codec = new Codec();
+  if (!codec) {
+    return 0;
+  }
+  if (codec->initDecoder()) {
+    codec->decodeFrames(data, size);
+  }
+  delete codec;
+  return 0;
+}
diff --git a/media/libstagefright/foundation/OpusHeader.cpp b/media/libstagefright/foundation/OpusHeader.cpp
index f5687e0..784e802 100644
--- a/media/libstagefright/foundation/OpusHeader.cpp
+++ b/media/libstagefright/foundation/OpusHeader.cpp
@@ -126,12 +126,20 @@
     }
     header->num_streams = data[kOpusHeaderNumStreamsOffset];
     header->num_coupled = data[kOpusHeaderNumCoupledStreamsOffset];
-    if (header->num_streams + header->num_coupled != header->channels) {
-        ALOGV("Inconsistent channel mapping.");
+    if (header->num_coupled > header->num_streams ||
+        header->num_streams + header->num_coupled != header->channels) {
+        ALOGV("Inconsistent channel mapping, streams: %d coupled: %d channels: %d",
+        header->num_streams, header->num_coupled, header->channels);
         return false;
     }
-    for (int i = 0; i < header->channels; ++i)
-        header->stream_map[i] = data[kOpusHeaderStreamMapOffset + i];
+    for (int i = 0; i < header->channels; ++i) {
+        uint8_t value = data[kOpusHeaderStreamMapOffset + i];
+        if (value != 255 && value >= header->channels) {
+            ALOGV("Invalid channel mapping for index %i : %d", i, value);
+            return false;
+        }
+        header->stream_map[i] = value;
+    }
     return true;
 }
 
diff --git a/media/libstagefright/foundation/tests/OpusHeader/Android.bp b/media/libstagefright/foundation/tests/OpusHeader/Android.bp
new file mode 100644
index 0000000..c1251a8
--- /dev/null
+++ b/media/libstagefright/foundation/tests/OpusHeader/Android.bp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+    name: "OpusHeaderTest",
+    gtest: true,
+
+    srcs: [
+        "OpusHeaderTest.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    static_libs: [
+        "libstagefright_foundation",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libstagefright/foundation/tests/OpusHeader/AndroidTest.xml b/media/libstagefright/foundation/tests/OpusHeader/AndroidTest.xml
new file mode 100644
index 0000000..afee16a
--- /dev/null
+++ b/media/libstagefright/foundation/tests/OpusHeader/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for opus header unit tests">
+    <option name="test-suite-tag" value="OpusHeaderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="OpusHeaderTest->/data/local/tmp/OpusHeaderTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip?unzip=true"
+            value="/data/local/tmp/OpusHeaderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="OpusHeaderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/OpusHeaderTestRes/" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTest.cpp b/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTest.cpp
new file mode 100644
index 0000000..d142781
--- /dev/null
+++ b/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTest.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OpusHeaderTest"
+#include <utils/Log.h>
+
+#include <fstream>
+#include <stdio.h>
+#include <string.h>
+
+#include <media/stagefright/foundation/OpusHeader.h>
+
+#include "OpusHeaderTestEnvironment.h"
+
+using namespace android;
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/OpusOutput"
+
+// Opus in WebM is a well-known, yet under-documented, format. The codec private data
+// of the track is an Opus Ogg header (https://tools.ietf.org/html/rfc7845#section-5.1)
+// channel mapping offset in opus header
+constexpr size_t kOpusHeaderStreamMapOffset = 21;
+constexpr size_t kMaxOpusHeaderSize = 100;
+// AOPUSHDR + AOPUSHDRLength +
+// (8 + 8 ) +
+// Header(csd) + num_streams + num_coupled + 1
+// (19 + 1 + 1 + 1) +
+// AOPUSDLY + AOPUSDLYLength + DELAY + AOPUSPRL + AOPUSPRLLength + PRL
+// (8 + 8 + 8 + 8 + 8 + 8)
+// = 86
+constexpr size_t kOpusHeaderChannelMapOffset = 86;
+constexpr uint32_t kOpusSampleRate = 48000;
+constexpr uint64_t kOpusSeekPrerollNs = 80000000;
+constexpr int64_t kNsecPerSec = 1000000000ll;
+
+// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
+// mappings for up to 8 channels. This information is part of the Vorbis I
+// Specification:
+// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
+constexpr int kMaxChannels = 8;
+constexpr uint8_t kOpusChannelMap[kMaxChannels][kMaxChannels] = {
+        {0},
+        {0, 1},
+        {0, 2, 1},
+        {0, 1, 2, 3},
+        {0, 4, 1, 2, 3},
+        {0, 4, 1, 2, 3, 5},
+        {0, 4, 1, 2, 3, 5, 6},
+        {0, 6, 1, 2, 3, 4, 5, 7},
+};
+
+static OpusHeaderTestEnvironment *gEnv = nullptr;
+
+class OpusHeaderTest {
+  public:
+    OpusHeaderTest() : mInputBuffer(nullptr) {}
+
+    ~OpusHeaderTest() {
+        if (mEleStream.is_open()) mEleStream.close();
+        if (mInputBuffer) {
+            free(mInputBuffer);
+            mInputBuffer = nullptr;
+        }
+    }
+    ifstream mEleStream;
+    uint8_t *mInputBuffer;
+};
+
+class OpusHeaderParseTest : public OpusHeaderTest,
+                            public ::testing::TestWithParam<
+                                    tuple<string /* InputFileName */, int32_t /* ChannelCount */,
+                                          bool /* isHeaderValid */, bool /* isCodecDelayValid */,
+                                          bool /* isSeekPreRollValid */, bool /* isInputValid */>> {
+};
+
+class OpusHeaderWriteTest
+    : public OpusHeaderTest,
+      public ::testing::TestWithParam<pair<int32_t /* ChannelCount */, int32_t /* skipSamples */>> {
+};
+
+TEST_P(OpusHeaderWriteTest, WriteTest) {
+    OpusHeader writtenHeader;
+    memset(&writtenHeader, 0, sizeof(writtenHeader));
+    int32_t channels = GetParam().first;
+    writtenHeader.channels = channels;
+    writtenHeader.num_streams = channels;
+    writtenHeader.channel_mapping = ((channels > 8) ? 255 : (channels > 2));
+    int32_t skipSamples = GetParam().second;
+    writtenHeader.skip_samples = skipSamples;
+    uint64_t codecDelayNs = skipSamples * kNsecPerSec / kOpusSampleRate;
+    uint8_t headerData[kMaxOpusHeaderSize];
+    int32_t headerSize = WriteOpusHeaders(writtenHeader, kOpusSampleRate, headerData,
+                                          sizeof(headerData), codecDelayNs, kOpusSeekPrerollNs);
+    ASSERT_GT(headerSize, 0) << "failed to generate Opus header";
+    ASSERT_LE(headerSize, kMaxOpusHeaderSize)
+            << "Invalid header written. Header size can't exceed kMaxOpusHeaderSize";
+
+    ofstream ostrm;
+    ostrm.open(OUTPUT_FILE_NAME, ofstream::binary);
+    ASSERT_TRUE(ostrm.is_open()) << "Failed to open output file " << OUTPUT_FILE_NAME;
+
+    // TODO : Validate bitstream (b/150116402)
+    ostrm.write(reinterpret_cast<char *>(headerData), sizeof(headerData));
+    ostrm.close();
+
+    size_t opusHeadSize = 0;
+    size_t codecDelayBufSize = 0;
+    size_t seekPreRollBufSize = 0;
+    void *opusHeadBuf = nullptr;
+    void *codecDelayBuf = nullptr;
+    void *seekPreRollBuf = nullptr;
+    bool status = GetOpusHeaderBuffers(headerData, headerSize, &opusHeadBuf, &opusHeadSize,
+                                       &codecDelayBuf, &codecDelayBufSize, &seekPreRollBuf,
+                                       &seekPreRollBufSize);
+    ASSERT_TRUE(status) << "Encountered error in GetOpusHeaderBuffers";
+
+    uint64_t value = *((uint64_t *)codecDelayBuf);
+    ASSERT_EQ(value, codecDelayNs);
+
+    value = *((uint64_t *)seekPreRollBuf);
+    ASSERT_EQ(value, kOpusSeekPrerollNs);
+
+    OpusHeader parsedHeader;
+    status = ParseOpusHeader((uint8_t *)opusHeadBuf, opusHeadSize, &parsedHeader);
+    ASSERT_TRUE(status) << "Encountered error while Parsing Opus Header.";
+
+    ASSERT_EQ(writtenHeader.channels, parsedHeader.channels)
+            << "Invalid header generated. Mismatch between channel counts";
+
+    ASSERT_EQ(writtenHeader.skip_samples, parsedHeader.skip_samples)
+            << "Mismatch between no of skipSamples written "
+               "and no of skipSamples got after parsing";
+
+    ASSERT_EQ(writtenHeader.channel_mapping, parsedHeader.channel_mapping)
+            << "Mismatch between channelMapping written "
+               "and channelMapping got after parsing";
+
+    if (parsedHeader.channel_mapping) {
+        ASSERT_GT(parsedHeader.channels, 2);
+        ASSERT_EQ(writtenHeader.num_streams, parsedHeader.num_streams)
+                << "Invalid header generated. Mismatch between channel counts";
+
+        ASSERT_EQ(writtenHeader.num_coupled, parsedHeader.num_coupled)
+                << "Invalid header generated. Mismatch between channel counts";
+
+        ASSERT_EQ(parsedHeader.num_coupled + parsedHeader.num_streams, parsedHeader.channels);
+
+        ASSERT_LE(parsedHeader.num_coupled, parsedHeader.num_streams)
+                << "Invalid header generated. Number of coupled streams cannot be greater than "
+                   "number "
+                   "of streams.";
+
+        ASSERT_EQ(headerSize, kOpusHeaderChannelMapOffset + writtenHeader.channels)
+                << "Invalid header written. Header size should be equal to 86 + "
+                   "writtenHeader.channels";
+
+        uint8_t mappedChannelNumber;
+        for (int32_t channelNumber = 0; channelNumber < channels; channelNumber++) {
+            mappedChannelNumber = *(reinterpret_cast<uint8_t *>(opusHeadBuf) +
+                                    kOpusHeaderStreamMapOffset + channelNumber);
+            ASSERT_LT(mappedChannelNumber, channels) << "Invalid header generated. Channel mapping "
+                                                        "cannot be greater than channel count.";
+
+            ASSERT_EQ(mappedChannelNumber, kOpusChannelMap[channels - 1][channelNumber])
+                    << "Invalid header generated. Channel mapping is not as per specification.";
+        }
+    } else {
+        ASSERT_LE(parsedHeader.channels, 2);
+    }
+}
+
+TEST_P(OpusHeaderParseTest, ParseTest) {
+    tuple<string, int32_t, bool, bool, bool, bool> params = GetParam();
+    string inputFileName = gEnv->getRes() + get<0>(params);
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true) << "Failed to open inputfile " << get<0>(params);
+    bool isHeaderValid = get<2>(params);
+    bool isCodecDelayValid = get<3>(params);
+    bool isSeekPreRollValid = get<4>(params);
+    bool isInputValid = get<5>(params);
+
+    struct stat buf;
+    stat(inputFileName.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    mInputBuffer = (uint8_t *)malloc(fileSize);
+    ASSERT_NE(mInputBuffer, nullptr) << "Insufficient memory. Malloc failed for size " << fileSize;
+
+    mEleStream.read(reinterpret_cast<char *>(mInputBuffer), fileSize);
+    ASSERT_EQ(mEleStream.gcount(), fileSize) << "mEleStream.gcount() != bytesCount";
+
+    OpusHeader header;
+    size_t opusHeadSize = 0;
+    size_t codecDelayBufSize = 0;
+    size_t seekPreRollBufSize = 0;
+    void *opusHeadBuf = nullptr;
+    void *codecDelayBuf = nullptr;
+    void *seekPreRollBuf = nullptr;
+    bool status = GetOpusHeaderBuffers(mInputBuffer, fileSize, &opusHeadBuf, &opusHeadSize,
+                                       &codecDelayBuf, &codecDelayBufSize, &seekPreRollBuf,
+                                       &seekPreRollBufSize);
+    if (!isHeaderValid) {
+        ASSERT_EQ(opusHeadBuf, nullptr);
+    } else {
+        ASSERT_NE(opusHeadBuf, nullptr);
+    }
+    if (!isCodecDelayValid) {
+        ASSERT_EQ(codecDelayBuf, nullptr);
+    } else {
+        ASSERT_NE(codecDelayBuf, nullptr);
+    }
+    if (!isSeekPreRollValid) {
+        ASSERT_EQ(seekPreRollBuf, nullptr);
+    } else {
+        ASSERT_NE(seekPreRollBuf, nullptr);
+    }
+    if (!status) {
+        ASSERT_FALSE(isInputValid) << "GetOpusHeaderBuffers failed";
+        return;
+    }
+
+    status = ParseOpusHeader((uint8_t *)opusHeadBuf, opusHeadSize, &header);
+
+    if (status) {
+        ASSERT_TRUE(isInputValid) << "Parse opus header didn't fail for invalid input";
+    } else {
+        ASSERT_FALSE(isInputValid);
+        return;
+    }
+
+    int32_t channels = get<1>(params);
+    ASSERT_EQ(header.channels, channels) << "Parser returned invalid channel count";
+    ASSERT_LE(header.channels, kMaxChannels);
+
+    ASSERT_LE(header.num_coupled, header.num_streams)
+            << "Invalid header generated. Number of coupled streams cannot be greater than number "
+               "of streams.";
+
+    ASSERT_EQ(header.num_coupled + header.num_streams, header.channels);
+
+    if (header.channel_mapping) {
+        uint8_t mappedChannelNumber;
+        for (int32_t channelNumber = 0; channelNumber < channels; channelNumber++) {
+            mappedChannelNumber = *(reinterpret_cast<uint8_t *>(opusHeadBuf) +
+                                    kOpusHeaderStreamMapOffset + channelNumber);
+            ASSERT_LT(mappedChannelNumber, channels)
+                    << "Invalid header. Channel mapping cannot be greater than channel count.";
+
+            ASSERT_EQ(mappedChannelNumber, kOpusChannelMap[channels - 1][channelNumber])
+                    << "Invalid header generated. Channel mapping "
+                       "is not as per specification.";
+        }
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(OpusHeaderTestAll, OpusHeaderWriteTest,
+                         ::testing::Values(make_pair(1, 312),
+                                           make_pair(2, 312),
+                                           make_pair(5, 312),
+                                           make_pair(6, 312),
+                                           make_pair(1, 0),
+                                           make_pair(2, 0),
+                                           make_pair(5, 0),
+                                           make_pair(6, 0),
+                                           make_pair(1, 624),
+                                           make_pair(2, 624),
+                                           make_pair(5, 624),
+                                           make_pair(6, 624)));
+
+INSTANTIATE_TEST_SUITE_P(
+        OpusHeaderTestAll, OpusHeaderParseTest,
+        ::testing::Values(
+                make_tuple("2ch_valid_size83B.opus", 2, true, true, true, true),
+                make_tuple("3ch_valid_size88B.opus", 3, true, true, true, true),
+                make_tuple("5ch_valid.opus", 5, true, false, false, true),
+                make_tuple("6ch_valid.opus", 6, true, false, false, true),
+                make_tuple("1ch_valid.opus", 1, true, false, false, true),
+                make_tuple("2ch_valid.opus", 2, true, false, false, true),
+                make_tuple("3ch_invalid_size.opus", 3, true, true, true, false),
+                make_tuple("3ch_invalid_streams.opus", 3, true, true, true, false),
+                make_tuple("5ch_invalid_channelmapping.opus", 5, true, false, false, false),
+                make_tuple("5ch_invalid_coupledstreams.opus", 5, true, false, false, false),
+                make_tuple("6ch_invalid_channelmapping.opus", 6, true, false, false, false),
+                make_tuple("9ch_invalid_channels.opus", 9, true, true, true, false),
+                make_tuple("2ch_invalid_header.opus", 2, false, false, false, false),
+                make_tuple("2ch_invalid_headerlength_16.opus", 2, false, false, false, false),
+                make_tuple("2ch_invalid_headerlength_256.opus", 2, false, false, false, false),
+                make_tuple("2ch_invalid_size.opus", 2, false, false, false, false),
+                make_tuple("3ch_invalid_channelmapping_0.opus", 3, true, true, true, false),
+                make_tuple("3ch_invalid_coupledstreams.opus", 3, true, true, true, false),
+                make_tuple("3ch_invalid_headerlength.opus", 3, true, true, true, false),
+                make_tuple("3ch_invalid_headerSize1.opus", 3, false, false, false, false),
+                make_tuple("3ch_invalid_headerSize2.opus", 3, false, false, false, false),
+                make_tuple("3ch_invalid_headerSize3.opus", 3, false, false, false, false),
+                make_tuple("3ch_invalid_nodelay.opus", 3, false, false, false, false),
+                make_tuple("3ch_invalid_nopreroll.opus", 3, false, false, false, false)));
+
+int main(int argc, char **argv) {
+    gEnv = new OpusHeaderTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGD("Opus Header Test Result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h b/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h
new file mode 100644
index 0000000..d0163c3
--- /dev/null
+++ b/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OPUS_HEADER_TEST_ENVIRONMENT_H__
+#define __OPUS_HEADER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class OpusHeaderTestEnvironment : public ::testing::Environment {
+  public:
+    OpusHeaderTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int OpusHeaderTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P': {
+                setRes(optarg);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __OPUS_HEADER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/foundation/tests/OpusHeader/README.md b/media/libstagefright/foundation/tests/OpusHeader/README.md
new file mode 100644
index 0000000..860c827
--- /dev/null
+++ b/media/libstagefright/foundation/tests/OpusHeader/README.md
@@ -0,0 +1,39 @@
+## Media Testing ##
+---
+#### Opus Header
+The OpusHeader Test Suite validates the OPUS header available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m OpusHeaderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/OpusHeaderTest/OpusHeaderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/OpusHeaderTest/OpusHeaderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip). Download, unzip and push these files into device for testing.
+
+```
+adb push OpusHeader /data/local/tmp/
+```
+
+usage: OpusHeaderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/OpusHeaderTest -P /data/local/tmp/OpusHeader/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest OpusHeaderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.cpp b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
index 20a1468..46c4a7c 100644
--- a/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
@@ -156,9 +156,11 @@
     mStats->setDeInitTime(timeTaken);
 }
 
-void C2Decoder::dumpStatistics(string inputReference, int64_t durationUs) {
+void C2Decoder::dumpStatistics(string inputReference, int64_t durationUs, string componentName,
+                               string statsFile) {
     string operation = "c2decode";
-    mStats->dumpStatistics(operation, inputReference, durationUs);
+    string mode = "async";
+    mStats->dumpStatistics(operation, inputReference, durationUs, componentName, mode, statsFile);
 }
 
 void C2Decoder::resetDecoder() {
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.h b/media/tests/benchmark/src/native/decoder/C2Decoder.h
index 4a3eb96..fb35a66 100644
--- a/media/tests/benchmark/src/native/decoder/C2Decoder.h
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.h
@@ -31,7 +31,8 @@
 
     void deInitCodec();
 
-    void dumpStatistics(string inputReference, int64_t durationUs);
+    void dumpStatistics(string inputReference, int64_t durationUs, string componentName,
+                        string statsFile);
 
     void resetDecoder();
 
diff --git a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
index 33429ef..6a50d40 100644
--- a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
@@ -251,9 +251,11 @@
     mStats->setDeInitTime(timeTaken);
 }
 
-void C2Encoder::dumpStatistics(string inputReference, int64_t durationUs) {
+void C2Encoder::dumpStatistics(string inputReference, int64_t durationUs, string componentName,
+                               string statsFile) {
     string operation = "c2encode";
-    mStats->dumpStatistics(operation, inputReference, durationUs);
+    string mode = "async";
+    mStats->dumpStatistics(operation, inputReference, durationUs, componentName, mode, statsFile);
 }
 
 void C2Encoder::resetEncoder() {
diff --git a/media/tests/benchmark/src/native/encoder/C2Encoder.h b/media/tests/benchmark/src/native/encoder/C2Encoder.h
index a4ca097..7a021f4 100644
--- a/media/tests/benchmark/src/native/encoder/C2Encoder.h
+++ b/media/tests/benchmark/src/native/encoder/C2Encoder.h
@@ -44,7 +44,8 @@
 
     void deInitCodec();
 
-    void dumpStatistics(string inputReference, int64_t durationUs);
+    void dumpStatistics(string inputReference, int64_t durationUs, string componentName,
+                        string statsFile);
 
     void resetEncoder();
 
diff --git a/media/tests/benchmark/tests/BenchmarkTestEnvironment.h b/media/tests/benchmark/tests/BenchmarkTestEnvironment.h
index ae2eee1..4edb048 100644
--- a/media/tests/benchmark/tests/BenchmarkTestEnvironment.h
+++ b/media/tests/benchmark/tests/BenchmarkTestEnvironment.h
@@ -25,7 +25,9 @@
 
 class BenchmarkTestEnvironment : public ::testing::Environment {
   public:
-    BenchmarkTestEnvironment() : res("/sdcard/media/") {}
+    BenchmarkTestEnvironment()
+        : res("/data/local/tmp/MediaBenchmark/res/"),
+          statsFile("/data/local/tmp/MediaBenchmark/res/stats.csv") {}
 
     // Parses the command line argument
     int initFromOptions(int argc, char **argv);
@@ -34,8 +36,15 @@
 
     const string getRes() const { return res; }
 
+    void setStatsFile(const string module) { statsFile = getRes() + module; }
+
+    const string getStatsFile() const { return statsFile; }
+
+    bool writeStatsHeader();
+
   private:
     string res;
+    string statsFile;
 };
 
 int BenchmarkTestEnvironment::initFromOptions(int argc, char **argv) {
@@ -70,4 +79,26 @@
     return 0;
 }
 
+/**
+ * Writes the stats header to a file
+ * <p>
+ * \param statsFile    file where the stats data is to be written
+ **/
+bool BenchmarkTestEnvironment::writeStatsHeader() {
+    char statsHeader[] =
+        "currentTime, fileName, operation, componentName, NDK/SDK, sync/async, setupTime, "
+        "destroyTime, minimumTime, maximumTime, averageTime, timeToProcess1SecContent, "
+        "totalBytesProcessedPerSec, timeToFirstFrame, totalSizeInBytes, totalTime\n";
+    FILE *fpStats = fopen(statsFile.c_str(), "w");
+    if(!fpStats) {
+        return false;
+    }
+    int32_t numBytes = fwrite(statsHeader, sizeof(char), sizeof(statsHeader), fpStats);
+    fclose(fpStats);
+    if(numBytes != sizeof(statsHeader)) {
+        return false;
+    }
+    return true;
+}
+
 #endif  // __BENCHMARK_TEST_ENVIRONMENT_H__
diff --git a/media/tests/benchmark/tests/C2DecoderTest.cpp b/media/tests/benchmark/tests/C2DecoderTest.cpp
index dedc743..85dcbc1 100644
--- a/media/tests/benchmark/tests/C2DecoderTest.cpp
+++ b/media/tests/benchmark/tests/C2DecoderTest.cpp
@@ -136,7 +136,8 @@
                 mDecoder->deInitCodec();
                 int64_t durationUs = extractor->getClipDuration();
                 ALOGV("codec : %s", codecName.c_str());
-                mDecoder->dumpStatistics(GetParam().first, durationUs);
+                mDecoder->dumpStatistics(GetParam().first, durationUs, codecName,
+                                         gEnv->getStatsFile());
                 mDecoder->resetDecoder();
             }
         }
@@ -178,6 +179,9 @@
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
     if (status == 0) {
+        gEnv->setStatsFile("C2Decoder.csv");
+        status = gEnv->writeStatsHeader();
+        ALOGV("Stats file = %d\n", status);
         status = RUN_ALL_TESTS();
         ALOGV("C2 Decoder Test result = %d\n", status);
     }
diff --git a/media/tests/benchmark/tests/C2EncoderTest.cpp b/media/tests/benchmark/tests/C2EncoderTest.cpp
index 98eb17a..b18d856 100644
--- a/media/tests/benchmark/tests/C2EncoderTest.cpp
+++ b/media/tests/benchmark/tests/C2EncoderTest.cpp
@@ -108,7 +108,7 @@
         }
 
         string decName = "";
-        string outputFileName = "decode.out";
+        string outputFileName = "/data/local/tmp/decode.out";
         FILE *outFp = fopen(outputFileName.c_str(), "wb");
         ASSERT_NE(outFp, nullptr) << "Unable to open output file" << outputFileName
                                   << " for dumping decoder's output";
@@ -140,7 +140,8 @@
                 mEncoder->deInitCodec();
                 int64_t durationUs = extractor->getClipDuration();
                 ALOGV("codec : %s", codecName.c_str());
-                mEncoder->dumpStatistics(GetParam().first, durationUs);
+                mEncoder->dumpStatistics(GetParam().first, durationUs, codecName,
+                                         gEnv->getStatsFile());
                 mEncoder->resetEncoder();
             }
         }
@@ -180,6 +181,9 @@
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
     if (status == 0) {
+        gEnv->setStatsFile("C2Encoder.csv");
+        status = gEnv->writeStatsHeader();
+        ALOGV("Stats file = %d\n", status);
         status = RUN_ALL_TESTS();
         ALOGV("C2 Encoder Test result = %d\n", status);
     }
diff --git a/media/tests/benchmark/tests/DecoderTest.cpp b/media/tests/benchmark/tests/DecoderTest.cpp
index 9f96d3b..81ef02a 100644
--- a/media/tests/benchmark/tests/DecoderTest.cpp
+++ b/media/tests/benchmark/tests/DecoderTest.cpp
@@ -84,7 +84,8 @@
         decoder->deInitCodec();
         ALOGV("codec : %s", codecName.c_str());
         string inputReference = get<0>(params);
-        decoder->dumpStatistics(inputReference);
+        decoder->dumpStatistics(inputReference, codecName, (asyncMode ? "async" : "sync"),
+                                gEnv->getStatsFile());
         free(inputBuffer);
         decoder->resetDecoder();
     }
@@ -179,8 +180,11 @@
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
     if (status == 0) {
+        gEnv->setStatsFile("Decoder.csv");
+        status = gEnv->writeStatsHeader();
+        ALOGV("Stats file = %d\n", status);
         status = RUN_ALL_TESTS();
-        ALOGD("Decoder Test result = %d\n", status);
+        ALOGV("Decoder Test result = %d\n", status);
     }
     return status;
 }
\ No newline at end of file
diff --git a/media/tests/benchmark/tests/EncoderTest.cpp b/media/tests/benchmark/tests/EncoderTest.cpp
index dc2a2dd..faac847 100644
--- a/media/tests/benchmark/tests/EncoderTest.cpp
+++ b/media/tests/benchmark/tests/EncoderTest.cpp
@@ -78,7 +78,7 @@
         }
 
         string decName = "";
-        string outputFileName = "decode.out";
+        string outputFileName = "/data/local/tmp/decode.out";
         FILE *outFp = fopen(outputFileName.c_str(), "wb");
         ASSERT_NE(outFp, nullptr) << "Unable to open output file" << outputFileName
                                   << " for dumping decoder's output";
@@ -133,7 +133,8 @@
         encoder->deInitCodec();
         ALOGV("codec : %s", codecName.c_str());
         string inputReference = get<0>(params);
-        encoder->dumpStatistics(inputReference, extractor->getClipDuration());
+        encoder->dumpStatistics(inputReference, extractor->getClipDuration(), codecName,
+                                (asyncMode ? "async" : "sync"), gEnv->getStatsFile());
         eleStream.close();
         if (outFp) fclose(outFp);
 
@@ -214,8 +215,11 @@
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
     if (status == 0) {
+        gEnv->setStatsFile("Encoder.csv");
+        status = gEnv->writeStatsHeader();
+        ALOGV("Stats file = %d\n", status);
         status = RUN_ALL_TESTS();
-        ALOGD("Encoder Test result = %d\n", status);
+        ALOGV("Encoder Test result = %d\n", status);
     }
     return status;
 }
diff --git a/media/tests/benchmark/tests/ExtractorTest.cpp b/media/tests/benchmark/tests/ExtractorTest.cpp
index ad8f1e6..d14d15b 100644
--- a/media/tests/benchmark/tests/ExtractorTest.cpp
+++ b/media/tests/benchmark/tests/ExtractorTest.cpp
@@ -48,8 +48,7 @@
     ASSERT_EQ(status, AMEDIA_OK) << "Extraction failed \n";
 
     extractObj->deInitExtractor();
-
-    extractObj->dumpStatistics(GetParam().first);
+    extractObj->dumpStatistics(GetParam().first, "", gEnv->getStatsFile());
 
     fclose(inputFp);
     delete extractObj;
@@ -79,8 +78,11 @@
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
     if (status == 0) {
+        gEnv->setStatsFile("Extractor.csv");
+        status = gEnv->writeStatsHeader();
+        ALOGV("Stats file = %d\n", status);
         status = RUN_ALL_TESTS();
-        ALOGD(" Extractor Test result = %d\n", status);
+        ALOGV("Extractor Test result = %d\n", status);
     }
     return status;
 }
diff --git a/media/tests/benchmark/tests/MuxerTest.cpp b/media/tests/benchmark/tests/MuxerTest.cpp
index fa2635d..991644b 100644
--- a/media/tests/benchmark/tests/MuxerTest.cpp
+++ b/media/tests/benchmark/tests/MuxerTest.cpp
@@ -113,7 +113,7 @@
         ASSERT_EQ(status, 0) << "Mux failed";
 
         muxerObj->deInitMuxer();
-        muxerObj->dumpStatistics(GetParam().first + "." + fmt.c_str());
+        muxerObj->dumpStatistics(GetParam().first + "." + fmt.c_str(), fmt, gEnv->getStatsFile());
         free(inputBuffer);
         fclose(outputFp);
         muxerObj->resetMuxer();
@@ -151,8 +151,11 @@
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
     if (status == 0) {
+        gEnv->setStatsFile("Muxer.csv");
+        status = gEnv->writeStatsHeader();
+        ALOGV("Stats file = %d\n", status);
         status = RUN_ALL_TESTS();
-        ALOGV("Test result = %d\n", status);
+        ALOGV("Muxer Test result = %d\n", status);
     }
     return status;
 }
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index fe15ff6..151c7bb 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -73,10 +73,18 @@
 audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
         const audio_attributes_t &attr) const
 {
-    const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
+    const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
                                    [&attr](const auto &supportedAttr) {
         return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr); });
-    return iter != end(mAttributesVector) ? iter->mStream : AUDIO_STREAM_DEFAULT;
+    if (iter == end(mAttributesVector)) {
+        return AUDIO_STREAM_DEFAULT;
+    }
+    audio_stream_type_t streamType = iter->mStream;
+    ALOGW_IF(streamType == AUDIO_STREAM_DEFAULT,
+             "%s: Strategy %s supporting attributes %s has not stream type associated"
+             "fallback on MUSIC. Do not use stream volume API", __func__, mName.c_str(),
+             toString(attr).c_str());
+    return streamType != AUDIO_STREAM_DEFAULT ? streamType : AUDIO_STREAM_MUSIC;
 }
 
 audio_attributes_t ProductStrategy::getAttributesForStreamType(audio_stream_type_t streamType) const
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ffc3a0f..016c340 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2457,6 +2457,10 @@
                                                   audio_devices_t device)
 {
     auto attributes = mEngine->getAttributesForStreamType(stream);
+    if (attributes == AUDIO_ATTRIBUTES_INITIALIZER) {
+        ALOGW("%s: no group for stream %s, bailing out", __func__, toString(stream).c_str());
+        return NO_ERROR;
+    }
     ALOGV("%s: stream %s attributes=%s", __func__,
           toString(stream).c_str(), toString(attributes).c_str());
     return setVolumeIndexForAttributes(attributes, index, device);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 9bc79e0..42fdbea 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -794,7 +794,7 @@
 
 Status CameraService::makeClient(const sp<CameraService>& cameraService,
         const sp<IInterface>& cameraCb, const String16& packageName,
-        const std::unique_ptr<String16>& featureId, const String8& cameraId, int api1CameraId,
+        const std::optional<String16>& featureId, const String8& cameraId, int api1CameraId,
         int facing, int clientPid, uid_t clientUid, int servicePid, int halVersion,
         int deviceVersion, apiLevel effectiveApiLevel,
         /*out*/sp<BasicClient>* client) {
@@ -950,7 +950,7 @@
     if (!(ret = connectHelper<ICameraClient,Client>(
             sp<ICameraClient>{nullptr}, id, cameraId,
             static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED),
-            internalPackageName, std::unique_ptr<String16>(), uid, USE_CALLING_PID,
+            internalPackageName, {}, uid, USE_CALLING_PID,
             API_1, /*shimUpdateOnly*/ true, /*out*/ tmp)
             ).isOk()) {
         ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string());
@@ -1463,7 +1463,7 @@
     String8 id = cameraIdIntToStr(api1CameraId);
     sp<Client> client = nullptr;
     ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
-            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, std::unique_ptr<String16>(),
+            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, {},
             clientUid, clientPid, API_1, /*shimUpdateOnly*/ false, /*out*/client);
 
     if(!ret.isOk()) {
@@ -1490,7 +1490,7 @@
     Status ret = Status::ok();
     sp<Client> client = nullptr;
     ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId, halVersion,
-            clientPackageName, std::unique_ptr<String16>(), clientUid, USE_CALLING_PID, API_1,
+            clientPackageName, {}, clientUid, USE_CALLING_PID, API_1,
             /*shimUpdateOnly*/ false, /*out*/client);
 
     if(!ret.isOk()) {
@@ -1565,7 +1565,7 @@
         const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
         const String16& cameraId,
         const String16& clientPackageName,
-        const std::unique_ptr<String16>& clientFeatureId,
+        const std::optional<String16>& clientFeatureId,
         int clientUid,
         /*out*/
         sp<hardware::camera2::ICameraDeviceUser>* device) {
@@ -1599,7 +1599,7 @@
 template<class CALLBACK, class CLIENT>
 Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
         int api1CameraId, int halVersion, const String16& clientPackageName,
-        const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
+        const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
         apiLevel effectiveApiLevel, bool shimUpdateOnly,
         /*out*/sp<CLIENT>& device) {
     binder::Status ret = binder::Status::ok();
@@ -2697,7 +2697,7 @@
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
         const String16& clientPackageName,
-        const std::unique_ptr<String16>& clientFeatureId,
+        const std::optional<String16>& clientFeatureId,
         const String8& cameraIdStr,
         int api1CameraId, int cameraFacing,
         int clientPid, uid_t clientUid,
@@ -2734,24 +2734,18 @@
 
 CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
         const sp<IBinder>& remoteCallback,
-        const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
+        const String16& clientPackageName, const std::optional<String16>& clientFeatureId,
         const String8& cameraIdStr, int cameraFacing,
         int clientPid, uid_t clientUid,
         int servicePid):
         mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing),
-        mClientPackageName(clientPackageName),
+        mClientPackageName(clientPackageName), mClientFeatureId(clientFeatureId),
         mClientPid(clientPid), mClientUid(clientUid),
         mServicePid(servicePid),
         mDisconnected(false),
         mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
         mRemoteBinder(remoteCallback)
 {
-    if (clientFeatureId) {
-        mClientFeatureId = std::unique_ptr<String16>(new String16(*clientFeatureId));
-    } else {
-        mClientFeatureId = std::unique_ptr<String16>();
-    }
-
     if (sCameraService == nullptr) {
         sCameraService = cameraService;
     }
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 1adf15a..83b551f 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -51,6 +51,7 @@
 #include <string>
 #include <map>
 #include <memory>
+#include <optional>
 #include <utility>
 #include <unordered_map>
 #include <unordered_set>
@@ -141,7 +142,7 @@
 
     virtual binder::Status     connectDevice(
             const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const String16& cameraId,
-            const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
+            const String16& clientPackageName, const std::optional<String16>& clientFeatureId,
             int32_t clientUid,
             /*out*/
             sp<hardware::camera2::ICameraDeviceUser>* device);
@@ -298,7 +299,7 @@
         BasicClient(const sp<CameraService>& cameraService,
                 const sp<IBinder>& remoteCallback,
                 const String16& clientPackageName,
-                const std::unique_ptr<String16>& clientFeatureId,
+                const std::optional<String16>& clientFeatureId,
                 const String8& cameraIdStr,
                 int cameraFacing,
                 int clientPid,
@@ -318,7 +319,7 @@
         const String8                   mCameraIdStr;
         const int                       mCameraFacing;
         String16                        mClientPackageName;
-        std::unique_ptr<String16>       mClientFeatureId;
+        std::optional<String16>         mClientFeatureId;
         pid_t                           mClientPid;
         const uid_t                     mClientUid;
         const pid_t                     mServicePid;
@@ -389,7 +390,7 @@
         Client(const sp<CameraService>& cameraService,
                 const sp<hardware::ICameraClient>& cameraClient,
                 const String16& clientPackageName,
-                const std::unique_ptr<String16>& clientFeatureId,
+                const std::optional<String16>& clientFeatureId,
                 const String8& cameraIdStr,
                 int api1CameraId,
                 int cameraFacing,
@@ -727,7 +728,7 @@
     template<class CALLBACK, class CLIENT>
     binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
             int api1CameraId, int halVersion, const String16& clientPackageName,
-            const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
+            const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
             apiLevel effectiveApiLevel, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
 
     // Lock guarding camera service state
@@ -1055,7 +1056,7 @@
 
     static binder::Status makeClient(const sp<CameraService>& cameraService,
             const sp<IInterface>& cameraCb, const String16& packageName,
-            const std::unique_ptr<String16>& featureId, const String8& cameraId, int api1CameraId,
+            const std::optional<String16>& featureId, const String8& cameraId, int api1CameraId,
             int facing, int clientPid, uid_t clientUid, int servicePid, int halVersion,
             int deviceVersion, apiLevel effectiveApiLevel,
             /*out*/sp<BasicClient>* client);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 1d62a74..e01e86d 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -50,7 +50,7 @@
 Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
         const sp<hardware::ICameraClient>& cameraClient,
         const String16& clientPackageName,
-        const std::unique_ptr<String16>& clientFeatureId,
+        const std::optional<String16>& clientFeatureId,
         const String8& cameraDeviceId,
         int api1CameraId,
         int cameraFacing,
@@ -733,6 +733,10 @@
 
     ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);
 
+    if (params.state == Parameters::DISCONNECTED) {
+        ALOGE("%s: Camera %d has been disconnected.", __FUNCTION__, mCameraId);
+        return INVALID_OPERATION;
+    }
     if ( (params.state == Parameters::PREVIEW ||
                     params.state == Parameters::RECORD ||
                     params.state == Parameters::VIDEO_SNAPSHOT)
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 3144e0e..c5f0428 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -94,7 +94,7 @@
     Camera2Client(const sp<CameraService>& cameraService,
             const sp<hardware::ICameraClient>& cameraClient,
             const String16& clientPackageName,
-            const std::unique_ptr<String16>& clientFeatureId,
+            const std::optional<String16>& clientFeatureId,
             const String8& cameraDeviceId,
             int api1CameraId,
             int cameraFacing,
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 892996c..b860ceb 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -34,7 +34,7 @@
 
 CameraClient::CameraClient(const sp<CameraService>& cameraService,
         const sp<hardware::ICameraClient>& cameraClient,
-        const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
+        const String16& clientPackageName, const std::optional<String16>& clientFeatureId,
         int cameraId, int cameraFacing,
         int clientPid, int clientUid,
         int servicePid):
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index a7eb960..aacb00e 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -68,7 +68,7 @@
     CameraClient(const sp<CameraService>& cameraService,
             const sp<hardware::ICameraClient>& cameraClient,
             const String16& clientPackageName,
-            const std::unique_ptr<String16>& clientFeatureId,
+            const std::optional<String16>& clientFeatureId,
             int cameraId,
             int cameraFacing,
             int clientPid,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index e35b436..022d686 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -54,7 +54,7 @@
         const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         const String16& clientPackageName,
-        const std::unique_ptr<String16>& clientFeatureId,
+        const std::optional<String16>& clientFeatureId,
         const String8& cameraId,
         int api1CameraId,
         int cameraFacing,
@@ -80,7 +80,7 @@
 CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         const String16& clientPackageName,
-        const std::unique_ptr<String16>& clientFeatureId,
+        const std::optional<String16>& clientFeatureId,
         const String8& cameraId,
         int cameraFacing,
         int clientPid,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 964c96a..e7e26da 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -50,7 +50,7 @@
     CameraDeviceClientBase(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
-            const std::unique_ptr<String16>& clientFeatureId,
+            const std::optional<String16>& clientFeatureId,
             const String8& cameraId,
             int api1CameraId,
             int cameraFacing,
@@ -175,7 +175,7 @@
     CameraDeviceClient(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
-            const std::unique_ptr<String16>& clientFeatureId,
+            const std::optional<String16>& clientFeatureId,
             const String8& cameraId,
             int cameraFacing,
             int clientPid,
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index b67fcb3..03621c8 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -48,7 +48,7 @@
             const KeyedVector<sp<IBinder>, sp<CompositeStream>>& offlineCompositeStreamMap,
             const sp<ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
-            const std::unique_ptr<String16>& clientFeatureId,
+            const std::optional<String16>& clientFeatureId,
             const String8& cameraIdStr, int cameraFacing,
             int clientPid, uid_t clientUid, int servicePid) :
             CameraService::BasicClient(
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 0a41776..609698c 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -44,7 +44,7 @@
         const sp<CameraService>& cameraService,
         const sp<TCamCallbacks>& remoteCallback,
         const String16& clientPackageName,
-        const std::unique_ptr<String16>& clientFeatureId,
+        const std::optional<String16>& clientFeatureId,
         const String8& cameraId,
         int api1CameraId,
         int cameraFacing,
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 042f5aa..d7506af 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -48,7 +48,7 @@
     Camera2ClientBase(const sp<CameraService>& cameraService,
                       const sp<TCamCallbacks>& remoteCallback,
                       const String16& clientPackageName,
-                      const std::unique_ptr<String16>& clientFeatureId,
+                      const std::optional<String16>& clientFeatureId,
                       const String8& cameraId,
                       int api1CameraId,
                       int cameraFacing,
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index a46133e..9ea9526 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -103,7 +103,7 @@
     }
     sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
     binder::Status serviceRet = mAidlICameraService->connectDevice(
-            callbacks, String16(cameraId.c_str()), String16(""), std::unique_ptr<String16>(),
+            callbacks, String16(cameraId.c_str()), String16(""), {},
             hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
     HStatus status = HStatus::NO_ERROR;
     if (!serviceRet.isOk()) {
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index b909ea4..e582316 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -34,9 +34,6 @@
         "liblog",
         "libavservices_minijail",
     ],
-    header_libs: [
-        "bionic_libc_platform_headers",
-    ],
     target: {
         android: {
             product_variables: {
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 9992d1c..71a5bff 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -39,23 +39,23 @@
 
 ::android::binder::Status MediaExtractorService::makeExtractor(
         const ::android::sp<::android::IDataSource>& remoteSource,
-        const ::std::unique_ptr< ::std::string> &mime,
+        const ::std::optional< ::std::string> &mime,
         ::android::sp<::android::IMediaExtractor>* _aidl_return) {
-    ALOGV("@@@ MediaExtractorService::makeExtractor for %s", mime.get()->c_str());
+    ALOGV("@@@ MediaExtractorService::makeExtractor for %s", mime ? mime->c_str() : nullptr);
 
     sp<DataSource> localSource = CreateDataSourceFromIDataSource(remoteSource);
 
     MediaBuffer::useSharedMemory();
     sp<IMediaExtractor> extractor = MediaExtractorFactory::CreateFromService(
             localSource,
-            mime.get() ? mime.get()->c_str() : nullptr);
+            mime ? mime->c_str() : nullptr);
 
     ALOGV("extractor service created %p (%s)",
             extractor.get(),
             extractor == nullptr ? "" : extractor->name());
 
     if (extractor != nullptr) {
-        registerMediaExtractor(extractor, localSource, mime.get() ? mime.get()->c_str() : nullptr);
+        registerMediaExtractor(extractor, localSource, mime ? mime->c_str() : nullptr);
     }
     *_aidl_return = extractor;
     return binder::Status::ok();
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index 1b40bf9..0081e7e 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -33,7 +33,7 @@
 
     virtual ::android::binder::Status makeExtractor(
             const ::android::sp<::android::IDataSource>& source,
-            const ::std::unique_ptr< ::std::string> &mime,
+            const ::std::optional< ::std::string> &mime,
             ::android::sp<::android::IMediaExtractor>* _aidl_return);
 
     virtual ::android::binder::Status makeIDataSource(
diff --git a/services/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
index b116b14..4d1fa8e 100644
--- a/services/mediaextractor/main_extractorservice.cpp
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -28,8 +28,6 @@
 #include <android-base/properties.h>
 #include <utils/misc.h>
 
-#include <bionic/reserved_signals.h>
-
 // from LOCAL_C_INCLUDES
 #include "MediaExtractorService.h"
 #include "minijail.h"
@@ -50,10 +48,6 @@
 
     signal(SIGPIPE, SIG_IGN);
 
-    // Do not assist platform profilers (relevant only on debug builds).
-    // Otherwise, the signal handler can violate the seccomp policy.
-    signal(BIONIC_SIGNAL_PROFILER, SIG_IGN);
-
     //b/62255959: this forces libutis.so to dlopen vendor version of libutils.so
     //before minijail is on. This is dirty but required since some syscalls such
     //as pread64 are used by linker but aren't allowed in the minijail. By
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index f500c62..92048c3 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -41,7 +41,7 @@
 using ::aidl::android::media::MediaResourcePolicyParcel;
 
 typedef std::map<std::tuple<
-        MediaResource::Type, MediaResource::SubType, std::vector<int8_t>>,
+        MediaResource::Type, MediaResource::SubType, std::vector<uint8_t>>,
         MediaResourceParcel> ResourceList;
 
 struct ResourceInfo {