Merge "ICameraService: Add methods to query concurrent streaming camera support."
diff --git a/apex/AndroidManifest-media.xml b/apex/AndroidManifest-media.xml
index 1af4586..b020cba 100644
--- a/apex/AndroidManifest-media.xml
+++ b/apex/AndroidManifest-media.xml
@@ -19,8 +19,10 @@
   <!-- APEX does not have classes.dex -->
   <application android:hasCode="false" />
   <!-- Setting maxSdk to lock the module to Q. minSdk is auto-set by build system -->
-  <uses-sdk
+  <!-- TODO: Uncomment this when the R API level is fixed. b/148281152 -->
+  <!--uses-sdk
       android:maxSdkVersion="29"
       android:targetSdkVersion="29"
   />
+  -->
 </manifest>
diff --git a/apex/AndroidManifest-swcodec.xml b/apex/AndroidManifest-swcodec.xml
index de50864..1a28d19 100644
--- a/apex/AndroidManifest-swcodec.xml
+++ b/apex/AndroidManifest-swcodec.xml
@@ -19,8 +19,10 @@
   <!-- APEX does not have classes.dex -->
   <application android:hasCode="false" />
   <!-- Setting maxSdk to lock the module to Q. minSdk is auto-set by build system -->
-  <uses-sdk
+  <!-- TODO: Uncomment this when the R API level is fixed. b/148281152 -->
+  <!--uses-sdk
       android:maxSdkVersion="29"
       android:targetSdkVersion="29"
   />
+  -->
 </manifest>
diff --git a/cmds/screenrecord/Android.bp b/cmds/screenrecord/Android.bp
index 72008c2..d7d905f 100644
--- a/cmds/screenrecord/Android.bp
+++ b/cmds/screenrecord/Android.bp
@@ -26,6 +26,7 @@
 
     header_libs: [
         "libmediadrm_headers",
+        "libmediametrics_headers",
     ],
 
     shared_libs: [
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 7b447d3..6470fb1 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -8,6 +8,9 @@
         jpeg.cpp        \
         SineSource.cpp
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia libmedia_codeclist libutils libbinder \
         libstagefright_foundation libjpeg libui libgui libcutils liblog \
@@ -37,6 +40,9 @@
         SineSource.cpp    \
         record.cpp
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia liblog libutils libbinder \
         libstagefright_foundation libdatasource libaudioclient
@@ -63,6 +69,9 @@
         AudioPlayer.cpp \
         recordvideo.cpp
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia liblog libutils libbinder \
         libstagefright_foundation libaudioclient
@@ -90,6 +99,9 @@
         SineSource.cpp    \
         audioloop.cpp
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia liblog libutils libbinder \
         libstagefright_foundation libaudioclient
@@ -113,6 +125,9 @@
 LOCAL_SRC_FILES:=         \
         stream.cpp    \
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libui libgui \
         libstagefright_foundation libmedia libcutils libdatasource
@@ -139,6 +154,7 @@
 
 LOCAL_HEADER_LIBRARIES := \
         libmediadrm_headers \
+        libmediametrics_headers \
 
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libstagefright_foundation \
@@ -168,6 +184,7 @@
 
 LOCAL_HEADER_LIBRARIES := \
         libmediadrm_headers \
+        libmediametrics_headers \
 
 LOCAL_SHARED_LIBRARIES := \
         libstagefright \
@@ -209,6 +226,9 @@
 LOCAL_SRC_FILES:=               \
         muxer.cpp            \
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libstagefright_foundation \
         libcutils libc
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 255640f..6ba1b9c 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -167,6 +167,7 @@
     ],
 
     header_libs: [
+        "libmediametrics_headers",
         "libstagefright_foundation_headers",
     ],
 }
