Add PixelStreamMangerFuzzer with guided input

Bug: 160002800
Test: adb shell ./data/fuzz/arm64/computepipe_pixel_mem_handle_fuzzer/computepipe_pixel_mem_handle_fuzzer
Change-Id: I235e44e8ab26a2e431624a0b03a24022820e7f45
Merged-In: I235e44e8ab26a2e431624a0b03a24022820e7f45
(cherry picked from commit 801ab199f927c294ab49869302864a3474b48350)
diff --git a/computepipe/tests/fuzz/Android.bp b/computepipe/tests/fuzz/Android.bp
index dff74b8..97f3435 100644
--- a/computepipe/tests/fuzz/Android.bp
+++ b/computepipe/tests/fuzz/Android.bp
@@ -12,10 +12,28 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_fuzz {
-    name: "computepipe_semantic_manager_fuzzer",
+cc_library_static {
+    name: "libcomputepipeprotosfuzz",
+    proto: {
+        export_proto_headers: true,
+    },
+    shared_libs: ["libprotobuf-cpp-full"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+    ],
     srcs: [
-        "SemanticManagerFuzzer.cpp",
+        "Fuzz.proto",
+    ],
+}
+
+cc_defaults {
+    name: "libcomputepipefuzz-defaults",
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
     ],
     static_libs: [
         "computepipe_runner_component",
@@ -39,3 +57,26 @@
         "packages/services/Car/computepipe/runner/stream_manager",
     ],
 }
+
+cc_fuzz {
+    name: "computepipe_semantic_manager_fuzzer",
+    defaults: ["libcomputepipefuzz-defaults"],
+    srcs: [
+        "SemanticManagerFuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "computepipe_pixel_mem_handle_fuzzer",
+    defaults: ["libcomputepipefuzz-defaults"],
+    srcs: [
+        "PixelMemHandleFuzzer.cpp",
+    ],
+    shared_libs: [
+         "libprotobuf-cpp-full",
+    ],
+    static_libs: [
+        "libcomputepipeprotosfuzz",
+        "libprotobuf-mutator",
+    ],
+}
diff --git a/computepipe/tests/fuzz/Fuzz.proto b/computepipe/tests/fuzz/Fuzz.proto
new file mode 100644
index 0000000..31495d8
--- /dev/null
+++ b/computepipe/tests/fuzz/Fuzz.proto
@@ -0,0 +1,21 @@
+syntax = "proto2";
+
+package android.automotive.computepipe.fuzz.proto;
+
+enum PixelFormat {
+    RGB = 0;
+    RGBA = 1;
+    GRAY = 2;
+}
+
+message Frame {
+    required uint32 height = 1;
+    required uint32 width = 2;
+    required PixelFormat format  = 3;
+    required uint32 stride = 4;
+    required string buffer = 5;
+}
+
+message PixelMemHandleFuzzerInput {
+    repeated Frame frames = 1;
+}
\ No newline at end of file
diff --git a/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp b/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp
new file mode 100644
index 0000000..3e98e2a
--- /dev/null
+++ b/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright 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.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <vndk/hardware_buffer.h>
+
+#include "InputFrame.h"
+#include "PixelFormatUtils.h"
+#include "PixelStreamManager.h"
+#include "gmock/gmock-matchers.h"
+#include "Fuzz.pb.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+namespace android {
+namespace automotive {
+namespace computepipe {
+namespace runner {
+namespace stream_manager {
+namespace {
+
+InputFrame convertToInputFrame(const fuzz::proto::Frame frame) {
+    uint32_t height = frame.height();
+    uint32_t width = frame.width();
+    uint32_t stride = frame.stride();
+    PixelFormat pixelFormat = static_cast<PixelFormat>(frame.format());
+    const uint8_t* data = reinterpret_cast<const uint8_t*>(frame.buffer().c_str());
+    return InputFrame(height, width, pixelFormat, stride, data);
+}
+
+int setFrameDataTest(const fuzz::proto::PixelMemHandleFuzzerInput& input) {
+    int bufferId = 10;
+    int streamId = 1;
+    uint64_t timestamp = 100;
+
+    PixelMemHandle memHandle(bufferId, streamId, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN);
+    InputFrame oldInputFrame = convertToInputFrame(input.frames().Get(0));
+    memHandle.setFrameData(timestamp, oldInputFrame);
+
+    // overwrite frame data with different format and dimensions
+    InputFrame newInputFrame = convertToInputFrame(input.frames().Get(1));
+    memHandle.setFrameData(timestamp, newInputFrame);
+
+    AHardwareBuffer_Desc desc;
+    AHardwareBuffer* buffer = memHandle.getHardwareBuffer();
+    AHardwareBuffer_describe(buffer, &desc);
+    return 0;
+}
+
+bool isValid(const fuzz::proto::PixelMemHandleFuzzerInput& input) {
+    for (auto& frame : input.frames()) {
+        uint64_t height = frame.height();
+        uint64_t width = frame.width();
+        uint64_t stride = frame.stride();
+        uint64_t size = frame.buffer().size();
+        if (stride > width * height) {
+            return false;
+        }
+
+        if (height * width != size) {
+            return false;
+        }
+
+        if (height * width == 0) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// generate guided and mutated frame data for fuzzing
+DEFINE_PROTO_FUZZER(const fuzz::proto::PixelMemHandleFuzzerInput& input) {
+    static PostProcessorRegistration reg = {
+            [](const fuzz::proto::PixelMemHandleFuzzerInput* input, unsigned int seed) {
+                if (input->frames().size() < 2) {
+                    return;
+                }
+
+                if (!isValid(*input)) {
+                    return;
+                }
+
+                setFrameDataTest(*input);
+            }
+    };
+}
+
+}  // namespace
+}  // namespace stream_manager
+}  // namespace runner
+}  // namespace computepipe
+}  // namespace automotive
+}  // namespace android