Added ndk_image_reader_fuzzer

Test: ./ndk_image_reader_fuzzer
Bug: 231667886

Change-Id: I0946242983c7b277df1332155f488ff6e7680949
(cherry picked from commit 5830d27abcb6ab1ec448fd85e7638f4e81d9d9f6)
diff --git a/media/ndk/fuzzer/Android.bp b/media/ndk/fuzzer/Android.bp
index 82d03e5..fee5705 100644
--- a/media/ndk/fuzzer/Android.bp
+++ b/media/ndk/fuzzer/Android.bp
@@ -55,3 +55,18 @@
     srcs: ["ndk_crypto_fuzzer.cpp"],
     defaults: ["libmediandk_fuzzer_defaults"],
 }
+
+cc_fuzz {
+     name: "ndk_image_reader_fuzzer",
+     srcs: [
+        "ndk_image_reader_fuzzer.cpp",
+     ],
+     shared_libs: [
+        "android.hidl.token@1.0-utils",
+        "android.hardware.graphics.bufferqueue@1.0",
+     ],
+     cflags: [
+        "-D__ANDROID_VNDK__",
+     ],
+     defaults: ["libmediandk_fuzzer_defaults"],
+}
diff --git a/media/ndk/fuzzer/README.md b/media/ndk/fuzzer/README.md
index 4f78e4a..21b9dc9 100644
--- a/media/ndk/fuzzer/README.md
+++ b/media/ndk/fuzzer/README.md
@@ -2,6 +2,7 @@
 
 ## Table of contents
 + [ndk_crypto_fuzzer](#NdkCrypto)
++ [ndk_image_reader_fuzzer](#NdkImageReader)
 
 # <a name="NdkCrypto"></a> Fuzzer for NdkCrypto
 
@@ -22,3 +23,31 @@
   $ adb sync data
   $ adb shell /data/fuzz/arm64/ndk_crypto_fuzzer/ndk_crypto_fuzzer
 ```
+
+# <a name="NdkImageReader"></a> Fuzzer for NdkImageReader
+
+NdkImageReader supports the following parameters:
+1. Width (parameter name: "imageWidth")
+2. Height (parameter name: "imageHeight")
+3. Format (parameter name: "imageFormat")
+4. Usage (parameter name: "imageUsage")
+5. Max images (parameter name: "imageMaxCount")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+| `width`| `1 to INT_MAX`| Value obtained from FuzzedDataProvider|
+| `height`| `1 to INT_MAX`| Value obtained from FuzzedDataProvider|
+| `format`| `1 to INT_MAX`| Value obtained from FuzzedDataProvider|
+| `usage`| `1 to INT_MAX`| Value obtained from FuzzedDataProvider|
+| `maxImages`| `1 to android::BufferQueue::MAX_MAX_ACQUIRED_BUFFERS`| Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) ndk_image_reader_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/ndk_image_reader_fuzzer/ndk_image_reader_fuzzer
+```
diff --git a/media/ndk/fuzzer/ndk_image_reader_fuzzer.cpp b/media/ndk/fuzzer/ndk_image_reader_fuzzer.cpp
new file mode 100644
index 0000000..6c11798
--- /dev/null
+++ b/media/ndk/fuzzer/ndk_image_reader_fuzzer.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 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 <cutils/native_handle.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <gui/BufferQueue.h>
+#include <media/NdkImageReader.h>
+
+constexpr int32_t kMaxSize = INT_MAX;
+constexpr int32_t kMinSize = 1;
+constexpr int32_t kMinImages = 1;
+
+class NdkImageReaderFuzzer {
+  public:
+    NdkImageReaderFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+    static void onImageAvailable(void*, AImageReader*){};
+    static void onBufferRemoved(void*, AImageReader*, AHardwareBuffer*){};
+};
+
+void NdkImageReaderFuzzer::process() {
+    AImageReader* reader = nullptr;
+    AImage* img = nullptr;
+    native_handle_t* handle = nullptr;
+    int32_t* acquireFenceFd = nullptr;
+    int32_t imageWidth = mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize);
+    int32_t imageHeight = mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize);
+    int32_t imageFormat = mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize);
+    int32_t imageUsage = mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize);
+    int32_t imageMaxCount = mFdp.ConsumeIntegralInRange<int32_t>(
+            kMinImages, android::BufferQueue::MAX_MAX_ACQUIRED_BUFFERS);
+    AImageReader_ImageListener readerAvailableCb{this, NdkImageReaderFuzzer::onImageAvailable};
+    AImageReader_BufferRemovedListener readerDetachedCb{this, onBufferRemoved};
+
+    if (mFdp.ConsumeBool()) {
+        AImageReader_new(imageWidth, imageHeight, imageFormat, imageMaxCount, &reader);
+    } else {
+        AImageReader_newWithUsage(imageWidth, imageHeight, imageFormat, imageUsage, imageMaxCount,
+                                  &reader);
+    }
+    while (mFdp.remaining_bytes()) {
+        auto ndkImageFunction = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() { AImageReader_acquireNextImage(reader, &img); },
+                [&]() { AImageReader_acquireLatestImage(reader, &img); },
+                [&]() { AImageReader_setImageListener(reader, &readerAvailableCb); },
+                [&]() { AImageReader_acquireNextImageAsync(reader, &img, acquireFenceFd); },
+                [&]() { AImageReader_acquireLatestImageAsync(reader, &img, acquireFenceFd); },
+                [&]() { AImageReader_setBufferRemovedListener(reader, &readerDetachedCb); },
+                [&]() { AImageReader_getWindowNativeHandle(reader, &handle); },
+        });
+        ndkImageFunction();
+    }
+    AImageReader_delete(reader);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    NdkImageReaderFuzzer ndkImageReaderFuzzer(data, size);
+    ndkImageReaderFuzzer.process();
+    return 0;
+}