Merge "C2: Advertise support for FEATURE_QpBounds in s/w video encoders" into main
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index dab7b89..318f093 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -446,6 +446,7 @@
     {
         IntfImpl::Lock lock = mIntf->lock();
         mPixelFormatInfo = mIntf->getPixelFormat_l();
+        mColorAspects = mIntf->getDefaultColorAspects_l();
     }
 
     mWidth = 320;
@@ -591,6 +592,41 @@
         return;
     }
 
+    // handle dynamic config parameters
+    {
+        IntfImpl::Lock lock = mIntf->lock();
+        std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects =
+            mIntf->getDefaultColorAspects_l();
+        lock.unlock();
+
+        if (mColorAspects->range != defaultColorAspects->range ||
+            mColorAspects->primaries != defaultColorAspects->primaries ||
+            mColorAspects->matrix != defaultColorAspects->matrix ||
+            mColorAspects->transfer != defaultColorAspects->transfer) {
+
+            mColorAspects->range = defaultColorAspects->range;
+            mColorAspects->primaries = defaultColorAspects->primaries;
+            mColorAspects->matrix = defaultColorAspects->matrix;
+            mColorAspects->transfer = defaultColorAspects->transfer;
+
+            C2StreamColorAspectsTuning::output colorAspect(0u, defaultColorAspects->range,
+                defaultColorAspects->primaries, defaultColorAspects->transfer,
+                defaultColorAspects->matrix);
+            std::vector<std::unique_ptr<C2SettingResult>> failures;
+            c2_status_t err = mIntf->config({&colorAspect}, C2_MAY_BLOCK, &failures);
+            if (err == C2_OK) {
+                work->worklets.front()->output.configUpdate.push_back(
+                    C2Param::Copy(colorAspect));
+            } else {
+                ALOGE("Config update colorAspect failed");
+                mSignalledError = true;
+                work->workletsProcessed = 1u;
+                work->result = C2_CORRUPTED;
+                return;
+            }
+        }
+    }
+
     size_t inOffset = 0u;
     size_t inSize = 0u;
     C2ReadView rView = mDummyReadView;
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.h b/media/codec2/components/vpx/C2SoftVpxDec.h
index e9d6dc9..93cc213 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.h
+++ b/media/codec2/components/vpx/C2SoftVpxDec.h
@@ -66,6 +66,7 @@
     // configurations used by component in process
     // (TODO: keep this in intf but make them internal only)
     std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormatInfo;
+    std::shared_ptr<C2StreamColorAspectsTuning::output> mColorAspects;
 
     std::shared_ptr<IntfImpl> mIntf;
     vpx_codec_ctx_t *mCodecCtx;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 0af164f..97c9659 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -366,24 +366,26 @@
     if (mIsInput) {
         return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), reply);
     } else {
-        if (mContext.isAsynchronous()) {
+        if (const auto state = getState(); state == StreamDescriptor::State::IDLE) {
             // Handle pause-flush-resume sequence. 'flush' from PAUSED goes to
             // IDLE. We move here from IDLE to ACTIVE (same as 'start' from PAUSED).
-            const auto state = getState();
-            if (state == StreamDescriptor::State::IDLE) {
-                StreamDescriptor::Reply localReply{};
-                StreamDescriptor::Reply* innerReply = reply ?: &localReply;
-                RETURN_STATUS_IF_ERROR(
-                        sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply));
-                if (innerReply->state != StreamDescriptor::State::ACTIVE) {
-                    ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
-                            __func__, toString(innerReply->state).c_str());
-                    return INVALID_OPERATION;
-                }
-                return OK;
+            StreamDescriptor::Reply localReply{};
+            StreamDescriptor::Reply* innerReply = reply ?: &localReply;
+            RETURN_STATUS_IF_ERROR(
+                    sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply));
+            if (innerReply->state != StreamDescriptor::State::ACTIVE) {
+                ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
+                        __func__, toString(innerReply->state).c_str());
+                return INVALID_OPERATION;
             }
+            return OK;
+        } else if (state == StreamDescriptor::State::PAUSED) {
+            return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
+        } else {
+            ALOGE("%s: unexpected stream state: %s (expected IDLE or PAUSED)",
+                        __func__, toString(state).c_str());
+            return INVALID_OPERATION;
         }
