Merge changes I446495dc,I5c5de9d4

* changes:
  Added mp4_extractor_fuzzer
  Added ExtractorFuzzerBase class
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index fae0674..98d2fde 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -501,7 +501,7 @@
 status_t C2SoftAvcDec::initDecoder() {
     if (OK != createDecoder()) return UNKNOWN_ERROR;
     mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
-    mStride = ALIGN128(mWidth);
+    mStride = ALIGN32(mWidth);
     mSignalledError = false;
     resetPlugin();
     (void) setNumCores();
@@ -519,10 +519,20 @@
                                  size_t inSize,
                                  uint32_t tsMarker) {
     uint32_t displayStride = mStride;
+    if (outBuffer) {
+        C2PlanarLayout layout;
+        layout = outBuffer->layout();
+        displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+    }
     uint32_t displayHeight = mHeight;
     size_t lumaSize = displayStride * displayHeight;
     size_t chromaSize = lumaSize >> 2;
 
+    if (mStride != displayStride) {
+        mStride = displayStride;
+        if (OK != setParams(mStride, IVD_DECODE_FRAME)) return false;
+    }
+
     ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
     ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
     if (inBuffer) {
@@ -756,24 +766,21 @@
         ALOGE("not supposed to be here, invalid decoder context");
         return C2_CORRUPTED;
     }
-    if (mStride != ALIGN128(mWidth)) {
-        mStride = ALIGN128(mWidth);
-        if (OK != setParams(mStride, IVD_DECODE_FRAME)) return C2_CORRUPTED;
-    }
     if (mOutBlock &&
-            (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
+            (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
         mOutBlock.reset();
     }
     if (!mOutBlock) {
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
-        c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
+        c2_status_t err =
+            pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
         if (err != C2_OK) {
             ALOGE("fetchGraphicBlock for Output failed with status %d", err);
             return err;
         }
         ALOGV("provided (%dx%d) required (%dx%d)",
-              mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
+              mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
     }
 
     return C2_OK;
@@ -908,7 +915,8 @@
         if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
             if (mHeaderDecoded == false) {
                 mHeaderDecoded = true;
-                setParams(ALIGN128(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
+                mStride = ALIGN32(s_decode_op.u4_pic_wd);
+                setParams(mStride, IVD_DECODE_FRAME);
             }
             if (s_decode_op.u4_pic_wd != mWidth || s_decode_op.u4_pic_ht != mHeight) {
                 mWidth = s_decode_op.u4_pic_wd;
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index ed27493..bd84de0 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -39,8 +39,7 @@
 #define ivdext_ctl_set_num_cores_op_t   ih264d_ctl_set_num_cores_op_t
 #define ivdext_ctl_get_vui_params_ip_t  ih264d_ctl_get_vui_params_ip_t
 #define ivdext_ctl_get_vui_params_op_t  ih264d_ctl_get_vui_params_op_t
-#define ALIGN64(x)                      ((((x) + 63) >> 6) << 6)
-#define ALIGN128(x)                     ((((x) + 127) >> 7) << 7)
+#define ALIGN32(x)                      ((((x) + 31) >> 5) << 5)
 #define MAX_NUM_CORES                   4
 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
         (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index e3d419c..ab93ce3 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -103,7 +103,7 @@
 
         addParameter(
                 DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
-                .withDefault(new C2StreamPictureSizeInfo::input(0u, 320, 240))
+                .withDefault(new C2StreamPictureSizeInfo::input(0u, 16, 16))
                 .withFields({
                     C2F(mSize, width).inRange(2, 2560, 2),
                     C2F(mSize, height).inRange(2, 2560, 2),
@@ -129,7 +129,7 @@
 
         addParameter(
                 DefineParam(mFrameRate, C2_PARAMKEY_FRAME_RATE)
-                .withDefault(new C2StreamFrameRateInfo::output(0u, 30.))
+                .withDefault(new C2StreamFrameRateInfo::output(0u, 1.))
                 // TODO: More restriction?
                 .withFields({C2F(mFrameRate, value).greaterThan(0.)})
                 .withSetter(Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 6db4387..e4b911d 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -497,7 +497,7 @@
 status_t C2SoftHevcDec::initDecoder() {
     if (OK != createDecoder()) return UNKNOWN_ERROR;
     mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
-    mStride = ALIGN128(mWidth);
+    mStride = ALIGN32(mWidth);
     mSignalledError = false;
     resetPlugin();
     (void) setNumCores();
@@ -515,10 +515,20 @@
                                   size_t inSize,
                                   uint32_t tsMarker) {
     uint32_t displayStride = mStride;
+    if (outBuffer) {
+        C2PlanarLayout layout;
+        layout = outBuffer->layout();
+        displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+    }
     uint32_t displayHeight = mHeight;
     size_t lumaSize = displayStride * displayHeight;
     size_t chromaSize = lumaSize >> 2;
 
+    if (mStride != displayStride) {
+        mStride = displayStride;
+        if (OK != setParams(mStride, IVD_DECODE_FRAME)) return false;
+    }
+
     ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
     ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
     if (inBuffer) {
@@ -752,24 +762,21 @@
         ALOGE("not supposed to be here, invalid decoder context");
         return C2_CORRUPTED;
     }
-    if (mStride != ALIGN128(mWidth)) {
-        mStride = ALIGN128(mWidth);
-        if (OK != setParams(mStride, IVD_DECODE_FRAME)) return C2_CORRUPTED;
-    }
     if (mOutBlock &&
-            (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
+            (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
         mOutBlock.reset();
     }
     if (!mOutBlock) {
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
-        c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
+        c2_status_t err =
+            pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
         if (err != C2_OK) {
             ALOGE("fetchGraphicBlock for Output failed with status %d", err);
             return err;
         }
         ALOGV("provided (%dx%d) required (%dx%d)",
-              mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
+              mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
     }
 
     return C2_OK;
@@ -904,7 +911,7 @@
         if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
             if (mHeaderDecoded == false) {
                 mHeaderDecoded = true;
-                setParams(ALIGN128(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
+                setParams(ALIGN32(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
             }
             if (s_decode_op.u4_pic_wd != mWidth ||  s_decode_op.u4_pic_ht != mHeight) {
                 mWidth = s_decode_op.u4_pic_wd;
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h
index aecd101..600d7c1 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.h
+++ b/media/codec2/components/hevc/C2SoftHevcDec.h
@@ -37,8 +37,7 @@
 #define ivdext_ctl_set_num_cores_op_t   ihevcd_cxa_ctl_set_num_cores_op_t
 #define ivdext_ctl_get_vui_params_ip_t  ihevcd_cxa_ctl_get_vui_params_ip_t
 #define ivdext_ctl_get_vui_params_op_t  ihevcd_cxa_ctl_get_vui_params_op_t
-#define ALIGN64(x)                      ((((x) + 63) >> 6) << 6)
-#define ALIGN128(x)                     ((((x) + 127) >> 7) << 7)
+#define ALIGN32(x)                      ((((x) + 31) >> 5) << 5)
 #define MAX_NUM_CORES                   4
 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
         (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index df7b403..82cae7c 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -564,7 +564,7 @@
     if (OK != createDecoder()) return UNKNOWN_ERROR;
 
     mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
-    mStride = ALIGN64(mWidth);
+    mStride = ALIGN32(mWidth);
     mSignalledError = false;
     resetPlugin();
     (void) setNumCores();
@@ -582,10 +582,20 @@
                                    size_t inSize,
                                    uint32_t tsMarker) {
     uint32_t displayStride = mStride;
+    if (outBuffer) {
+        C2PlanarLayout layout;
+        layout = outBuffer->layout();
+        displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+    }
     uint32_t displayHeight = mHeight;
     size_t lumaSize = displayStride * displayHeight;
     size_t chromaSize = lumaSize >> 2;
 
+    if (mStride != displayStride) {
+        mStride = displayStride;
+        if (OK != setParams(mStride)) return false;
+    }
+
     ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
     ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
     if (inBuffer) {
@@ -826,24 +836,21 @@
         ALOGE("not supposed to be here, invalid decoder context");
         return C2_CORRUPTED;
     }
-    if (mStride != ALIGN64(mWidth)) {
-        mStride = ALIGN64(mWidth);
-        if (OK != setParams(mStride)) return C2_CORRUPTED;
-    }
     if (mOutBlock &&
-            (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
+            (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
         mOutBlock.reset();
     }
     if (!mOutBlock) {
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
-        c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
+        c2_status_t err =
+            pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
         if (err != C2_OK) {
             ALOGE("fetchGraphicBlock for Output failed with status %d", err);
             return err;
         }
         ALOGV("provided (%dx%d) required (%dx%d)",
-              mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
+              mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
     }
 
     return C2_OK;
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
index 65d3b87..fd66304a 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
@@ -37,7 +37,7 @@
 #define ivdext_ctl_set_num_cores_op_t   impeg2d_ctl_set_num_cores_op_t
 #define ivdext_ctl_get_seq_info_ip_t    impeg2d_ctl_get_seq_info_ip_t
 #define ivdext_ctl_get_seq_info_op_t    impeg2d_ctl_get_seq_info_op_t
-#define ALIGN64(x)                      ((((x) + 63) >> 6) << 6)
+#define ALIGN32(x)                      ((((x) + 31) >> 5) << 5)
 #define MAX_NUM_CORES                   4
 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
         (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES
diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp
index 6c94754..2c2d11d 100644
--- a/media/libstagefright/timedtext/TextDescriptions.cpp
+++ b/media/libstagefright/timedtext/TextDescriptions.cpp
@@ -504,7 +504,7 @@
                             return OK;
                         }
 
-                        parcel->write(tmpData, len);
+                        parcel->writeByteArray(len, tmpData);
                         tmpData += len;
                         subChunkRemaining -= len;
                     }
diff --git a/media/libstagefright/timedtext/test/AndroidTest.xml b/media/libstagefright/timedtext/test/AndroidTest.xml
index 8925790..3654e23 100644
--- a/media/libstagefright/timedtext/test/AndroidTest.xml
+++ b/media/libstagefright/timedtext/test/AndroidTest.xml
@@ -25,7 +25,7 @@
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="TimedTextUnitTestt" />
+        <option name="module-name" value="TimedTextUnitTest" />
         <option name="native-test-flag" value="-P /data/local/tmp/TimedTextUnitTestRes/" />
     </test>
 </configuration>
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index a232150..3be5e74 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -1525,7 +1525,7 @@
                 nodeInfo.attributeList.push_back(Attribute{"rank", rank});
             }
             nodeList->insert(std::make_pair(
-                    std::move(order), std::move(nodeInfo)));
+                    order, std::move(nodeInfo)));
         }
     }
 }
diff --git a/media/libstagefright/xmlparser/test/Android.bp b/media/libstagefright/xmlparser/test/Android.bp
new file mode 100644
index 0000000..6d97c96
--- /dev/null
+++ b/media/libstagefright/xmlparser/test/Android.bp
@@ -0,0 +1,52 @@
+/*
+ * 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: "XMLParserTest",
+    gtest: true,
+
+    srcs: [
+        "XMLParserTest.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libstagefright_xmlparser",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    data: [":xmlparsertest_test_files",],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
+
+filegroup {
+    name: "xmlparsertest_test_files",
+    srcs: [
+        "testdata/media_codecs_unit_test.xml",
+        "testdata/media_codecs_unit_test_caller.xml",
+    ],
+}
diff --git a/media/libstagefright/xmlparser/test/AndroidTest.xml b/media/libstagefright/xmlparser/test/AndroidTest.xml
new file mode 100644
index 0000000..2e11b1b
--- /dev/null
+++ b/media/libstagefright/xmlparser/test/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?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 xml parser unit test">
+    <option name="test-suite-tag" value="XMLParserTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="media_codecs_unit_test.xml->/data/local/tmp/media_codecs_unit_test.xml" />
+        <option name="push" value="media_codecs_unit_test_caller.xml->/data/local/tmp/media_codecs_unit_test_caller.xml" />
+        <option name="push" value="XMLParserTest->/data/local/tmp/XMLParserTest" />
+    </target_preparer>
+   <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="XMLParserTest" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/xmlparser/test/README.md b/media/libstagefright/xmlparser/test/README.md
new file mode 100644
index 0000000..e9363fd
--- /dev/null
+++ b/media/libstagefright/xmlparser/test/README.md
@@ -0,0 +1,33 @@
+## Media Testing ##
+---
+#### XML Parser
+The XMLParser Test Suite validates the XMLParser available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m XMLParserTest
+```
+
+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/XMLParserTest/XMLParserTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/XMLParserTest/XMLParserTest /data/local/tmp/
+```
+
+usage: XMLParserTest
+```
+adb shell /data/local/tmp/XMLParserTest
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest XMLParserTest
+```
diff --git a/media/libstagefright/xmlparser/test/XMLParserTest.cpp b/media/libstagefright/xmlparser/test/XMLParserTest.cpp
new file mode 100644
index 0000000..9ddd374
--- /dev/null
+++ b/media/libstagefright/xmlparser/test/XMLParserTest.cpp
@@ -0,0 +1,392 @@
+/*
+ * 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 "XMLParserTest"
+
+#include <utils/Log.h>
+
+#include <fstream>
+
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+
+#include "XMLParserTestEnvironment.h"
+
+#define XML_FILE_NAME "media_codecs_unit_test_caller.xml"
+
+using namespace android;
+
+static XMLParserTestEnvironment *gEnv = nullptr;
+
+struct CodecProperties {
+    string codecName;
+    MediaCodecsXmlParser::CodecProperties codecProp;
+};
+
+struct RoleProperties {
+    string roleName;
+    string typeName;
+    string codecName;
+    bool isEncoder;
+    size_t order;
+    vector<pair<string, string>> attributeMap;
+};
+
+class XMLParseTest : public ::testing::Test {
+  public:
+    ~XMLParseTest() {
+        if (mEleStream.is_open()) mEleStream.close();
+        mInputDataVector.clear();
+        mInputRoleVector.clear();
+    }
+
+    virtual void SetUp() override { setUpDatabase(); }
+
+    void setUpDatabase();
+
+    void setCodecProperties(string codecName, bool isEncoder, int32_t order, set<string> quirkSet,
+                            set<string> domainSet, set<string> variantSet, string typeName,
+                            vector<pair<string, string>> domain, vector<string> aliases,
+                            string rank);
+
+    void setRoleProperties(string roleName, bool isEncoder, int32_t order, string typeName,
+                           string codecName, vector<pair<string, string>> domain);
+
+    void setServiceAttribute(map<string, string> serviceAttributeNameValuePair);
+
+    void printCodecMap(const MediaCodecsXmlParser::Codec mcodec);
+
+    void checkRoleMap(int32_t index, bool isEncoder, string typeName, string codecName,
+                      vector<pair<string, string>> attrMap);
+
+    bool compareMap(const map<string, string> &lhs, const map<string, string> &rhs);
+
+    ifstream mEleStream;
+    MediaCodecsXmlParser mParser;
+    vector<CodecProperties> mInputDataVector;
+    vector<RoleProperties> mInputRoleVector;
+    map<string, string> mInputServiceAttributeMap;
+};
+
+void XMLParseTest::setUpDatabase() {
+    // The values set below are specific to test vector testdata/media_codecs_unit_test.xml
+    setCodecProperties("test1.decoder", false, 1, {"attribute::disabled", "quirk::quirk1"},
+                       {"telephony"}, {}, "audio/mpeg", {}, {"alias1.decoder"}, "4");
+
+    setCodecProperties("test2.decoder", false, 2, {"quirk::quirk1"}, {}, {}, "audio/3gpp", {}, {},
+                       "");
+
+    setCodecProperties("test3.decoder", false, 3, {}, {}, {}, "audio/amr-wb",
+                       {
+                               pair<string, string>("feature-feature1", "feature1Val"),
+                               pair<string, string>("feature-feature2", "0"),
+                               pair<string, string>("feature-feature3", "0"),
+                       },
+                       {}, "");
+
+    setCodecProperties("test4.decoder", false, 4, {}, {}, {}, "audio/flac",
+                       {pair<string, string>("feature-feature1", "feature1Val")}, {}, "");
+
+    setCodecProperties("test5.decoder", false, 5, {"attribute::attributeQuirk1"}, {}, {},
+                       "audio/g711-mlaw", {}, {}, "");
+
+    setCodecProperties("test6.decoder", false, 6, {}, {}, {"variant1", "variant2"},
+                       "audio/mp4a-latm",
+                       {pair<string, string>("variant1:::variant1Limit1-range",
+                                             "variant1Limit1Min-variant1Limit1Max"),
+                        pair<string, string>("variant1:::variant1Limit2-range",
+                                             "variant1Limit2Low-variant1Limit2High"),
+                        pair<string, string>("variant2:::variant2Limit1", "variant2Limit1Value")},
+                       {}, "");
+
+    setCodecProperties(
+            "test7.decoder", false, 7, {}, {}, {}, "audio/vorbis",
+            {
+                    pair<string, string>("-min-limit1", "limit1Min"),
+                    /*pair<string, string>("limit1-in", "limit1In"),*/
+                    pair<string, string>("limit2-range", "limit2Min-limit2Max"),
+                    pair<string, string>("limit2-scale", "limit2Scale"),
+                    pair<string, string>("limit3-default", "limit3Val3"),
+                    pair<string, string>("limit3-ranges", "limit3Val1,limit3Val2,limit3Val3"),
+            },
+            {}, "");
+
+    setCodecProperties("test8.encoder", true, 8, {}, {}, {}, "audio/opus",
+                       {pair<string, string>("max-limit1", "limit1Max")}, {}, "");
+
+    setRoleProperties("audio_decoder.mp3", false, 1, "audio/mpeg", "test1.decoder",
+                      {pair<string, string>("attribute::disabled", "present"),
+                       pair<string, string>("rank", "4")});
+
+    setRoleProperties("audio_decoder.amrnb", false, 2, "audio/3gpp", "test2.decoder", {});
+
+    setRoleProperties("audio_decoder.amrwb", false, 3, "audio/amr-wb", "test3.decoder",
+                      {pair<string, string>("feature-feature1", "feature1Val"),
+                       pair<string, string>("feature-feature2", "0"),
+                       pair<string, string>("feature-feature3", "0")});
+
+    setRoleProperties("audio/flac", false, 4, "audio/flac", "test4.decoder",
+                      {pair<string, string>("feature-feature1", "feature1Val")});
+
+    setRoleProperties("audio_decoder.g711mlaw", false, 5, "audio/g711-mlaw", "test5.decoder",
+                      {pair<string, string>("attribute::attributeQuirk1", "present")});
+
+    setRoleProperties("audio_decoder.aac", false, 6, "audio/mp4a-latm", "test6.decoder",
+                      {pair<string, string>("variant1:::variant1Limit1-range",
+                                            "variant1Limit1Min-variant1Limit1Max"),
+                       pair<string, string>("variant1:::variant1Limit2-range",
+                                            "variant1Limit2Low-variant1Limit2High"),
+                       pair<string, string>("variant2:::variant2Limit1", "variant2Limit1Value")});
+
+    setRoleProperties("audio_decoder.vorbis", false, 7, "audio/vorbis", "test7.decoder",
+                      {pair<string, string>("-min-limit1", "limit1Min"),
+                       /*pair<string, string>("limit1-in", "limit1In"),*/
+                       pair<string, string>("limit2-range", "limit2Min-limit2Max"),
+                       pair<string, string>("limit2-scale", "limit2Scale"),
+                       pair<string, string>("limit3-default", "limit3Val3"),
+                       pair<string, string>("limit3-ranges", "limit3Val1,limit3Val2,limit3Val3")});
+
+    setRoleProperties("audio_encoder.opus", true, 8, "audio/opus", "test8.encoder",
+                      {pair<string, string>("max-limit1", "limit1Max")});
+
+    setServiceAttribute(
+            {pair<string, string>("domain-telephony", "0"), pair<string, string>("domain-tv", "0"),
+             pair<string, string>("setting2", "0"), pair<string, string>("variant-variant1", "0")});
+}
+
+bool XMLParseTest::compareMap(const map<string, string> &lhs, const map<string, string> &rhs) {
+    return lhs.size() == rhs.size() && equal(lhs.begin(), lhs.end(), rhs.begin());
+}
+
+void XMLParseTest::setCodecProperties(string codecName, bool isEncoder, int32_t order,
+                                      set<string> quirkSet, set<string> domainSet,
+                                      set<string> variantSet, string typeName,
+                                      vector<pair<string, string>> domain, vector<string> aliases,
+                                      string rank) {
+    map<string, string> AttributeMapDB;
+    for (const auto &AttrStr : domain) {
+        AttributeMapDB.insert(AttrStr);
+    }
+    map<string, MediaCodecsXmlParser::AttributeMap> TypeMapDataBase;
+    TypeMapDataBase.insert(
+            pair<string, MediaCodecsXmlParser::AttributeMap>(typeName, AttributeMapDB));
+    CodecProperties codecProperty;
+    codecProperty.codecName = codecName;
+    codecProperty.codecProp.isEncoder = isEncoder;
+    codecProperty.codecProp.order = order;
+    codecProperty.codecProp.quirkSet = quirkSet;
+    codecProperty.codecProp.domainSet = domainSet;
+    codecProperty.codecProp.variantSet = variantSet;
+    codecProperty.codecProp.typeMap = TypeMapDataBase;
+    codecProperty.codecProp.aliases = aliases;
+    codecProperty.codecProp.rank = rank;
+    mInputDataVector.push_back(codecProperty);
+}
+
+void XMLParseTest::setRoleProperties(string roleName, bool isEncoder, int32_t order,
+                                     string typeName, string codecName,
+                                     vector<pair<string, string>> attributeNameValuePair) {
+    struct RoleProperties roleProperty;
+    roleProperty.roleName = roleName;
+    roleProperty.typeName = typeName;
+    roleProperty.codecName = codecName;
+    roleProperty.isEncoder = isEncoder;
+    roleProperty.order = order;
+    roleProperty.attributeMap = attributeNameValuePair;
+    mInputRoleVector.push_back(roleProperty);
+}
+
+void XMLParseTest::setServiceAttribute(map<string, string> serviceAttributeNameValuePair) {
+    for (const auto &serviceAttrStr : serviceAttributeNameValuePair) {
+        mInputServiceAttributeMap.insert(serviceAttrStr);
+    }
+}
+
+void XMLParseTest::printCodecMap(const MediaCodecsXmlParser::Codec mcodec) {
+    const string &name = mcodec.first;
+    ALOGV("codec name = %s\n", name.c_str());
+    const MediaCodecsXmlParser::CodecProperties &properties = mcodec.second;
+    bool isEncoder = properties.isEncoder;
+    ALOGV("isEncoder = %d\n", isEncoder);
+    size_t order = properties.order;
+    ALOGV("order = %zu\n", order);
+    string rank = properties.rank;
+    ALOGV("rank = %s\n", rank.c_str());
+
+    for (auto &itrQuirkSet : properties.quirkSet) {
+        ALOGV("quirkSet= %s", itrQuirkSet.c_str());
+    }
+
+    for (auto &itrDomainSet : properties.domainSet) {
+        ALOGV("domainSet= %s", itrDomainSet.c_str());
+    }
+
+    for (auto &itrVariantSet : properties.variantSet) {
+        ALOGV("variantSet= %s", itrVariantSet.c_str());
+    }
+
+    map<string, MediaCodecsXmlParser::AttributeMap> TypeMap = properties.typeMap;
+    ALOGV("The TypeMap is :");
+
+    for (auto &itrTypeMap : TypeMap) {
+        ALOGV("itrTypeMap->first\t%s\t", itrTypeMap.first.c_str());
+
+        for (auto &itrAttributeMap : itrTypeMap.second) {
+            ALOGV("AttributeMap->first = %s", itrAttributeMap.first.c_str());
+            ALOGV("AttributeMap->second = %s", itrAttributeMap.second.c_str());
+        }
+    }
+}
+
+void XMLParseTest::checkRoleMap(int32_t index, bool isEncoder, string typeName, string codecName,
+                                vector<pair<string, string>> AttributePairMap) {
+    ASSERT_EQ(isEncoder, mInputRoleVector.at(index).isEncoder)
+            << "Invalid RoleMap data. IsEncoder mismatch";
+    ASSERT_EQ(typeName, mInputRoleVector.at(index).typeName)
+            << "Invalid RoleMap data. typeName mismatch";
+    ASSERT_EQ(codecName, mInputRoleVector.at(index).codecName)
+            << "Invalid RoleMap data. codecName mismatch";
+
+    vector<pair<string, string>>::iterator itr_attributeMapDB =
+            (mInputRoleVector.at(index).attributeMap).begin();
+    vector<pair<string, string>>::iterator itr_attributeMap = AttributePairMap.begin();
+    for (; itr_attributeMap != AttributePairMap.end() &&
+           itr_attributeMapDB != mInputRoleVector.at(index).attributeMap.end();
+         ++itr_attributeMap, ++itr_attributeMapDB) {
+        string attributeName = itr_attributeMap->first;
+        string attributeNameDB = itr_attributeMapDB->first;
+        string attributevalue = itr_attributeMap->second;
+        string attributeValueDB = itr_attributeMapDB->second;
+        ASSERT_EQ(attributeName, attributeNameDB)
+                << "Invalid RoleMap data. Attribute name mismatch\t" << attributeName << " != "
+                << "attributeNameDB";
+        ASSERT_EQ(attributevalue, attributeValueDB)
+                << "Invalid RoleMap data. Attribute value mismatch\t" << attributevalue << " != "
+                << "attributeValueDB";
+    }
+}
+
+TEST_F(XMLParseTest, CodecMapParseTest) {
+    string inputFileName = gEnv->getRes() + XML_FILE_NAME;
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true) << "Failed to open inputfile " << inputFileName;
+
+    mParser.parseXmlPath(inputFileName);
+    for (const MediaCodecsXmlParser::Codec &mcodec : mParser.getCodecMap()) {
+        printCodecMap(mcodec);
+        const MediaCodecsXmlParser::CodecProperties &properties = mcodec.second;
+        int32_t index = properties.order - 1;
+        ASSERT_GE(index, 0) << "Invalid order";
+        ASSERT_EQ(mInputDataVector.at(index).codecName, mcodec.first.c_str())
+                << "Invalid CodecMap data. codecName mismatch";
+        ASSERT_EQ(properties.isEncoder, mInputDataVector.at(index).codecProp.isEncoder)
+                << "Invalid CodecMap data. isEncoder mismatch";
+        ASSERT_EQ(properties.order, mInputDataVector.at(index).codecProp.order)
+                << "Invalid CodecMap data. order mismatch";
+
+        set<string> quirkSetDB = mInputDataVector.at(index).codecProp.quirkSet;
+        set<string> quirkSet = properties.quirkSet;
+        set<string> quirkDifference;
+        set_difference(quirkSetDB.begin(), quirkSetDB.end(), quirkSet.begin(), quirkSet.end(),
+                       inserter(quirkDifference, quirkDifference.end()));
+        ASSERT_EQ(quirkDifference.size(), 0) << "CodecMap:quirk mismatch";
+
+        map<string, MediaCodecsXmlParser::AttributeMap> TypeMapDB =
+                mInputDataVector.at(index).codecProp.typeMap;
+        map<string, MediaCodecsXmlParser::AttributeMap> TypeMap = properties.typeMap;
+        map<string, MediaCodecsXmlParser::AttributeMap>::iterator itr_TypeMapDB = TypeMapDB.begin();
+        map<string, MediaCodecsXmlParser::AttributeMap>::iterator itr_TypeMap = TypeMap.begin();
+
+        ASSERT_EQ(TypeMapDB.size(), TypeMap.size())
+                << "Invalid CodecMap data. Typemap size mismatch";
+
+        for (; itr_TypeMap != TypeMap.end() && itr_TypeMapDB != TypeMapDB.end();
+             ++itr_TypeMap, ++itr_TypeMapDB) {
+            ASSERT_EQ(itr_TypeMap->first, itr_TypeMapDB->first)
+                    << "Invalid CodecMap data. type mismatch";
+            bool flag = compareMap(itr_TypeMap->second, itr_TypeMapDB->second);
+            ASSERT_TRUE(flag) << "typeMap mismatch";
+        }
+        ASSERT_EQ(mInputDataVector.at(index).codecProp.rank, properties.rank)
+                << "Invalid CodecMap data. rank mismatch";
+    }
+}
+
+TEST_F(XMLParseTest, RoleMapParseTest) {
+    string inputFileName = gEnv->getRes() + XML_FILE_NAME;
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true) << "Failed to open inputfile " << inputFileName;
+
+    mParser.parseXmlPath(inputFileName);
+
+    for (auto &mRole : mParser.getRoleMap()) {
+        typedef pair<string, string> Attribute;
+        const string &roleName = mRole.first;
+        ALOGV("Role map:name = %s\n", roleName.c_str());
+        const MediaCodecsXmlParser::RoleProperties &properties = mRole.second;
+        string type = properties.type;
+        ALOGV("Role map: type = %s\n", type.c_str());
+
+        bool isEncoder = properties.isEncoder;
+        ALOGV("Role map: isEncoder = %d\n", isEncoder);
+
+        multimap<size_t, MediaCodecsXmlParser::NodeInfo> nodeList = properties.nodeList;
+        multimap<size_t, MediaCodecsXmlParser::NodeInfo>::iterator itr_Node;
+        ALOGV("\nThe multimap nodeList is : \n");
+        for (itr_Node = nodeList.begin(); itr_Node != nodeList.end(); ++itr_Node) {
+            ALOGV("itr_Node->first=ORDER=\t%zu\t", itr_Node->first);
+            int32_t index = itr_Node->first - 1;
+            MediaCodecsXmlParser::NodeInfo nodePtr = itr_Node->second;
+            ALOGV("Role map:itr_Node->second.name = %s\n", nodePtr.name.c_str());
+            vector<Attribute> attrList = nodePtr.attributeList;
+            for (auto attrNameValueList = attrList.begin(); attrNameValueList != attrList.end();
+                 ++attrNameValueList) {
+                ALOGV("Role map:nodePtr.attributeList->first = %s\n",
+                      attrNameValueList->first.c_str());
+                ALOGV("Role map:nodePtr.attributeList->second = %s\n",
+                      attrNameValueList->second.c_str());
+            }
+            checkRoleMap(index, isEncoder, properties.type, nodePtr.name.c_str(), attrList);
+        }
+    }
+}
+
+TEST_F(XMLParseTest, ServiceAttributeMapParseTest) {
+    string inputFileName = gEnv->getRes() + XML_FILE_NAME;
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true) << "Failed to open inputfile " << inputFileName;
+
+    mParser.parseXmlPath(inputFileName);
+    const auto serviceAttributeMap = mParser.getServiceAttributeMap();
+    for (const auto &attributePair : serviceAttributeMap) {
+        ALOGV("serviceAttribute.key = %s \t serviceAttribute.value = %s",
+              attributePair.first.c_str(), attributePair.second.c_str());
+    }
+    bool flag = compareMap(mInputServiceAttributeMap, serviceAttributeMap);
+    ASSERT_TRUE(flag) << "ServiceMapParseTest: typeMap mismatch";
+}
+
+int main(int argc, char **argv) {
+    gEnv = new XMLParserTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGD("XML Parser Test Result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/xmlparser/test/XMLParserTestEnvironment.h b/media/libstagefright/xmlparser/test/XMLParserTestEnvironment.h
new file mode 100644
index 0000000..61a09e6
--- /dev/null
+++ b/media/libstagefright/xmlparser/test/XMLParserTestEnvironment.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 __XML_PARSER_TEST_ENVIRONMENT_H__
+#define __XML_PARSER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class XMLParserTestEnvironment : public ::testing::Environment {
+  public:
+    XMLParserTestEnvironment() : 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 XMLParserTestEnvironment::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  // __XML_PARSER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml b/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml
new file mode 100644
index 0000000..a7299d3
--- /dev/null
+++ b/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml
@@ -0,0 +1,80 @@
+<?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.
+-->
+
+<!-- REFERENCE : frameworks/av/media/libstagefright/xmlparser/media_codecs.xsd -->
+<Included>
+    <Settings>
+        <Domain name="telephony" enabled="false" />
+        <Domain name="tv" enabled="false" />
+        <Variant name="variant1" enabled="false" />
+        <Setting name="setting1" value="settingValue1" update="true" />
+        <Setting name="setting2" enabled="false" />
+    </Settings>
+    <Decoders>
+        <!-- entry for enabled, domain, rank and update properties -->
+        <MediaCodec name="test1.decoder" type="audio/mpeg" update="false" domain="telephony" enabled="false" rank="4">
+            <Alias name="alias1.decoder" />
+            <Quirk name="quirk1" value="quirk1Value"/>
+        </MediaCodec>
+        <!-- entry for testing Quirk -->
+        <MediaCodec name="test2.decoder" type="audio/3gpp" enabled="true" >
+            <Quirk name="quirk1" value="quirk1Value"/>
+        </MediaCodec>
+        <!-- entry for testing Feature -->
+        <!-- feature2 takes value 0 (feature with same name takes lower feature's value) -->
+        <!-- feature3 gives value as 0 since it's optional -->
+        <!-- optional="true" required="true" is not a valid combination. -->
+        <!-- optional="false" required="false" is not a valid combination. -->
+        <MediaCodec name="test3.decoder" type="audio/amr-wb" >
+            <Feature name="feature1" value="feature1Val" />
+            <Feature name="feature2" value="feature2Val"/>
+            <Feature name="feature2" />
+            <Feature name="feature3" optional="true" required="false" />
+        </MediaCodec>
+        <!-- entry for testing Type -->
+        <MediaCodec name="test4.decoder">
+            <Type name="audio/flac">
+                <Feature name="feature1" value="feature1Val" />
+            </Type>
+        </MediaCodec>
+        <!-- entry for testing Attribute -->
+        <MediaCodec name="test5.decoder" type="audio/g711-mlaw" >
+            <Attribute name="attributeQuirk1" />
+        </MediaCodec>
+        <!-- entry for testing Variant -->
+        <MediaCodec name="test6.decoder" type="audio/mp4a-latm" variant="variant1,variant2" >
+            <Variant name="variant1">
+                <Limit name="variant1Limit1" min="variant1Limit1Min" max="variant1Limit1Max" />
+                <Limit name="variant1Limit2" range="variant1Limit2Low-variant1Limit2High" />
+            </Variant>
+            <Variant name="variant2">
+                <Limit name="variant2Limit1" value="variant2Limit1Value" />
+            </Variant>
+        </MediaCodec>
+        <!-- entry for testing Limit -->
+        <!-- 'in' is present in xsd file but not handled in MediaCodecsXmlParser -->
+        <MediaCodec name="test7.decoder" type="audio/vorbis" >
+            <Limit name="limit1" in="limit1In" min="limit1Min"/>
+            <Limit name="limit2" min="limit2Min" max="limit2Max" scale="limit2Scale" />
+            <Limit name="limit3" ranges="limit3Val1,limit3Val2,limit3Val3" default="limit3Val3" />
+        </MediaCodec>
+    </Decoders>
+    <Encoders>
+        <MediaCodec name="test8.encoder" type="audio/opus">
+            <Limit name="limit1" max="limit1Max" />
+        </MediaCodec>
+    </Encoders>
+</Included>
diff --git a/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test_caller.xml b/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test_caller.xml
new file mode 100644
index 0000000..d864ce9
--- /dev/null
+++ b/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test_caller.xml
@@ -0,0 +1,4 @@
+<!-- entry for testing Include -->
+<MediaCodecs>
+    <Include href="media_codecs_unit_test.xml" />
+</MediaCodecs>