Merge "Add PixelStreamMangerFuzzer with guided input" into rvc-qpr-dev
diff --git a/computepipe/runner/graph/GrpcGraph.cpp b/computepipe/runner/graph/GrpcGraph.cpp
index 6967230..efd56c9 100644
--- a/computepipe/runner/graph/GrpcGraph.cpp
+++ b/computepipe/runner/graph/GrpcGraph.cpp
@@ -65,6 +65,10 @@
 
 }  // namespace
 
+GrpcGraph::~GrpcGraph() {
+    mStreamSetObserver.reset();
+}
+
 PrebuiltGraphState GrpcGraph::GetGraphState() const {
     std::lock_guard lock(mLock);
     return mGraphState;
diff --git a/computepipe/runner/graph/GrpcGraph.h b/computepipe/runner/graph/GrpcGraph.h
index d833dd2..0805e35 100644
--- a/computepipe/runner/graph/GrpcGraph.h
+++ b/computepipe/runner/graph/GrpcGraph.h
@@ -45,7 +45,7 @@
   public:
     GrpcGraph() {}
 
-    virtual ~GrpcGraph() {}
+    virtual ~GrpcGraph();
 
     Status initialize(const std::string& address,
                       std::weak_ptr<PrebuiltEngineInterface> engineInterface);
diff --git a/computepipe/runner/graph/StreamSetObserver.cpp b/computepipe/runner/graph/StreamSetObserver.cpp
index 30e3b54..2586b51 100644
--- a/computepipe/runner/graph/StreamSetObserver.cpp
+++ b/computepipe/runner/graph/StreamSetObserver.cpp
@@ -157,10 +157,9 @@
     std::unique_lock lock(mLock);
     if (mStopped) {
         // Separate thread is necessary here to avoid recursive locking.
-        std::thread t([streamGraphInterface(mStreamGraphInterface)]() {
-            streamGraphInterface->dispatchGraphTerminationMessage(Status::SUCCESS, "");
+        mGraphTerminationThread = std::thread([this]() {
+            this->mStreamGraphInterface->dispatchGraphTerminationMessage(Status::SUCCESS, "");
         });
-        t.detach();
         return;
     }
 
@@ -184,10 +183,16 @@
     if (mStreamObservers.empty()) {
         mStopped = true;
         mStoppedCv.notify_one();
-        std::thread t([streamGraphInterface(mStreamGraphInterface)]() {
+        mGraphTerminationThread = std::thread([streamGraphInterface(mStreamGraphInterface)]() {
             streamGraphInterface->dispatchGraphTerminationMessage(Status::SUCCESS, "");
         });
-        t.detach();
+    }
+}
+
+StreamSetObserver::~StreamSetObserver() {
+    std::unique_lock lock(mLock);
+    if (mGraphTerminationThread.joinable()) {
+        mGraphTerminationThread.join();
     }
 }
 
diff --git a/computepipe/runner/graph/StreamSetObserver.h b/computepipe/runner/graph/StreamSetObserver.h
index 7999f18..fe3f40f 100644
--- a/computepipe/runner/graph/StreamSetObserver.h
+++ b/computepipe/runner/graph/StreamSetObserver.h
@@ -78,6 +78,8 @@
 
 class StreamSetObserver : public EndOfStreamReporter {
   public:
+    virtual ~StreamSetObserver();
+
     StreamSetObserver(const runner::ClientConfig& clientConfig,
                       StreamGraphInterface* streamGraphInterface);
 
@@ -92,6 +94,7 @@
     std::map<int, std::unique_ptr<SingleStreamObserver>> mStreamObservers;
     std::mutex mLock;
     std::condition_variable mStoppedCv;
+    std::thread mGraphTerminationThread;
     bool mStopped = true;
 };
 
diff --git a/evs/manager/1.1/test/fuzzer/EnumeratorFuzzer.cpp b/evs/manager/1.1/test/fuzzer/EnumeratorFuzzer.cpp
index d0bfebf..476dc3f 100644
--- a/evs/manager/1.1/test/fuzzer/EnumeratorFuzzer.cpp
+++ b/evs/manager/1.1/test/fuzzer/EnumeratorFuzzer.cpp
@@ -62,7 +62,7 @@
 static vector<sp<IEvsCamera_1_0>> sVirtualCameras;
 static vector<sp<IEvsDisplay_1_0>> sDisplays;
 
-extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+bool DoInitialization() {
     setenv("TREBLE_TESTING_OVERRIDE", "true", true);
     configureRpcThreadpool(2, false /* callerWillNotJoin */);
 
@@ -76,24 +76,23 @@
         exit(2);
     }
 
-    // Inititialize the enumerator that we are going to test
-    // TODO(b/162631113) if we place the initialization of enumerator inside
-    // LLVMFuzzerTestOneInput, there will be issues in destruction.
-    sEnumerator = new Enumerator();
-    if (!sEnumerator->init(kMockHWEnumeratorName)) {
-        std::cerr << "Failed to connect to hardware service"
-                  << "- quitting from LLVMFuzzerInitialize" << std::endl;
-        exit(1);
-    }
-
-    return 0;
+    return true;
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     FuzzedDataProvider fdp(data, size);
 
+    // Inititialize the enumerator that we are going to test
+    static bool initialized = DoInitialization();
+    sEnumerator = new Enumerator();
+    if (!initialized || !sEnumerator->init(kMockHWEnumeratorName)) {
+        std::cerr << "Failed to connect to hardware service"
+                  << "- quitting from LLVMFuzzerInitialize" << std::endl;
+        exit(1);
+    }
+
     while (fdp.remaining_bytes() > kMaxFuzzerConsumedBytes) {
-        switch (fdp.ConsumeIntegralInRange<uint32_t>(0, EVS_FUZZ_API_SUM)) {
+        switch (fdp.ConsumeIntegralInRange<uint32_t>(0, EVS_FUZZ_API_SUM - 1)) {
             case EVS_FUZZ_GET_CAMERA_LIST: {
                 sEnumerator->getCameraList([](auto list){});
                 break;
@@ -102,7 +101,7 @@
                 uint64_t whichCam =
                             fdp.ConsumeIntegralInRange<uint64_t>(startMockHWCameraId,
                                                                  endMockHWCameraId-1);
-                hidl_string camStr = to_string(whichCam);
+                hidl_string camStr = std::to_string(whichCam);
                 sp<IEvsCamera_1_0> virtualCam = sEnumerator->openCamera(camStr);
                 if (virtualCam != nullptr) {
                     sVirtualCameras.emplace_back(virtualCam);
@@ -144,7 +143,7 @@
                 uint64_t whichCam =
                             fdp.ConsumeIntegralInRange<uint64_t>(startMockHWCameraId,
                                                                  endMockHWCameraId-1);
-                hidl_string camStr = to_string(whichCam);
+                hidl_string camStr = std::to_string(whichCam);
                 Stream streamCfg = {};
                 sp<IEvsCamera_1_1> virtualCam = sEnumerator->openCamera_1_1(camStr, streamCfg);
                 if (virtualCam != nullptr) {
@@ -191,6 +190,8 @@
                 break;
         }
     }
+    // Explicitly destroy the Enumerator
+    sEnumerator = nullptr;
     return 0;
 }
 
diff --git a/evs/manager/1.1/test/fuzzer/HalCameraFuzzer.cpp b/evs/manager/1.1/test/fuzzer/HalCameraFuzzer.cpp
index 4660182..a414593 100644
--- a/evs/manager/1.1/test/fuzzer/HalCameraFuzzer.cpp
+++ b/evs/manager/1.1/test/fuzzer/HalCameraFuzzer.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <fuzzer/FuzzedDataProvider.h>
+#include <sys/time.h>
 #include <iostream>
 #include "Common.h"
 #include "Enumerator.h"
@@ -47,14 +48,25 @@
     EVS_FUZZ_BASE_ENUM                   // verify common functions
 };
 
+int64_t getCurrentTimeStamp() {
+    struct timeval tp;
+    gettimeofday(&tp, NULL);
+    int64_t ms = tp.tv_sec * 1000 + tp.tv_usec / 1000;
+    return ms;
+}
+
+const int kMaxFuzzerConsumedBytes = 12;
+
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     FuzzedDataProvider fdp(data, size);
     sp<IEvsCamera_1_1> mockHWCamera = new MockHWCamera();
     sp<HalCamera> halCamera = new HalCamera(mockHWCamera);
     std::vector<sp<VirtualCamera>> virtualCameras;
+    std::vector<BufferDesc_1_0> vBufferDesc_1_0;
+    std::vector<BufferDesc_1_1> vBufferDesc_1_1;
 
-    while (fdp.remaining_bytes() > 4) {
-        switch (fdp.ConsumeIntegralInRange<uint32_t>(0, EVS_FUZZ_API_SUM)) {
+    while (fdp.remaining_bytes() > kMaxFuzzerConsumedBytes) {
+        switch (fdp.ConsumeIntegralInRange<uint32_t>(0, EVS_FUZZ_API_SUM - 1)) {
             case EVS_FUZZ_MAKE_VIRTUAL_CAMERA: {
                 sp<VirtualCamera> virtualCamera = halCamera->makeVirtualCamera();
                 virtualCameras.emplace_back(virtualCamera);
@@ -97,6 +109,131 @@
                 halCamera->changeFramesInFlight(delta);
                 break;
             }
+            case EVS_FUZZ_CHANGE_FRAMES_IN_FLIGHT_1: {
+                hidl_vec<BufferDesc_1_1> buffers;
+                int32_t delta = 0;
+                halCamera->changeFramesInFlight(buffers, &delta);
+                break;
+            }
+            case EVS_FUZZ_REQUEST_NEW_FRAME: {
+                if (!virtualCameras.empty()) {
+                    uint32_t whichCam =
+                            fdp.ConsumeIntegralInRange<uint32_t>(0, virtualCameras.size() - 1);
+                    halCamera->requestNewFrame(virtualCameras[whichCam], getCurrentTimeStamp());
+                }
+                break;
+            }
+            case EVS_FUZZ_CLIENT_STREAM_STARTING: {
+                halCamera->clientStreamStarting();
+                break;
+            }
+            case EVS_FUZZ_CLIENT_STREAM_ENDING: {
+                if (!virtualCameras.empty()) {
+                    uint32_t whichCam =
+                            fdp.ConsumeIntegralInRange<uint32_t>(0, virtualCameras.size() - 1);
+                    halCamera->clientStreamEnding(virtualCameras[whichCam].get());
+                }
+                break;
+            }
+            case EVS_FUZZ_DONE_WITH_FRAME_1_0: {
+                if (!vBufferDesc_1_0.empty()) {
+                    uint32_t whichBuffer =
+                            fdp.ConsumeIntegralInRange<uint32_t>(0, vBufferDesc_1_0.size() - 1);
+                    halCamera->doneWithFrame(vBufferDesc_1_0[whichBuffer]);
+                }
+                break;
+            }
+            case EVS_FUZZ_DONE_WITH_FRAME_1_1: {
+                if (!vBufferDesc_1_1.empty()) {
+                    uint32_t whichBuffer =
+                            fdp.ConsumeIntegralInRange<uint32_t>(0, vBufferDesc_1_1.size() - 1);
+                    halCamera->doneWithFrame(vBufferDesc_1_1[whichBuffer]);
+                }
+                break;
+            }
+            case EVS_FUZZ_SET_PRIMARY: {
+                if (!virtualCameras.empty()) {
+                    uint32_t whichCam =
+                            fdp.ConsumeIntegralInRange<uint32_t>(0, virtualCameras.size() - 1);
+                    halCamera->setMaster(virtualCameras[whichCam]);
+                }
+                break;
+            }
+            case EVS_FUZZ_FORCE_PRIMARY: {
+                if (!virtualCameras.empty()) {
+                    uint32_t whichCam =
+                            fdp.ConsumeIntegralInRange<uint32_t>(0, virtualCameras.size() - 1);
+                    halCamera->forceMaster(virtualCameras[whichCam]);
+                }
+                break;
+            }
+            case EVS_FUZZ_UNSET_PRIMARY: {
+                if (!virtualCameras.empty()) {
+                    uint32_t whichCam =
+                            fdp.ConsumeIntegralInRange<uint32_t>(0, virtualCameras.size() - 1);
+                    halCamera->unsetMaster(virtualCameras[whichCam]);
+                }
+                break;
+            }
+            case EVS_FUZZ_SET_PARAMETER: {
+                if (!virtualCameras.empty()) {
+                    uint32_t whichCam =
+                            fdp.ConsumeIntegralInRange<uint32_t>(0, virtualCameras.size() - 1);
+                    uint32_t whichParam = fdp.ConsumeIntegralInRange<
+                            uint32_t>(0, static_cast<uint32_t>(CameraParam::ABSOLUTE_ZOOM));
+                    int32_t value = fdp.ConsumeIntegral<int32_t>();
+                    halCamera->setParameter(virtualCameras[whichCam],
+                                            static_cast<CameraParam>(whichParam), value);
+                }
+                break;
+            }
+            case EVS_FUZZ_GET_PARAMETER: {
+                uint32_t whichParam =
+                        fdp.ConsumeIntegralInRange<uint32_t>(0,
+                                                             static_cast<uint32_t>(
+                                                                     CameraParam::ABSOLUTE_ZOOM));
+                int32_t value = fdp.ConsumeIntegral<int32_t>();
+                halCamera->getParameter(static_cast<CameraParam>(whichParam), value);
+                break;
+            }
+            case EVS_FUZZ_GET_STATS: {
+                halCamera->getStats();
+                break;
+            }
+            case EVS_FUZZ_GET_STREAM_CONFIGURATION: {
+                halCamera->getStreamConfiguration();
+                break;
+            }
+            case EVS_FUZZ_DELIVER_FRAME: {
+                BufferDesc_1_0 buffer;
+                buffer.bufferId = fdp.ConsumeIntegral<int32_t>();
+                halCamera->deliverFrame(buffer);
+                vBufferDesc_1_0.emplace_back(buffer);
+                break;
+            }
+            case EVS_FUZZ_DELIVER_FRAME_1_1: {
+                std::vector<BufferDesc_1_1> vec;
+                BufferDesc_1_1 buffer;
+                buffer.bufferId = fdp.ConsumeIntegral<int32_t>();
+                vec.push_back(buffer);
+                hardware::hidl_vec<BufferDesc_1_1> hidl_vec(vec);
+                halCamera->deliverFrame_1_1(hidl_vec);
+                vBufferDesc_1_1.emplace_back(buffer);
+                break;
+            }
+            case EVS_FUZZ_NOTIFY: {
+                EvsEventDesc event;
+                uint32_t type =
+                        fdp.ConsumeIntegralInRange<uint32_t>(0,
+                                                             static_cast<uint32_t>(
+                                                                     EvsEventType::STREAM_ERROR));
+                event.aType = static_cast<EvsEventType>(type);
+                // TODO(b/160824438) let's comment this for now because of the failure.
+                // If virtualCamera does not call startVideoStream, and notify(1) is called
+                // it will fail.
+                // halCamera->notify(event);
+                break;
+            }
             default:
                 LOG(ERROR) << "Unexpected option, aborting...";
                 break;
diff --git a/evs/manager/1.1/test/fuzzer/HalDisplayFuzzer.cpp b/evs/manager/1.1/test/fuzzer/HalDisplayFuzzer.cpp
index 8ccc057..3e88d0d 100644
--- a/evs/manager/1.1/test/fuzzer/HalDisplayFuzzer.cpp
+++ b/evs/manager/1.1/test/fuzzer/HalDisplayFuzzer.cpp
@@ -52,7 +52,7 @@
     sp<HalDisplay> halDisplay = new HalDisplay(mockHWDisplay);
 
     while (fdp.remaining_bytes() > kMaxFuzzerConsumedBytes) {
-        switch (fdp.ConsumeIntegralInRange<uint32_t>(0, EVS_FUZZ_API_SUM)) {
+        switch (fdp.ConsumeIntegralInRange<uint32_t>(0, EVS_FUZZ_API_SUM - 1)) {
             case EVS_FUZZ_GET_HW_DISPLAY: {
                 halDisplay->getHwDisplay();
                 break;
diff --git a/evs/manager/1.1/test/fuzzer/MockHWCamera.h b/evs/manager/1.1/test/fuzzer/MockHWCamera.h
index a4e0638..4be393d 100644
--- a/evs/manager/1.1/test/fuzzer/MockHWCamera.h
+++ b/evs/manager/1.1/test/fuzzer/MockHWCamera.h
@@ -58,8 +58,9 @@
                 (const hidl_string& deviceId, getPhysicalCameraInfo_cb _hidl_cb), (override));
     MOCK_METHOD(Return<EvsResult>, pauseVideoStream, (), (override));
     MOCK_METHOD(Return<EvsResult>, resumeVideoStream, (), (override));
-    MOCK_METHOD(Return<EvsResult>, doneWithFrame_1_1,
-                (const hardware::hidl_vec<BufferDesc_1_1>& buffer), (override));
+    Return<EvsResult> doneWithFrame_1_1(const hardware::hidl_vec<BufferDesc_1_1>& buffer) override {
+        return EvsResult::OK;
+    }
     MOCK_METHOD(Return<EvsResult>, setMaster, (), (override));
     MOCK_METHOD(Return<EvsResult>, forceMaster, (const sp<IEvsDisplay_1_0>& display), (override));
     MOCK_METHOD(Return<EvsResult>, unsetMaster, (), (override));
diff --git a/evs/manager/1.1/test/fuzzer/VirtualCameraFuzzer.cpp b/evs/manager/1.1/test/fuzzer/VirtualCameraFuzzer.cpp
index 3776f4b..ddff9c4 100644
--- a/evs/manager/1.1/test/fuzzer/VirtualCameraFuzzer.cpp
+++ b/evs/manager/1.1/test/fuzzer/VirtualCameraFuzzer.cpp
@@ -68,7 +68,7 @@
     bool videoStarted = false;
 
     while (fdp.remaining_bytes() > kMaxFuzzerConsumedBytes) {
-        switch (fdp.ConsumeIntegralInRange<uint32_t>(0, EVS_FUZZ_API_SUM)) {
+        switch (fdp.ConsumeIntegralInRange<uint32_t>(0, EVS_FUZZ_API_SUM - 1)) {
             case EVS_FUZZ_GET_ALLOWED_BUFFERS: {
                 virtualCamera->getAllowedBuffers();
                 break;