-        return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
     }
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index bb49b5a..bd43fe2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2098,9 +2098,12 @@
              displayHeight,
              cropLeft, cropTop);
     } else {
-        CHECK(inputFormat->findInt32("width", &displayWidth));
-        CHECK(inputFormat->findInt32("height", &displayHeight));
-
+        if (!inputFormat->findInt32("width", &displayWidth)
+            || !inputFormat->findInt32("height", &displayHeight)) {
+            ALOGW("Either video width or video height missing, reporting 0x0!");
+            notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0);
+            return;
+        }
         ALOGV("Video input format %d x %d", displayWidth, displayHeight);
     }
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 4e378d4..1a479ac 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -3975,6 +3975,15 @@
                     switch (mState) {
                         case INITIALIZING:
                         {
+                            // Resource error during INITIALIZING state needs to be logged
+                            // through metrics, to be able to track such occurrences.
+                            if (isResourceError(err)) {
+                                mediametrics_setInt32(mMetricsHandle, kCodecError, err);
+                                mediametrics_setCString(mMetricsHandle, kCodecErrorState,
+                                                        stateString(mState).c_str());
+                                flushMediametrics();
+                                initMediametrics();
+                            }
                             setState(UNINITIALIZED);
                             break;
                         }
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
index 4218d2d..3f850c2 100644
--- a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
@@ -24,61 +24,64 @@
 
 namespace android {
 
-#define MAX_MEDIA_BUFFER_SIZE 2048
+static const android_pixel_format_t kColorFormats[] = {
+        HAL_PIXEL_FORMAT_RGBA_8888,
+        HAL_PIXEL_FORMAT_RGB_565,
+        HAL_PIXEL_FORMAT_BGRA_8888,
+        HAL_PIXEL_FORMAT_RGBA_1010102,
+        HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, /* To cover the default case */
+};
 
-// Fuzzer entry point.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-    // Init our wrapper
+static const MediaSource::ReadOptions::SeekMode kSeekModes[] = {
+        MediaSource::ReadOptions::SeekMode::SEEK_PREVIOUS_SYNC,
+        MediaSource::ReadOptions::SeekMode::SEEK_NEXT_SYNC,
+        MediaSource::ReadOptions::SeekMode::SEEK_CLOSEST_SYNC,
+        MediaSource::ReadOptions::SeekMode::SEEK_CLOSEST,
+        MediaSource::ReadOptions::SeekMode::SEEK_FRAME_INDEX,
+};
+
+static const std::string kComponentNames[] = {
+        "c2.android.avc.decoder",  "c2.android.hevc.decoder", "c2.android.vp8.decoder",
+        "c2.android.vp9.decoder",  "c2.android.av1.decoder",  "c2.android.mpeg4.decoder",
+        "c2.android.h263.decoder",
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     FuzzedDataProvider fdp(data, size);
+    std::string component = fdp.PickValueInArray(kComponentNames);
+    AString componentName(component.c_str());
+    sp<MetaData> trackMeta = generateMetaData(&fdp, component);
+    sp<IMediaSource> source = sp<IMediaSourceFuzzImpl>::make(&fdp, gMaxMediaBufferSize);
 
-    std::string name = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
-    AString componentName(name.c_str());
-    sp<MetaData> trackMeta = generateMetaData(&fdp);
-    sp<IMediaSource> source = new IMediaSourceFuzzImpl(&fdp, MAX_MEDIA_BUFFER_SIZE);
-
-    // Image or video Decoder?
-    sp<FrameDecoder> decoder;
-    bool isVideoDecoder = fdp.ConsumeBool();
-    if (isVideoDecoder) {
-        decoder = new VideoFrameDecoder(componentName, trackMeta, source);
+    sp<FrameDecoder> decoder = nullptr;
+    if (fdp.ConsumeBool()) {
+        decoder = sp<MediaImageDecoder>::make(componentName, trackMeta, source);
     } else {
-        decoder = new MediaImageDecoder(componentName, trackMeta, source);
+        decoder = sp<VideoFrameDecoder>::make(componentName, trackMeta, source);
     }
 
-    while (fdp.remaining_bytes()) {
-        uint8_t switchCase = fdp.ConsumeIntegralInRange<uint8_t>(0, 3);
-        switch (switchCase) {
-            case 0: {
-                int64_t frameTimeUs = fdp.ConsumeIntegral<int64_t>();
-                int option = fdp.ConsumeIntegral<int>();
-                int colorFormat = fdp.ConsumeIntegral<int>();
-                decoder->init(frameTimeUs, option, colorFormat);
-                break;
-            }
-            case 1:
-                decoder->extractFrame();
-                break;
-            case 2: {
-                FrameRect rect;
-                rect.left = fdp.ConsumeIntegral<int32_t>();
-                rect.top = fdp.ConsumeIntegral<int32_t>();
-                rect.right = fdp.ConsumeIntegral<int32_t>();
-                rect.bottom = fdp.ConsumeIntegral<int32_t>();
-                decoder->extractFrame(&rect);
-                break;
-            }
-            case 3: {
-                sp<MetaData> trackMeta = generateMetaData(&fdp);
-                decoder->getMetadataOnly(trackMeta,
-                                         /*colorFormat*/ fdp.ConsumeIntegral<int>(),
-                                         /*thumbnail*/ fdp.ConsumeBool());
-                break;
-            }
-        }
+    if (decoder.get() &&
+        decoder->init(fdp.ConsumeIntegral<uint64_t>() /* frameTimeUs */,
+                      fdp.PickValueInArray(kSeekModes) /* option */,
+                      fdp.PickValueInArray(kColorFormats) /* colorFormat */) == OK) {
+        auto frameDecoderAPI = fdp.PickValueInArray<const std::function<void()>>({
+                [&]() { decoder->extractFrame(); },
+                [&]() {
+                    FrameRect rect(fdp.ConsumeIntegral<int32_t>() /* left */,
+                                   fdp.ConsumeIntegral<int32_t>() /* top */,
+                                   fdp.ConsumeIntegral<int32_t>() /* right */,
+                                   fdp.ConsumeIntegral<int32_t>() /* bottom */
+                    );
+                    decoder->extractFrame(&rect);
+                },
+                [&]() {
+                    FrameDecoder::getMetadataOnly(
+                            trackMeta, fdp.PickValueInArray(kColorFormats) /* colorFormat */,
+                            fdp.ConsumeBool() /* thumbnail */);
+                },
+        });
+        frameDecoderAPI();
     }
-
-    generated_mime_types.clear();
-
     return 0;
 }
 
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h
index 228c04a..5430530 100644
--- a/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h
+++ b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h
@@ -20,69 +20,100 @@
 #include <media/stagefright/MetaData.h>
 #include "MediaMimeTypes.h"
 
-#define MAX_METADATA_BUF_SIZE 512
-
 namespace android {
 
 std::vector<std::shared_ptr<char>> generated_mime_types;
+constexpr uint8_t kMinKeyHeight = 32;
+constexpr uint8_t kMinKeyWidth = 32;
+constexpr uint16_t kMaxKeyHeight = 2160;
+constexpr uint16_t kMaxKeyWidth = 3840;
+size_t gMaxMediaBufferSize = 0;
 
-sp<MetaData> generateMetaData(FuzzedDataProvider *fdp) {
-    sp<MetaData> newMeta = new MetaData();
+sp<MetaData> generateMetaData(FuzzedDataProvider* fdp, std::string componentName = std::string()) {
+    sp<MetaData> newMeta = sp<MetaData>::make();
 
-    // random MIME Type
-    const char *mime_type;
-    size_t index = fdp->ConsumeIntegralInRange<size_t>(0, kMimeTypes.size());
-    // Let there be a chance of a true random string
-    if (index == kMimeTypes.size()) {
-        std::string mime_str = fdp->ConsumeRandomLengthString(64);
-        std::shared_ptr<char> mime_cstr(new char[mime_str.length()+1]);
-        generated_mime_types.push_back(mime_cstr);
-        strncpy(mime_cstr.get(), mime_str.c_str(), mime_str.length()+1);
-        mime_type = mime_cstr.get();
-    } else {
-        mime_type = kMimeTypes[index];
+    const char* mime;
+    if(!componentName.empty())
+    {
+        auto it = decoderToMediaType.find(componentName);
+        mime = it->second;
     }
-    newMeta->setCString(kKeyMIMEType, mime_type);
+    else{
+        size_t index = fdp->ConsumeIntegralInRange<size_t>(0, kMimeTypes.size());
+        // Let there be a chance of a true random string
+        if (index == kMimeTypes.size()) {
+            std::string mime_str = fdp->ConsumeRandomLengthString(64);
+            std::shared_ptr<char> mime_cstr(new char[mime_str.length()+1]);
+            generated_mime_types.push_back(mime_cstr);
+            strncpy(mime_cstr.get(), mime_str.c_str(), mime_str.length()+1);
+            mime = mime_cstr.get();
+        } else {
+            mime = kMimeTypes[index];
+        }
+    }
+    newMeta->setCString(kKeyMIMEType, mime);
 
-    // Thumbnail time
-    newMeta->setInt64(kKeyThumbnailTime, fdp->ConsumeIntegral<int64_t>());
+    auto height = fdp->ConsumeIntegralInRange<uint16_t>(kMinKeyHeight, kMaxKeyHeight);
+    auto width = fdp->ConsumeIntegralInRange<uint16_t>(kMinKeyWidth, kMaxKeyWidth);
+    newMeta->setInt32(kKeyHeight, height);
+    newMeta->setInt32(kKeyWidth, width);
 
-    // Values used by allocVideoFrame
-    newMeta->setInt32(kKeyRotation, fdp->ConsumeIntegral<int32_t>());
-    size_t profile_size =
-        fdp->ConsumeIntegralInRange<size_t>(0, MAX_METADATA_BUF_SIZE);
-    std::vector<uint8_t> profile_bytes =
-        fdp->ConsumeBytes<uint8_t>(profile_size);
-    newMeta->setData(kKeyIccProfile,
-                     fdp->ConsumeIntegral<int32_t>(),
-                     profile_bytes.empty() ? nullptr : profile_bytes.data(),
-                     profile_bytes.size());
-    newMeta->setInt32(kKeySARWidth, fdp->ConsumeIntegral<int32_t>());
-    newMeta->setInt32(kKeySARHeight, fdp->ConsumeIntegral<int32_t>());
-    newMeta->setInt32(kKeyDisplayWidth, fdp->ConsumeIntegral<int32_t>());
-    newMeta->setInt32(kKeyDisplayHeight, fdp->ConsumeIntegral<int32_t>());
+    gMaxMediaBufferSize = height * width;
 
-    // Values used by findThumbnailInfo
-    newMeta->setInt32(kKeyThumbnailWidth, fdp->ConsumeIntegral<int32_t>());
-    newMeta->setInt32(kKeyThumbnailHeight, fdp->ConsumeIntegral<int32_t>());
-    size_t thumbnail_size =
-        fdp->ConsumeIntegralInRange<size_t>(0, MAX_METADATA_BUF_SIZE);
-    std::vector<uint8_t> thumb_bytes =
-        fdp->ConsumeBytes<uint8_t>(thumbnail_size);
-    newMeta->setData(kKeyThumbnailHVCC,
-                     fdp->ConsumeIntegral<int32_t>(),
-                     thumb_bytes.empty() ? nullptr : thumb_bytes.data(),
-                     thumb_bytes.size());
+    if (fdp->ConsumeBool()) {
+        newMeta->setInt32(kKeyTileHeight,
+                          fdp->ConsumeIntegralInRange<uint16_t>(kMinKeyHeight, height));
+        newMeta->setInt32(kKeyTileWidth,
+                          fdp->ConsumeIntegralInRange<uint16_t>(kMinKeyWidth, width));
+        newMeta->setInt32(kKeyGridRows, fdp->ConsumeIntegral<uint8_t>());
+        newMeta->setInt32(kKeyGridCols, fdp->ConsumeIntegral<uint8_t>());
+    }
 
-    // Values used by findGridInfo
-    newMeta->setInt32(kKeyTileWidth, fdp->ConsumeIntegral<int32_t>());
-    newMeta->setInt32(kKeyTileHeight, fdp->ConsumeIntegral<int32_t>());
-    newMeta->setInt32(kKeyGridRows, fdp->ConsumeIntegral<int32_t>());
-    newMeta->setInt32(kKeyGridCols, fdp->ConsumeIntegral<int32_t>());
+    if (fdp->ConsumeBool()) {
+        newMeta->setInt32(kKeySARHeight, fdp->ConsumeIntegral<uint8_t>());
+        newMeta->setInt32(kKeySARWidth, fdp->ConsumeIntegral<uint8_t>());
+    }
 
-    // A few functions perform a CHECK() that height/width are set
-    newMeta->setInt32(kKeyHeight, fdp->ConsumeIntegral<int32_t>());
-    newMeta->setInt32(kKeyWidth, fdp->ConsumeIntegral<int32_t>());
+    if (fdp->ConsumeBool()) {
+        newMeta->setInt32(kKeyDisplayHeight,
+                          fdp->ConsumeIntegralInRange<uint16_t>(height, UINT16_MAX));
+        newMeta->setInt32(kKeyDisplayWidth,
+                          fdp->ConsumeIntegralInRange<uint16_t>(width, UINT16_MAX));
+    }
+
+    if (fdp->ConsumeBool()) {
+        newMeta->setRect(kKeyCropRect, fdp->ConsumeIntegral<int32_t>() /* left */,
+                         fdp->ConsumeIntegral<int32_t>() /* top */,
+                         fdp->ConsumeIntegral<int32_t>() /* right */,
+                         fdp->ConsumeIntegral<int32_t>() /* bottom */);
+    }
+
+    if (fdp->ConsumeBool()) {
+        newMeta->setInt32(kKeyRotation, fdp->ConsumeIntegralInRange<uint8_t>(0, 3) * 90);
+    }
+
+    if (fdp->ConsumeBool()) {
+        newMeta->setInt64(kKeyThumbnailTime, fdp->ConsumeIntegral<uint64_t>());
+        newMeta->setInt32(kKeyThumbnailHeight, fdp->ConsumeIntegral<uint8_t>());
+        newMeta->setInt32(kKeyThumbnailWidth, fdp->ConsumeIntegral<uint8_t>());
+
+        size_t thumbnailSize = fdp->ConsumeIntegral<size_t>();
+        std::vector<uint8_t> thumbnailData = fdp->ConsumeBytes<uint8_t>(thumbnailSize);
+        if (mime == MEDIA_MIMETYPE_VIDEO_AV1) {
+            newMeta->setData(kKeyThumbnailAV1C, fdp->ConsumeIntegral<int32_t>() /* type */,
+                             thumbnailData.data(), thumbnailData.size());
+        } else {
+            newMeta->setData(kKeyThumbnailHVCC, fdp->ConsumeIntegral<int32_t>() /* type */,
+                             thumbnailData.data(), thumbnailData.size());
+        }
+    }
+
+    if (fdp->ConsumeBool()) {
+        size_t profileSize = fdp->ConsumeIntegral<size_t>();
+        std::vector<uint8_t> profileData = fdp->ConsumeBytes<uint8_t>(profileSize);
+        newMeta->setData(kKeyIccProfile, fdp->ConsumeIntegral<int32_t>() /* type */,
+                         profileData.data(), profileData.size());
+    }
 
     return newMeta;
 }
diff --git a/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h
index e769950..7e6f662 100644
--- a/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h
+++ b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h
@@ -19,31 +19,33 @@
 
 #include <media/stagefright/MediaSource.h>
 
+#define MAX_FRAMES 5
+
 namespace android {
 
 class IMediaSourceFuzzImpl : public IMediaSource {
  public:
-    IMediaSourceFuzzImpl(FuzzedDataProvider *_fdp, size_t _max_buffer_size) :
-        fdp(_fdp),
-        max_buffer_size(_max_buffer_size) {}
-    status_t start(MetaData*) override { return 0; }
-    status_t stop() override { return 0; }
-    sp<MetaData> getFormat() override { return nullptr; }
-    status_t read(MediaBufferBase**,
-        const MediaSource::ReadOptions*) override;
-    status_t readMultiple(Vector<MediaBufferBase*>*, uint32_t,
-        const MediaSource::ReadOptions*) override;
-    bool supportReadMultiple() override { return true; }
-    bool supportNonblockingRead() override { return true; }
-    status_t pause() override { return 0; }
+   IMediaSourceFuzzImpl(FuzzedDataProvider* _fdp, size_t _max_buffer_size)
+       : frames_read(0), fdp(_fdp), min_buffer_size(32 * 32), max_buffer_size(_max_buffer_size) {}
+   status_t start(MetaData*) override { return 0; }
+   status_t stop() override { return 0; }
+   sp<MetaData> getFormat() override { return nullptr; }
+   status_t read(MediaBufferBase**, const MediaSource::ReadOptions*) override;
+   status_t readMultiple(Vector<MediaBufferBase*>*, uint32_t,
+                         const MediaSource::ReadOptions*) override;
+   bool supportReadMultiple() override { return true; }
+   bool supportNonblockingRead() override { return true; }
+   status_t pause() override { return 0; }
 
  protected:
     IBinder* onAsBinder() { return nullptr; }
 
  private:
-    FuzzedDataProvider *fdp;
-    std::vector<std::shared_ptr<MediaBufferBase>> buffer_bases;
-    const size_t max_buffer_size;
+   uint8_t frames_read;
+   FuzzedDataProvider* fdp;
+   const size_t min_buffer_size;
+   const size_t max_buffer_size;
+   std::vector<uint8_t> buf;
 };
 
 // This class is simply to expose the destructor
@@ -53,32 +55,41 @@
     ~MediaBufferFuzzImpl() {}
 };
 
-status_t IMediaSourceFuzzImpl::read(MediaBufferBase **buffer,
-        const MediaSource::ReadOptions *options) {
+status_t IMediaSourceFuzzImpl::read(MediaBufferBase** buffer, const MediaSource::ReadOptions*) {
     Vector<MediaBufferBase*> buffers;
-    status_t ret = readMultiple(&buffers, 1, options);
+    status_t ret = readMultiple(&buffers, 1, nullptr);
     *buffer = buffers.empty() ? nullptr : buffers[0];
 
     return ret;
 }
 
-status_t IMediaSourceFuzzImpl::readMultiple(Vector<MediaBufferBase*>* buffers,
-        uint32_t maxNumBuffers, const MediaSource::ReadOptions*) {
-    uint32_t num_buffers =
-        fdp->ConsumeIntegralInRange<uint32_t>(0, maxNumBuffers);
-    for(uint32_t i = 0; i < num_buffers; i++) {
-        std::vector<uint8_t> buf = fdp->ConsumeBytes<uint8_t>(
-            fdp->ConsumeIntegralInRange<size_t>(0, max_buffer_size));
+status_t IMediaSourceFuzzImpl::readMultiple(Vector<MediaBufferBase*>* buffers, uint32_t,
+                                            const MediaSource::ReadOptions*) {
+    if (++frames_read == MAX_FRAMES) {
+        auto size = fdp->ConsumeIntegralInRange<size_t>(min_buffer_size, max_buffer_size);
+        buf = fdp->ConsumeBytes<uint8_t>(size);
+        if (buf.size() < size) {
+            buf.resize(size, 0);
+        }
 
-        std::shared_ptr<MediaBufferBase> mbb(
-            new MediaBufferFuzzImpl(buf.data(), buf.size()));
+        MediaBufferBase* mbb = new MediaBufferFuzzImpl(buf.data(), buf.size());
+        mbb->meta_data().setInt64(kKeyTime, fdp->ConsumeIntegral<uint64_t>());
+        buffers->push_back(mbb);
 
-        buffer_bases.push_back(mbb);
-        buffers->push_back(mbb.get());
+        return ERROR_END_OF_STREAM;
     }
 
-    // STATUS_OK
-    return 0;
+    auto size = fdp->ConsumeIntegralInRange<size_t>(min_buffer_size, max_buffer_size);
+    buf = fdp->ConsumeBytes<uint8_t>(size);
+    if (buf.size() < size) {
+        buf.resize(size, 0);
+    }
+
+    MediaBufferBase* mbb = new MediaBufferFuzzImpl(buf.data(), buf.size());
+    mbb->meta_data().setInt64(kKeyTime, fdp->ConsumeIntegral<uint64_t>());
+    buffers->push_back(mbb);
+
+    return OK;
 }
 
 } // namespace android
diff --git a/media/libstagefright/tests/fuzzers/MediaMimeTypes.h b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h
index 9f337ac..de7814e 100644
--- a/media/libstagefright/tests/fuzzers/MediaMimeTypes.h
+++ b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h
@@ -18,6 +18,7 @@
 #define FUZZER_MEDIAMIMETYPES_H_
 
 #include <media/stagefright/foundation/MediaDefs.h>
+#include <unordered_map>
 
 namespace android {
 
@@ -80,6 +81,15 @@
     MEDIA_MIMETYPE_DATA_TIMED_ID3
 };
 
+static const std::unordered_map<std::string, const char*> decoderToMediaType = {
+        {"c2.android.vp8.decoder", MEDIA_MIMETYPE_VIDEO_VP8},
+        {"c2.android.vp9.decoder", MEDIA_MIMETYPE_VIDEO_VP9},
+        {"c2.android.av1.decoder", MEDIA_MIMETYPE_VIDEO_AV1},
+        {"c2.android.avc.decoder", MEDIA_MIMETYPE_VIDEO_AVC},
+        {"c2.android.hevc.decoder", MEDIA_MIMETYPE_VIDEO_HEVC},
+        {"c2.android.mpeg4.decoder", MEDIA_MIMETYPE_VIDEO_MPEG4},
+        {"c2.android.h263.decoder", MEDIA_MIMETYPE_VIDEO_H263}};
+
 }  // namespace android
 
 #endif  // FUZZER_MEDIAMIMETYPES_H_
diff --git a/media/libstagefright/tests/fuzzers/corpus/0ef67b8a074fed50b8875df345ab2e62175c34c9 b/media/libstagefright/tests/fuzzers/corpus/0ef67b8a074fed50b8875df345ab2e62175c34c9
new file mode 100644
index 0000000..652581f
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/corpus/0ef67b8a074fed50b8875df345ab2e62175c34c9
Binary files differ
diff --git a/media/libstagefright/tests/fuzzers/corpus/60eb43c963545c0b2676dad3e4c38cfe87136bbc b/media/libstagefright/tests/fuzzers/corpus/60eb43c963545c0b2676dad3e4c38cfe87136bbc
new file mode 100644
index 0000000..60ca169
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/corpus/60eb43c963545c0b2676dad3e4c38cfe87136bbc
Binary files differ
diff --git a/media/libstagefright/tests/fuzzers/corpus/8c7cb9439f81a8e00b651b3658fe24116f37df7e b/media/libstagefright/tests/fuzzers/corpus/8c7cb9439f81a8e00b651b3658fe24116f37df7e
new file mode 100644
index 0000000..c03bcad
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/corpus/8c7cb9439f81a8e00b651b3658fe24116f37df7e
Binary files differ
diff --git a/media/libstagefright/tests/fuzzers/corpus/c624e73c16c59dfbc3c563416cfc962e3c3a96a0 b/media/libstagefright/tests/fuzzers/corpus/c624e73c16c59dfbc3c563416cfc962e3c3a96a0
new file mode 100644
index 0000000..52f2d5a
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/corpus/c624e73c16c59dfbc3c563416cfc962e3c3a96a0
Binary files differ
diff --git a/media/libstagefright/tests/fuzzers/corpus/c6aff0d7ccaf58a1964a6bcc51777bf1786503ca b/media/libstagefright/tests/fuzzers/corpus/c6aff0d7ccaf58a1964a6bcc51777bf1786503ca
new file mode 100644
index 0000000..83c522f
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/corpus/c6aff0d7ccaf58a1964a6bcc51777bf1786503ca
Binary files differ
diff --git a/media/libstagefright/tests/fuzzers/corpus/ec6bd6069f74a2f6e92442f88efb29288ad6f456 b/media/libstagefright/tests/fuzzers/corpus/ec6bd6069f74a2f6e92442f88efb29288ad6f456
new file mode 100644
index 0000000..62d259b
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/corpus/ec6bd6069f74a2f6e92442f88efb29288ad6f456
Binary files differ
diff --git a/media/libstagefright/tests/fuzzers/corpus/fbf47d9a9173df0a39285c94d89fcbc767d5e774 b/media/libstagefright/tests/fuzzers/corpus/fbf47d9a9173df0a39285c94d89fcbc767d5e774
new file mode 100644
index 0000000..db78b75
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/corpus/fbf47d9a9173df0a39285c94d89fcbc767d5e774
Binary files differ
diff --git a/services/mediaresourcemanager/ResourceManagerMetrics.cpp b/services/mediaresourcemanager/ResourceManagerMetrics.cpp
index cd00937..a8a1de1 100644
--- a/services/mediaresourcemanager/ResourceManagerMetrics.cpp
+++ b/services/mediaresourcemanager/ResourceManagerMetrics.cpp
@@ -109,23 +109,17 @@
     return CodecBucketUnspecified;
 }
 
-static bool getLogMessage(int hwCount, int swCount, std::stringstream& logMsg) {
-    bool update = false;
-    logMsg.clear();
+static std::string getLogMessage(const std::string& firstKey, const long& firstValue,
+                                 const std::string& secondKey, const long& secondValue) {
 
-    if (hwCount > 0) {
-        logMsg << " HW: " << hwCount;
-        update = true;
+    std::stringstream logMsg;
+    if (firstValue > 0) {
+        logMsg << firstKey << firstValue;
     }
-    if (swCount > 0) {
-        logMsg << " SW: " << swCount;
-        update = true;
+    if (secondValue > 0) {
+        logMsg << secondKey << secondValue;
     }
-
-    if (update) {
-        logMsg << " ] ";
-    }
-    return update;
+    return logMsg.str();
 }
 
 ResourceManagerMetrics::ResourceManagerMetrics(const sp<ProcessInfoInterface>& processInfo) {
@@ -364,6 +358,15 @@
     std::scoped_lock lock(mLock);
     // post MediaCodecConcurrentUsageReported for this terminated pid.
     pushConcurrentUsageReport(pid, uid);
+    // Remove all the metrics associated with this process.
+    std::map<int32_t, ConcurrentCodecs>::iterator it1 = mProcessConcurrentCodecsMap.find(pid);
+    if (it1 != mProcessConcurrentCodecsMap.end()) {
+        mProcessConcurrentCodecsMap.erase(it1);
+    }
+    std::map<int32_t, PixelCount>::iterator it2 = mProcessPixelsMap.find(pid);
+    if (it2 != mProcessPixelsMap.end()) {
+        mProcessPixelsMap.erase(it2);
+    }
 }
 
 void ResourceManagerMetrics::pushConcurrentUsageReport(int32_t pid, uid_t uid) {
@@ -400,24 +403,30 @@
 
     std::stringstream peakCodecLog;
     peakCodecLog << "Peak { ";
-    std::stringstream logMsg;
-    if (getLogMessage(peakHwAudioEncoderCount, peakSwAudioEncoderCount, logMsg)) {
-        peakCodecLog << "AudioEnc[" << logMsg.str();
+    std::string logMsg;
+    logMsg = getLogMessage(" HW: ", peakHwAudioEncoderCount, " SW: ", peakSwAudioEncoderCount);
+    if (!logMsg.empty()) {
+        peakCodecLog << "AudioEnc[ " << logMsg << " ] ";
     }
-    if (getLogMessage(peakHwAudioDecoderCount, peakSwAudioDecoderCount, logMsg)) {
-        peakCodecLog << "AudioDec[" << logMsg.str();
+    logMsg = getLogMessage(" HW: ", peakHwAudioDecoderCount, " SW: ", peakSwAudioDecoderCount);
+    if (!logMsg.empty()) {
+        peakCodecLog << "AudioDec[" << logMsg << " ] ";
     }
-    if (getLogMessage(peakHwVideoEncoderCount, peakSwVideoEncoderCount, logMsg)) {
-        peakCodecLog << "VideoEnc[" << logMsg.str();
+    logMsg = getLogMessage(" HW: ", peakHwVideoEncoderCount, " SW: ", peakSwVideoEncoderCount);
+    if (!logMsg.empty()) {
+        peakCodecLog << "VideoEnc[" << logMsg << " ] ";
     }
-    if (getLogMessage(peakHwVideoDecoderCount, peakSwVideoDecoderCount, logMsg)) {
-        peakCodecLog << "VideoDec[" << logMsg.str();
+    logMsg = getLogMessage(" HW: ", peakHwVideoDecoderCount, " SW: ", peakSwVideoDecoderCount);
+    if (!logMsg.empty()) {
+        peakCodecLog << "VideoDec[" << logMsg << " ] ";
     }
-    if (getLogMessage(peakHwImageEncoderCount, peakSwImageEncoderCount, logMsg)) {
-        peakCodecLog << "ImageEnc[" << logMsg.str();
+    logMsg = getLogMessage(" HW: ", peakHwImageEncoderCount, " SW: ", peakSwImageEncoderCount);
+    if (!logMsg.empty()) {
+        peakCodecLog << "ImageEnc[" << logMsg << " ] ";
     }
-    if (getLogMessage(peakHwImageDecoderCount, peakSwImageDecoderCount, logMsg)) {
-        peakCodecLog << "ImageDec[" << logMsg.str();
+    logMsg = getLogMessage(" HW: ", peakHwImageDecoderCount, " SW: ", peakSwImageDecoderCount);
+    if (!logMsg.empty()) {
+        peakCodecLog << "ImageDec[" << logMsg << " ] ";
     }
     peakCodecLog << "}";
 
@@ -705,4 +714,114 @@
     return 0;
 }
 
+static std::string getConcurrentInstanceCount(const std::map<std::string, int>& resourceMap) {
+    if (resourceMap.empty()) {
+        return "";
+    }
+    std::stringstream concurrentInstanceInfo;
+    for (const auto& [name, count] : resourceMap) {
+        if (count > 0) {
+            concurrentInstanceInfo << "      Name: " << name << " Instances: " << count << "\n";
+        }
+    }
+
+    std::string info = concurrentInstanceInfo.str();
+    if (info.empty()) {
+        return "";
+    }
+    return "    Current Concurrent Codec Instances:\n" + info;
+}
+
+static std::string getAppsPixelCount(const std::map<int32_t, PixelCount>& pixelMap) {
+    if (pixelMap.empty()) {
+        return "";
+    }
+    std::stringstream pixelInfo;
+    for (const auto& [pid, pixelCount] : pixelMap) {
+        std::string logMsg = getLogMessage(" Current Pixels: ", pixelCount.mCurrent,
+                                           " Peak Pixels: ", pixelCount.mPeak);
+        if (!logMsg.empty()) {
+            pixelInfo  << "      PID[" << pid << "]: {" << logMsg << " }\n";
+        }
+    }
+
+    return "    Applications Pixel Usage:\n" + pixelInfo.str();
+}
+
+static std::string getCodecUsageMetrics(const ConcurrentCodecsMap& codecsMap) {
+    int peakHwAudioEncoderCount = codecsMap[HwAudioEncoder];
+    int peakHwAudioDecoderCount = codecsMap[HwAudioDecoder];
+    int peakHwVideoEncoderCount = codecsMap[HwVideoEncoder];
+    int peakHwVideoDecoderCount = codecsMap[HwVideoDecoder];
+    int peakHwImageEncoderCount = codecsMap[HwImageEncoder];
+    int peakHwImageDecoderCount = codecsMap[HwImageDecoder];
+    int peakSwAudioEncoderCount = codecsMap[SwAudioEncoder];
+    int peakSwAudioDecoderCount = codecsMap[SwAudioDecoder];
+    int peakSwVideoEncoderCount = codecsMap[SwVideoEncoder];
+    int peakSwVideoDecoderCount = codecsMap[SwVideoDecoder];
+    int peakSwImageEncoderCount = codecsMap[SwImageEncoder];
+    int peakSwImageDecoderCount = codecsMap[SwImageDecoder];
+    std::stringstream usageMetrics;
+    std::string logMsg;
+    logMsg = getLogMessage(" HW: ", peakHwAudioEncoderCount, " SW: ", peakSwAudioEncoderCount);
+    if (!logMsg.empty()) {
+        usageMetrics << "AudioEnc[" << logMsg << " ] ";
+    }
+    logMsg = getLogMessage(" HW: ", peakHwAudioDecoderCount, " SW: ", peakSwAudioDecoderCount);
+    if (!logMsg.empty()) {
+        usageMetrics << "AudioDec[" << logMsg << " ] ";
+    }
+    logMsg = getLogMessage(" HW: ", peakHwVideoEncoderCount, " SW: ", peakSwVideoEncoderCount);
+    if (!logMsg.empty()) {
+        usageMetrics << "VideoEnc[" << logMsg << " ] ";
+    }
+    logMsg = getLogMessage(" HW: ", peakHwVideoDecoderCount, " SW: ", peakSwVideoDecoderCount);
+    if (!logMsg.empty()) {
+        usageMetrics << "VideoDec[" << logMsg << " ] ";
+    }
+    logMsg = getLogMessage(" HW: ", peakHwImageEncoderCount, " SW: ", peakSwImageEncoderCount);
+    if (!logMsg.empty()) {
+        usageMetrics << "ImageEnc[" << logMsg << " ] ";
+    }
+    logMsg = getLogMessage(" HW: ", peakHwImageDecoderCount, " SW: ", peakSwImageDecoderCount);
+    if (!logMsg.empty()) {
+        usageMetrics << "ImageDec[" << logMsg << " ] ";
+    }
+
+    return usageMetrics.str();
+}
+
+static std::string getAppsCodecUsageMetrics(
+        const std::map<int32_t, ConcurrentCodecs>& processCodecsMap) {
+    if (processCodecsMap.empty()) {
+        return "";
+    }
+    std::stringstream codecUsage;
+    std::string info;
+    for (const auto& [pid, codecMap] : processCodecsMap) {
+        codecUsage << "      PID[" << pid << "]: ";
+        info = getCodecUsageMetrics(codecMap.mCurrent);
+        if (!info.empty()) {
+            codecUsage << "Current Codec Usage: { " << info << "} ";
+        }
+        info = getCodecUsageMetrics(codecMap.mPeak);
+        if (!info.empty()) {
+            codecUsage << "Peak Codec Usage: { " << info << "}";
+        }
+        codecUsage << "\n";
+    }
+
+    return "    Applications Codec Usage:\n" + codecUsage.str();
+}
+
+
+std::string ResourceManagerMetrics::dump() const {
+    std::string metricsLog("  Metrics logs:\n");
+    metricsLog += getConcurrentInstanceCount(mConcurrentResourceCountMap);
+    metricsLog += getAppsPixelCount(mProcessPixelsMap);
+    metricsLog += getAppsCodecUsageMetrics(mProcessConcurrentCodecsMap);
+
+    return std::move(metricsLog);
+}
+
 } // namespace android
diff --git a/services/mediaresourcemanager/ResourceManagerMetrics.h b/services/mediaresourcemanager/ResourceManagerMetrics.h
index 7a5a89f..9904f7d 100644
--- a/services/mediaresourcemanager/ResourceManagerMetrics.h
+++ b/services/mediaresourcemanager/ResourceManagerMetrics.h
@@ -171,6 +171,9 @@
     // Get the current concurrent pixel count (associated with the video codecs) for the process.
     long getCurrentConcurrentPixelCount(int pid) const;
 
+    // retrieves metrics log.
+    std::string dump() const;
+
 private:
     ResourceManagerMetrics(const ResourceManagerMetrics&) = delete;
     ResourceManagerMetrics(ResourceManagerMetrics&&) = delete;
@@ -204,9 +207,9 @@
     // Map of resources (name) and number of concurrent instances
     std::map<std::string, int> mConcurrentResourceCountMap;
 
-    // Map of concurrent codes by CodecBucket across the system.
+    // Map of concurrent codecs by CodecBucket across the system.
     ConcurrentCodecsMap mConcurrentCodecsMap;
-    // Map of concurrent and peak codes by CodecBucket for each process/application.
+    // Map of concurrent and peak codecs by CodecBucket for each process/application.
     std::map<int32_t, ConcurrentCodecs> mProcessConcurrentCodecsMap;
 
     // Uid Observer to monitor the application termination.
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index d37d893..9c2fb7c 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -108,10 +108,17 @@
         serviceLog = mServiceLog->toString("    " /* linePrefix */);
     }
 
-    // Get all the resource (and overload pid) logs
+    // Get all the resource (and overload pid) log.
     std::string resourceLog;
     getResourceDump(resourceLog);
 
+    // Get all the metrics log.
+    std::string metricsLog;
+    {
+        std::scoped_lock lock{mLock};
+        metricsLog = mResourceManagerMetrics->dump();
+    }
+
     const size_t SIZE = 256;
     char buffer[SIZE];
     snprintf(buffer, SIZE, "ResourceManagerService: %p\n", this);
@@ -123,11 +130,16 @@
             supportsSecureWithNonSecureCodec);
     result.append(buffer);
 
+    // Add resource log.
     result.append(resourceLog.c_str());
 
+    // Add service log.
     result.append("  Events logs (most recent at top):\n");
     result.append(serviceLog);
 
+    // Add metrics log.
+    result.append(metricsLog.c_str());
+
     write(fd, result.c_str(), result.size());
     return OK;
 }