diff --git a/drm/libmediadrm/tests/Android.bp b/drm/libmediadrm/tests/Android.bp
index 7471e05..6529387 100644
--- a/drm/libmediadrm/tests/Android.bp
+++ b/drm/libmediadrm/tests/Android.bp
@@ -3,7 +3,10 @@
 cc_test {
     name: "CounterMetric_test",
     srcs: ["CounterMetric_test.cpp"],
-    header_libs: ["libmedia_headers"],
+    header_libs: [
+        "libmedia_headers",
+        "libmediametrics_headers",
+    ],
     shared_libs: ["libmediadrm"],
     cflags: [
       "-Werror",
@@ -46,7 +49,8 @@
     name: "EventMetric_test",
     srcs: ["EventMetric_test.cpp"],
     header_libs: [
-        "libmedia_headers"
+        "libmedia_headers",
+        "libmediametrics_headers",
     ],
     shared_libs: [
       "liblog",
diff --git a/include/media/IMediaMetricsService.h b/include/media/IMediaMetricsService.h
deleted file mode 120000
index 84b99ee..0000000
--- a/include/media/IMediaMetricsService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediametrics/include/IMediaMetricsService.h
\ No newline at end of file
diff --git a/include/media/MediaMetrics.h b/include/media/MediaMetrics.h
deleted file mode 120000
index 5f757e4..0000000
--- a/include/media/MediaMetrics.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediametrics/include/MediaMetrics.h
\ No newline at end of file
diff --git a/include/media/MediaMetricsItem.h b/include/media/MediaMetricsItem.h
deleted file mode 120000
index 5438953..0000000
--- a/include/media/MediaMetricsItem.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediametrics/include/MediaMetricsItem.h
\ No newline at end of file
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 79b77a0..f44f0d5 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -24,6 +24,7 @@
 
 LOCAL_HEADER_LIBRARIES := \
 	libaudiohal_headers \
+	libmediametrics_headers \
 
 # TODO oboeservice is the old folder name for aaudioservice. It will be changed.
 LOCAL_C_INCLUDES := \
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 534c1a7..94034b5 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -23,6 +23,7 @@
     header_libs: [
         "libcodec2_internal",
         "libmediadrm_headers",
+        "libmediametrics_headers",
         "media_ndk_headers",
     ],
 
diff --git a/media/codec2/sfplugin/tests/Android.bp b/media/codec2/sfplugin/tests/Android.bp
index b6eb2b4..c953f84 100644
--- a/media/codec2/sfplugin/tests/Android.bp
+++ b/media/codec2/sfplugin/tests/Android.bp
@@ -35,6 +35,7 @@
 
     header_libs: [
         "libmediadrm_headers",
+        "libmediametrics_headers",
     ],
 
     shared_libs: [
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index 8753aa9..901c28f 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -68,6 +68,7 @@
     header_libs: [
         "libaaudio_headers",
         "libmedia_headers",
+        "libmediametrics_headers",
     ],
     export_header_lib_headers: ["libaaudio_headers"],
 
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index d509be6..350a780 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -13,6 +13,7 @@
            "test_create_utils.cpp"],
     header_libs: [
         "libmedia_headers",
+        "libmediametrics_headers",
     ],
     shared_libs: [
         "libaudioclient",
@@ -30,6 +31,7 @@
            "test_create_utils.cpp"],
     header_libs: [
         "libmedia_headers",
+        "libmediametrics_headers",
     ],
     shared_libs: [
         "libaudioclient",
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 2208eca..273d91c 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -334,6 +334,13 @@
     }
     mDataSource = dataSource;
 
+    return reinit(frameInfo);
+}
+
+bool HeifDecoderImpl::reinit(HeifFrameInfo* frameInfo) {
+    mFrameDecoded = false;
+    mFrameMemory.clear();
+
     mRetriever = new MediaMetadataRetriever();
     status_t err = mRetriever->setDataSource(mDataSource, "image/heif");
     if (err != OK) {
@@ -457,27 +464,35 @@
 }
 
 bool HeifDecoderImpl::setOutputColor(HeifColorFormat heifColor) {
+    if (heifColor == mOutputColor) {
+        return true;
+    }
+
     switch(heifColor) {
         case kHeifColorFormat_RGB565:
         {
             mOutputColor = HAL_PIXEL_FORMAT_RGB_565;
-            return true;
+            break;
         }
         case kHeifColorFormat_RGBA_8888:
         {
             mOutputColor = HAL_PIXEL_FORMAT_RGBA_8888;
-            return true;
+            break;
         }
         case kHeifColorFormat_BGRA_8888:
         {
             mOutputColor = HAL_PIXEL_FORMAT_BGRA_8888;
-            return true;
+            break;
         }
         default:
-            break;
+            ALOGE("Unsupported output color format %d", heifColor);
+            return false;
     }
-    ALOGE("Unsupported output color format %d", heifColor);
-    return false;
+
+    if (mFrameDecoded) {
+        return reinit(nullptr);
+    }
+    return true;
 }
 
 bool HeifDecoderImpl::decodeAsync() {
@@ -506,7 +521,8 @@
     }
     // Aggressive clear to avoid holding on to resources
     mRetriever.clear();
-    mDataSource.clear();
+
+    // Hold on to mDataSource in case the client wants to redecode.
     return false;
 }
 
@@ -606,7 +622,8 @@
 
     // Aggressively clear to avoid holding on to resources
     mRetriever.clear();
-    mDataSource.clear();
+
+    // Hold on to mDataSource in case the client wants to redecode.
     return true;
 }
 
diff --git a/media/libheif/HeifDecoderImpl.h b/media/libheif/HeifDecoderImpl.h
index 69c74a7..2b9c710 100644
--- a/media/libheif/HeifDecoderImpl.h
+++ b/media/libheif/HeifDecoderImpl.h
@@ -81,6 +81,7 @@
 
     bool decodeAsync();
     bool getScanlineInner(uint8_t* dst);
+    bool reinit(HeifFrameInfo* frameInfo);
 };
 
 } // namespace android
diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp
index 7fd5408..0cd5194 100644
--- a/media/libmediametrics/Android.bp
+++ b/media/libmediametrics/Android.bp
@@ -1,3 +1,8 @@
+cc_library_headers {
+    name: "libmediametrics_headers",
+    export_include_dirs: ["include"],
+}
+
 cc_library_shared {
     name: "libmediametrics",
 
diff --git a/media/libmediametrics/include/IMediaMetricsService.h b/media/libmediametrics/include/media/IMediaMetricsService.h
similarity index 100%
rename from media/libmediametrics/include/IMediaMetricsService.h
rename to media/libmediametrics/include/media/IMediaMetricsService.h
diff --git a/media/libmediametrics/include/MediaMetrics.h b/media/libmediametrics/include/media/MediaMetrics.h
similarity index 100%
rename from media/libmediametrics/include/MediaMetrics.h
rename to media/libmediametrics/include/media/MediaMetrics.h
diff --git a/media/libmediametrics/include/MediaMetricsItem.h b/media/libmediametrics/include/media/MediaMetricsItem.h
similarity index 100%
rename from media/libmediametrics/include/MediaMetricsItem.h
rename to media/libmediametrics/include/media/MediaMetricsItem.h
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index c8f48a2..32c97cf 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -19,6 +19,7 @@
 
     header_libs: [
         "libmediadrm_headers",
+        "libmediametrics_headers",
         "media_plugin_headers",
     ],
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 6757474..13149b5 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -3619,7 +3619,6 @@
         AString *errorDetailMsg;
         CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
 
-        ALOGI("calling queueSec");
         err = mBufferChannel->queueSecureInputBuffer(
                 buffer,
                 (mFlags & kFlagIsSecure),
diff --git a/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h b/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
new file mode 100644
index 0000000..5a2fcd1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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 __AMRNBENC_TEST_ENVIRONMENT_H__
+#define __AMRNBENC_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class AmrnbEncTestEnvironment : public ::testing::Environment {
+  public:
+    AmrnbEncTestEnvironment() : 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 AmrnbEncTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", 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  // __AMRNBENC_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp b/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
new file mode 100644
index 0000000..fb72998
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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 "AmrnbEncoderTest"
+
+#include <utils/Log.h>
+
+#include <audio_utils/sndfile.h>
+#include <stdio.h>
+
+#include "gsmamr_enc.h"
+
+#include "AmrnbEncTestEnvironment.h"
+
+#define OUTPUT_FILE "/data/local/tmp/amrnbEncode.out"
+
+constexpr int32_t kInputBufferSize = L_FRAME * 2;  // 160 samples * 16-bit per sample.
+constexpr int32_t kOutputBufferSize = 1024;
+constexpr int32_t kNumFrameReset = 200;
+constexpr int32_t kMaxCount = 10;
+struct AmrNbEncState {
+    void *encCtx;
+    void *pidSyncCtx;
+};
+
+static AmrnbEncTestEnvironment *gEnv = nullptr;
+
+class AmrnbEncoderTest : public ::testing::TestWithParam<pair<string, int32_t>> {
+  public:
+    AmrnbEncoderTest() : mAmrEncHandle(nullptr) {}
+
+    ~AmrnbEncoderTest() {
+        if (mAmrEncHandle) {
+            free(mAmrEncHandle);
+            mAmrEncHandle = nullptr;
+        }
+    }
+
+    AmrNbEncState *mAmrEncHandle;
+    int32_t EncodeFrames(int32_t mode, FILE *fpInput, FILE *mFpOutput,
+                         int32_t frameCount = INT32_MAX);
+};
+
+int32_t AmrnbEncoderTest::EncodeFrames(int32_t mode, FILE *fpInput, FILE *mFpOutput,
+                                       int32_t frameCount) {
+    int32_t frameNum = 0;
+    uint16_t inputBuf[kInputBufferSize];
+    uint8_t outputBuf[kOutputBufferSize];
+    while (frameNum < frameCount) {
+        int32_t bytesRead = fread(inputBuf, 1, kInputBufferSize, fpInput);
+        if (bytesRead != kInputBufferSize && !feof(fpInput)) {
+            ALOGE("Unable to read data from input file");
+            return -1;
+        } else if (feof(fpInput) && bytesRead == 0) {
+            break;
+        }
+        Frame_Type_3GPP frame_type = (Frame_Type_3GPP)mode;
+        int32_t bytesGenerated =
+                AMREncode(mAmrEncHandle->encCtx, mAmrEncHandle->pidSyncCtx, (Mode)mode,
+                          (Word16 *)inputBuf, outputBuf, &frame_type, AMR_TX_WMF);
+        frameNum++;
+        if (bytesGenerated < 0) {
+            ALOGE("Error in encoging the file: Invalid output format");
+            return -1;
+        }
+
+        // Convert from WMF to RFC 3267 format.
+        if (bytesGenerated > 0) {
+            outputBuf[0] = ((outputBuf[0] << 3) | 4) & 0x7c;
+        }
+        fwrite(outputBuf, 1, bytesGenerated, mFpOutput);
+    }
+    return 0;
+}
+
+TEST_F(AmrnbEncoderTest, CreateAmrnbEncoderTest) {
+    mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
+    ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
+    for (int count = 0; count < kMaxCount; count++) {
+        int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
+        ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
+        ALOGV("Successfully created encoder");
+    }
+    if (mAmrEncHandle) {
+        AMREncodeExit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx);
+        ASSERT_EQ(mAmrEncHandle->encCtx, nullptr) << "Error deleting AMR-NB encoder";
+        ASSERT_EQ(mAmrEncHandle->pidSyncCtx, nullptr) << "Error deleting AMR-NB encoder";
+        free(mAmrEncHandle);
+        mAmrEncHandle = nullptr;
+        ALOGV("Successfully deleted encoder");
+    }
+}
+
+TEST_P(AmrnbEncoderTest, EncodeTest) {
+    mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
+    ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
+    int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
+    ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
+
+    string inputFile = gEnv->getRes() + GetParam().first;
+    FILE *fpInput = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(fpInput, nullptr) << "Error opening input file " << inputFile;
+
+    FILE *fpOutput = fopen(OUTPUT_FILE, "wb");
+    ASSERT_NE(fpOutput, nullptr) << "Error opening output file " << OUTPUT_FILE;
+
+    // Write file header.
+    fwrite("#!AMR\n", 1, 6, fpOutput);
+
+    int32_t mode = GetParam().second;
+    int32_t encodeErr = EncodeFrames(mode, fpInput, fpOutput);
+    ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
+
+    fclose(fpOutput);
+    fclose(fpInput);
+
+    AMREncodeExit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx);
+    ASSERT_EQ(mAmrEncHandle->encCtx, nullptr) << "Error deleting AMR-NB encoder";
+    ASSERT_EQ(mAmrEncHandle->pidSyncCtx, nullptr) << "Error deleting AMR-NB encoder";
+    free(mAmrEncHandle);
+    mAmrEncHandle = nullptr;
+    ALOGV("Successfully deleted encoder");
+}
+
+TEST_P(AmrnbEncoderTest, ResetEncoderTest) {
+    mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
+    ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
+    int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
+    ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
+
+    string inputFile = gEnv->getRes() + GetParam().first;
+    FILE *fpInput = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(fpInput, nullptr) << "Error opening input file " << inputFile;
+
+    FILE *fpOutput = fopen(OUTPUT_FILE, "wb");
+    ASSERT_NE(fpOutput, nullptr) << "Error opening output file " << OUTPUT_FILE;
+
+    // Write file header.
+    fwrite("#!AMR\n", 1, 6, fpOutput);
+
+    int32_t mode = GetParam().second;
+    // Encode kNumFrameReset first
+    int32_t encodeErr = EncodeFrames(mode, fpInput, fpOutput, kNumFrameReset);
+    ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
+
+    status = AMREncodeReset(mAmrEncHandle->encCtx, mAmrEncHandle->pidSyncCtx);
+    ASSERT_EQ(status, 0) << "Error resting AMR-NB encoder";
+
+    // Start encoding again
+    encodeErr = EncodeFrames(mode, fpInput, fpOutput);
+    ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
+
+    fclose(fpOutput);
+    fclose(fpInput);
+
+    AMREncodeExit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx);
+    ASSERT_EQ(mAmrEncHandle->encCtx, nullptr) << "Error deleting AMR-NB encoder";
+    ASSERT_EQ(mAmrEncHandle->pidSyncCtx, nullptr) << "Error deleting AMR-NB encoder";
+    free(mAmrEncHandle);
+    mAmrEncHandle = nullptr;
+    ALOGV("Successfully deleted encoder");
+}
+
+// TODO: Add more test vectors
+INSTANTIATE_TEST_SUITE_P(AmrnbEncoderTestAll, AmrnbEncoderTest,
+                         ::testing::Values(make_pair("bbb_raw_1ch_8khz_s16le.raw", MR475),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR515),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR59),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR67),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR74),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR795),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR102),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR122),
+                                           make_pair("sinesweepraw.raw", MR475),
+                                           make_pair("sinesweepraw.raw", MR515),
+                                           make_pair("sinesweepraw.raw", MR59),
+                                           make_pair("sinesweepraw.raw", MR67),
+                                           make_pair("sinesweepraw.raw", MR74),
+                                           make_pair("sinesweepraw.raw", MR795),
+                                           make_pair("sinesweepraw.raw", MR102),
+                                           make_pair("sinesweepraw.raw", MR122)));
+
+int main(int argc, char **argv) {
+    gEnv = new AmrnbEncTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/test/Android.bp b/media/libstagefright/codecs/amrnb/enc/test/Android.bp
new file mode 100644
index 0000000..e8982fe
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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: "AmrnbEncoderTest",
+    gtest: true,
+
+    srcs: [
+        "AmrnbEncoderTest.cpp",
+    ],
+
+    static_libs: [
+        "libstagefright_amrnb_common",
+        "libstagefright_amrnbenc",
+        "libaudioutils",
+        "libsndfile",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/test/README.md b/media/libstagefright/codecs/amrnb/enc/test/README.md
new file mode 100644
index 0000000..4ddaa57
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/README.md
@@ -0,0 +1,34 @@
+## Media Testing ##
+---
+#### AMR-NB Encoder :
+The Amr-Nb Encoder Test Suite validates the amrnb encoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m AmrnbEncoderTest
+```
+
+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/AmrnbEncoderTest/AmrnbEncoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/AmrnbEncoderTest/AmrnbEncoderTest /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_encoder folder and push all the files in this folder to /data/local/tmp/ on the device.
+```
+adb push amr-nb_encoder/. /data/local/tmp/
+```
+
+usage: AmrnbEncoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/AmrnbEncoderTest -P /data/local/tmp/
+```
diff --git a/media/libstagefright/codecs/mp3dec/test/Android.bp b/media/libstagefright/codecs/mp3dec/test/Android.bp
new file mode 100644
index 0000000..0ff8b12
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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: "Mp3DecoderTest",
+    gtest: true,
+
+    srcs: [
+        "mp3reader.cpp",
+        "Mp3DecoderTest.cpp",
+    ],
+
+    static_libs: [
+        "libstagefright_mp3dec",
+        "libsndfile",
+        "libaudioutils",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp
new file mode 100644
index 0000000..99553ec
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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 "Mp3DecoderTest"
+
+#include <utils/Log.h>
+
+#include <audio_utils/sndfile.h>
+#include <stdio.h>
+
+#include "mp3reader.h"
+#include "pvmp3decoder_api.h"
+
+#include "Mp3DecoderTestEnvironment.h"
+
+#define OUTPUT_FILE "/data/local/tmp/mp3Decode.out"
+
+constexpr int32_t kInputBufferSize = 1024 * 10;
+constexpr int32_t kOutputBufferSize = 4608 * 2;
+constexpr int32_t kMaxCount = 10;
+constexpr int32_t kNumFrameReset = 150;
+
+static Mp3DecoderTestEnvironment *gEnv = nullptr;
+
+class Mp3DecoderTest : public ::testing::TestWithParam<string> {
+  public:
+    Mp3DecoderTest() : mConfig(nullptr) {}
+
+    ~Mp3DecoderTest() {
+        if (mConfig) {
+            delete mConfig;
+            mConfig = nullptr;
+        }
+    }
+
+    virtual void SetUp() override {
+        mConfig = new tPVMP3DecoderExternal{};
+        ASSERT_NE(mConfig, nullptr) << "Failed to initialize config. No Memory available";
+        mConfig->equalizerType = flat;
+        mConfig->crcEnabled = false;
+    }
+
+    tPVMP3DecoderExternal *mConfig;
+    Mp3Reader mMp3Reader;
+
+    ERROR_CODE DecodeFrames(void *decoderbuf, SNDFILE *outFileHandle, SF_INFO sfInfo,
+                            int32_t frameCount = INT32_MAX);
+    SNDFILE *openOutputFile(SF_INFO *sfInfo);
+};
+
+ERROR_CODE Mp3DecoderTest::DecodeFrames(void *decoderBuf, SNDFILE *outFileHandle, SF_INFO sfInfo,
+                                        int32_t frameCount) {
+    uint8_t inputBuf[kInputBufferSize];
+    int16_t outputBuf[kOutputBufferSize];
+    uint32_t bytesRead;
+    ERROR_CODE decoderErr;
+    while (frameCount > 0) {
+        bool success = mMp3Reader.getFrame(inputBuf, &bytesRead);
+        if (!success) {
+            break;
+        }
+        mConfig->inputBufferCurrentLength = bytesRead;
+        mConfig->inputBufferMaxLength = 0;
+        mConfig->inputBufferUsedLength = 0;
+        mConfig->pInputBuffer = inputBuf;
+        mConfig->pOutputBuffer = outputBuf;
+        mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
+        decoderErr = pvmp3_framedecoder(mConfig, decoderBuf);
+        if (decoderErr != NO_DECODING_ERROR) break;
+        sf_writef_short(outFileHandle, outputBuf, mConfig->outputFrameSize / sfInfo.channels);
+        frameCount--;
+    }
+    return decoderErr;
+}
+
+SNDFILE *Mp3DecoderTest::openOutputFile(SF_INFO *sfInfo) {
+    memset(sfInfo, 0, sizeof(SF_INFO));
+    sfInfo->channels = mMp3Reader.getNumChannels();
+    sfInfo->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+    sfInfo->samplerate = mMp3Reader.getSampleRate();
+    SNDFILE *outFileHandle = sf_open(OUTPUT_FILE, SFM_WRITE, sfInfo);
+    return outFileHandle;
+}
+
+TEST_F(Mp3DecoderTest, MultiCreateMp3DecoderTest) {
+    size_t memRequirements = pvmp3_decoderMemRequirements();
+    ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
+    void *decoderBuf = malloc(memRequirements);
+    ASSERT_NE(decoderBuf, nullptr)
+            << "Failed to allocate decoder memory of size " << memRequirements;
+    for (int count = 0; count < kMaxCount; count++) {
+        pvmp3_InitDecoder(mConfig, decoderBuf);
+        ALOGV("Decoder created successfully");
+    }
+    if (decoderBuf) {
+        free(decoderBuf);
+        decoderBuf = nullptr;
+    }
+}
+
+TEST_P(Mp3DecoderTest, DecodeTest) {
+    size_t memRequirements = pvmp3_decoderMemRequirements();
+    ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
+    void *decoderBuf = malloc(memRequirements);
+    ASSERT_NE(decoderBuf, nullptr)
+            << "Failed to allocate decoder memory of size " << memRequirements;
+
+    pvmp3_InitDecoder(mConfig, decoderBuf);
+    ALOGV("Decoder created successfully");
+    string inputFile = gEnv->getRes() + GetParam();
+    bool status = mMp3Reader.init(inputFile.c_str());
+    ASSERT_TRUE(status) << "Unable to initialize the mp3Reader";
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
+    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
+
+    ERROR_CODE decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+    ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
+    ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
+    ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
+
+    mMp3Reader.close();
+    sf_close(outFileHandle);
+    if (decoderBuf) {
+        free(decoderBuf);
+        decoderBuf = nullptr;
+    }
+}
+
+TEST_P(Mp3DecoderTest, ResetDecoderTest) {
+    size_t memRequirements = pvmp3_decoderMemRequirements();
+    ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
+    void *decoderBuf = malloc(memRequirements);
+    ASSERT_NE(decoderBuf, nullptr)
+            << "Failed to allocate decoder memory of size " << memRequirements;
+
+    pvmp3_InitDecoder(mConfig, decoderBuf);
+    ALOGV("Decoder created successfully.");
+    string inputFile = gEnv->getRes() + GetParam();
+    bool status = mMp3Reader.init(inputFile.c_str());
+    ASSERT_TRUE(status) << "Unable to initialize the mp3Reader";
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
+    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
+
+    ERROR_CODE decoderErr;
+    decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo, kNumFrameReset);
+    ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
+    ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
+    ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
+
+    pvmp3_resetDecoder(decoderBuf);
+    // Decode the same file.
+    decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+    ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
+    ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
+    ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
+
+    mMp3Reader.close();
+    sf_close(outFileHandle);
+    if (decoderBuf) {
+        free(decoderBuf);
+        decoderBuf = nullptr;
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(Mp3DecoderTestAll, Mp3DecoderTest,
+                         ::testing::Values(("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3"),
+                                           ("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3"),
+                                           ("bbb_mp3_stereo_192kbps_48000hz.mp3")));
+
+int main(int argc, char **argv) {
+    gEnv = new Mp3DecoderTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
new file mode 100644
index 0000000..a54b34c
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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 __MP3DECODER_TEST_ENVIRONMENT_H__
+#define __MP3DECODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class Mp3DecoderTestEnvironment : public ::testing::Environment {
+  public:
+    Mp3DecoderTestEnvironment() : 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 Mp3DecoderTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", 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  // __MP3DECODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/mp3dec/test/README.md b/media/libstagefright/codecs/mp3dec/test/README.md
new file mode 100644
index 0000000..019239e
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/README.md
@@ -0,0 +1,34 @@
+## Media Testing ##
+---
+#### Mp3Decoder :
+The Mp3Decoder Test Suite validates the mp3decoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m Mp3DecoderTest
+```
+
+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/Mp3DecoderTest/Mp3DecoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/Mp3DecoderTest/Mp3DecoderTest /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 mp3 folder and push all the files in this folder to /data/local/tmp/ on the device.
+```
+adb push mp3/. /data/local/tmp/
+```
+
+usage: Mp3DecoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/Mp3DecoderTest -P /data/local/tmp/
+```
diff --git a/media/libstagefright/omx/tests/Android.bp b/media/libstagefright/omx/tests/Android.bp
index eb01543..fefb3bb 100644
--- a/media/libstagefright/omx/tests/Android.bp
+++ b/media/libstagefright/omx/tests/Android.bp
@@ -23,6 +23,7 @@
 
     header_libs: [
         "libbase_headers",
+        "libmediametrics_headers",
         "media_ndk_headers",
     ],
 
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 7b285a6..9bc6bd0 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -72,6 +72,7 @@
 
     header_libs: [
         "libmediadrm_headers",
+        "libmediametrics_headers",
     ],
 
     shared_libs: [
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 109ce7d..98fee12 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -81,7 +81,8 @@
     ],
 
     header_libs: [
-        "libmediadrm_headers"
+        "libmediadrm_headers",
+        "libmediametrics_headers",
     ],
 
     shared_libs: [
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index 816a6b1..9d6d169 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -15,6 +15,9 @@
         "libutils",
         "liblog",
     ],
+    header_libs: [
+        "libmediametrics_headers",
+    ],
 }
 
 // service executable
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index 20f346c..ec59ec1 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -15,6 +15,9 @@
         "libmediautils",
         "libutils",
     ],
+    header_libs: [
+        "libmediametrics_headers",
+    ],
 
     init_rc: [
         "mediametrics.rc",