Merge changes from topic "link libinput dynamically for tests"

* changes:
  Use C++20 in libinput
  Revert "Link libinput statically for inputflinger_tests"
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index 6704a1d..35f87f9 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -68,6 +68,8 @@
     ANDROID_BITMAP_FORMAT_A_8       = 8,
     /** Each component is stored as a half float. **/
     ANDROID_BITMAP_FORMAT_RGBA_F16  = 9,
+    /** Red: 10 bits, Green: 10 bits, Blue: 10 bits, Alpha: 2 bits. **/
+    ANDROID_BITMAP_FORMAT_RGBA_1010102 = 10,
 };
 
 /** Bitmap alpha format */
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 83e9858..06a0aca 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -546,7 +546,10 @@
 }
 
 TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) {
+    std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
     std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+    bgSurface->showAt(100, 100);
+
     // In case we pass the very big inset without any checking.
     fgSurface->mInputInfo.surfaceInset = INT32_MAX;
     fgSurface->showAt(100, 100);
@@ -554,8 +557,8 @@
     fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
 
     // expect no crash for overflow, and inset size to be clamped to surface size
-    injectTap(202, 202);
-    fgSurface->expectTap(1, 1);
+    injectTap(112, 124);
+    bgSurface->expectTap(12, 24);
 }
 
 // Ensure we ignore transparent region when getting screen bounds when positioning input frame.
@@ -987,6 +990,31 @@
     EXPECT_EQ(surface->consumeEvent(100), nullptr);
 }
 
+TEST_F(InputSurfacesTest, layer_with_empty_crop_cannot_be_focused) {
+    std::unique_ptr<InputSurface> bufferSurface =
+            InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
+
+    bufferSurface->showAt(50, 50, Rect::EMPTY_RECT);
+
+    bufferSurface->requestFocus();
+    EXPECT_EQ(bufferSurface->consumeEvent(100), nullptr);
+
+    bufferSurface->showAt(50, 50, Rect::INVALID_RECT);
+
+    bufferSurface->requestFocus();
+    EXPECT_EQ(bufferSurface->consumeEvent(100), nullptr);
+}
+
+TEST_F(InputSurfacesTest, layer_with_valid_crop_can_be_focused) {
+    std::unique_ptr<InputSurface> bufferSurface =
+            InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
+
+    bufferSurface->showAt(50, 50, Rect{0, 0, 100, 100});
+
+    bufferSurface->requestFocus();
+    bufferSurface->assertFocusChange(true);
+}
+
 /**
  * If a cropped layer's touchable region is replaced with a null crop, it should receive input in
  * its own crop.
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index 33ab7c4..cc96f83 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -132,9 +132,13 @@
         ALOGE("sync_file_info returned NULL for fd %d", mFenceFd.get());
         return SIGNAL_TIME_INVALID;
     }
+
     if (finfo->status != 1) {
+        const auto status = finfo->status;
+        ALOGE_IF(status < 0, "%s: sync_file_info contains an error: <%d> for fd: <%d>", __func__,
+                 status, mFenceFd.get());
         sync_file_info_free(finfo);
-        return SIGNAL_TIME_PENDING;
+        return status < 0 ? SIGNAL_TIME_INVALID : SIGNAL_TIME_PENDING;
     }
 
     uint64_t timestamp = 0;
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index 9922d6a..c97cc94 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -98,9 +98,6 @@
 static bool hasIAllocatorAidl() {
     // Avoid re-querying repeatedly for this information;
     static bool sHasIAllocatorAidl = []() -> bool {
-        // TODO: Enable after landing sepolicy changes
-        if constexpr ((true)) return false;
-
         if (__builtin_available(android 31, *)) {
             return AServiceManager_isDeclared(kAidlAllocatorServiceName.c_str());
         }
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 7a3d6c5..d1982fc 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -120,7 +120,8 @@
 
 // Amount of time to allow for an event to be dispatched (measured since its eventTime)
 // before considering it stale and dropping it.
-constexpr nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
+const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL // 10sec
+        * HwTimeoutMultiplier();
 
 // Log a warning when an event takes longer than this to process, even if an ANR does not occur.
 constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index 49cb912..08cfaa6 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -90,6 +90,10 @@
     // The dataspace for this layer
     ui::Dataspace dataspace{ui::Dataspace::UNKNOWN};
 
+    // A hint to the HWC that this region is transparent and may be skipped in
+    // order to save power.
+    Region outputSpaceBlockingRegionHint;
+
     // Overrides the buffer, acquire fence, and display frame stored in LayerFECompositionState
     struct {
         std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 162d84e..65f9731 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -50,6 +50,8 @@
 
 #include "TracedOrdinal.h"
 
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine {
 
 Output::~Output() = default;
@@ -529,11 +531,18 @@
 
     /*
      * transparentRegion: area of a surface that is hinted to be completely
-     * transparent. This is only used to tell when the layer has no visible non-
-     * transparent regions and can be removed from the layer list. It does not
-     * affect the visibleRegion of this layer or any layers beneath it. The hint
-     * may not be correct if apps don't respect the SurfaceView restrictions
-     * (which, sadly, some don't).
+     * transparent.
+     * This is used to tell when the layer has no visible non-transparent
+     * regions and can be removed from the layer list. It does not affect the
+     * visibleRegion of this layer or any layers beneath it. The hint may not
+     * be correct if apps don't respect the SurfaceView restrictions (which,
+     * sadly, some don't).
+     *
+     * In addition, it is used on DISPLAY_DECORATION layers to specify the
+     * blockingRegion, allowing the DPU to skip it to save power. Once we have
+     * hardware that supports a blockingRegion on frames with AFBC, it may be
+     * useful to use this for other layers, too, so long as we can prevent
+     * regressions on b/7179570.
      */
     Region transparentRegion;
 
@@ -674,6 +683,9 @@
     outputLayerState.outputSpaceVisibleRegion = outputState.transform.transform(
             visibleNonShadowRegion.intersect(outputState.layerStackSpace.getContent()));
     outputLayerState.shadowRegion = shadowRegion;
+    outputLayerState.outputSpaceBlockingRegionHint =
+            layerFEState->compositionType == Composition::DISPLAY_DECORATION ? transparentRegion
+                                                                             : Region();
 }
 
 void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 95cc5a8..4ccf11f 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -484,6 +484,14 @@
         visibleRegion.dump(LOG_TAG);
     }
 
+    if (auto error =
+                hwcLayer->setBlockingRegion(outputDependentState.outputSpaceBlockingRegionHint);
+        error != hal::Error::NONE) {
+        ALOGE("[%s] Failed to set blocking region: %s (%d)", getLayerFE().getDebugName(),
+              to_string(error).c_str(), static_cast<int32_t>(error));
+        outputDependentState.outputSpaceBlockingRegionHint.dump(LOG_TAG);
+    }
+
     const auto dataspace = outputDependentState.overrideInfo.buffer
             ? outputDependentState.overrideInfo.dataspace
             : outputDependentState.dataspace;
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 132ac02..0b123b1 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -846,7 +846,8 @@
                                    ui::Dataspace dataspace = kDataspace,
                                    const Region& visibleRegion = kOutputSpaceVisibleRegion,
                                    const Region& surfaceDamage = kSurfaceDamage,
-                                   float whitePointNits = kWhitePointNits) {
+                                   float whitePointNits = kWhitePointNits,
+                                   const Region& blockingRegion = Region()) {
         EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(visibleRegion))).WillOnce(Return(kError));
         EXPECT_CALL(*mHwcLayer, setDataspace(dataspace)).WillOnce(Return(kError));
         EXPECT_CALL(*mHwcLayer, setWhitePointNits(whitePointNits)).WillOnce(Return(kError));
@@ -855,6 +856,8 @@
                                          ? hal::Error::UNSUPPORTED
                                          : hal::Error::NONE));
         EXPECT_CALL(*mHwcLayer, setSurfaceDamage(RegionEq(surfaceDamage))).WillOnce(Return(kError));
+        EXPECT_CALL(*mHwcLayer, setBlockingRegion(RegionEq(blockingRegion)))
+                .WillOnce(Return(kError));
     }
 
     void expectSetCompositionTypeCall(Composition compositionType) {
@@ -1278,6 +1281,23 @@
     EXPECT_EQ(Composition::DEVICE, mOutputLayer.getState().hwc->hwcCompositionType);
 }
 
+TEST_F(OutputLayerWriteStateToHWCTest, setBlockingRegion) {
+    mLayerFEState.compositionType = Composition::DISPLAY_DECORATION;
+    const auto blockingRegion = Region(Rect(0, 0, 1000, 1000));
+    mOutputLayer.editState().outputSpaceBlockingRegionHint = blockingRegion;
+
+    expectGeometryCommonCalls();
+    expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
+                              kSurfaceDamage, kWhitePointNits, blockingRegion);
+    expectSetHdrMetadataAndBufferCalls();
+    EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
+    expectSetCompositionTypeCall(Composition::DISPLAY_DECORATION);
+
+    mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
+                                 /*zIsOverridden*/ false, /*isPeekingThrough*/
+                                 false);
+}
+
 /*
  * OutputLayer::writeCursorPositionToHWC()
  */
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 655db4b..f7d5991 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -1291,7 +1291,7 @@
         mLayer.layerFEState.contentDirty = true;
         mLayer.layerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
         mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
-        mLayer.layerFEState.transparentRegionHint = Region(Rect(0, 0, 100, 100));
+        mLayer.layerFEState.transparentRegionHint = kTransparentRegionHint;
 
         mLayer.outputLayerState.visibleRegion = Region(Rect(0, 0, 50, 200));
         mLayer.outputLayerState.coveredRegion = Region(Rect(50, 0, 100, 200));
@@ -1309,6 +1309,7 @@
     static const Region kRightHalfBoundsNoRotation;
     static const Region kLowerHalfBoundsNoRotation;
     static const Region kFullBounds90Rotation;
+    static const Region kTransparentRegionHint;
 
     StrictMock<OutputPartialMock> mOutput;
     LayerFESet mGeomSnapshots;
@@ -1326,6 +1327,8 @@
         Region(Rect(50, 0, 100, 200));
 const Region OutputEnsureOutputLayerIfVisibleTest::kFullBounds90Rotation =
         Region(Rect(0, 0, 200, 100));
+const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHint =
+        Region(Rect(0, 0, 100, 100));
 
 TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerIncluded) {
     EXPECT_CALL(mOutput, includesLayer(sp<LayerFE>(mLayer.layerFE))).WillOnce(Return(false));
@@ -1749,6 +1752,33 @@
     ensureOutputLayerIfVisible();
 }
 
+TEST_F(OutputEnsureOutputLayerIfVisibleTest, displayDecorSetsBlockingFromTransparentRegion) {
+    mLayer.layerFEState.isOpaque = false;
+    mLayer.layerFEState.contentDirty = true;
+    mLayer.layerFEState.compositionType =
+            aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION;
+
+    EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
+    EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer.layerFE)))
+            .WillOnce(Return(&mLayer.outputLayer));
+    ensureOutputLayerIfVisible();
+
+    EXPECT_THAT(mLayer.outputLayerState.outputSpaceBlockingRegionHint,
+                RegionEq(kTransparentRegionHint));
+}
+
+TEST_F(OutputEnsureOutputLayerIfVisibleTest, normalLayersDoNotSetBlockingRegion) {
+    mLayer.layerFEState.isOpaque = false;
+    mLayer.layerFEState.contentDirty = true;
+
+    EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
+    EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer.layerFE)))
+            .WillOnce(Return(&mLayer.outputLayer));
+    ensureOutputLayerIfVisible();
+
+    EXPECT_THAT(mLayer.outputLayerState.outputSpaceBlockingRegionHint, RegionEq(Region()));
+}
+
 /*
  * Output::present()
  */
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9fffd12..645d4d1 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2160,91 +2160,71 @@
     return getCroppedBufferSize(getDrawingState());
 }
 
-void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& displayTransform) {
-    Rect layerBounds = getInputBounds();
-    if (!layerBounds.isValid()) {
+void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& screenToDisplay) {
+    Rect tmpBounds = getInputBounds();
+    if (!tmpBounds.isValid()) {
         info.flags = WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::NOT_FOCUSABLE;
+        info.focusable = false;
         info.touchableRegion.clear();
         // A layer could have invalid input bounds and still expect to receive touch input if it has
         // replaceTouchableRegionWithCrop. For that case, the input transform needs to be calculated
         // correctly to determine the coordinate space for input events. Use an empty rect so that
         // the layer will receive input in its own layer space.
-        layerBounds = Rect::EMPTY_RECT;
+        tmpBounds = Rect::EMPTY_RECT;
     }
 
-    const ui::Transform layerTransform = getInputTransform();
-    // Transform that takes window coordinates to non-rotated display coordinates
-    ui::Transform t = displayTransform * layerTransform;
-    int32_t xSurfaceInset = info.surfaceInset;
-    int32_t ySurfaceInset = info.surfaceInset;
-    // Bring screenBounds into non-unrotated space
-    Rect screenBounds = displayTransform.transform(Rect{mScreenBounds});
+    // InputDispatcher works in the display device's coordinate space. Here, we calculate the
+    // frame and transform used for the layer, which determines the bounds and the coordinate space
+    // within which the layer will receive input.
+    //
+    // The coordinate space within which each of the bounds are specified is explicitly documented
+    // in the variable name. For example "inputBoundsInLayer" is specified in layer space. A
+    // Transform converts one coordinate space to another, which is apparent in its naming. For
+    // example, "layerToDisplay" transforms layer space to display space.
+    //
+    // Coordinate space definitions:
+    //   - display: The display device's coordinate space. Correlates to pixels on the display.
+    //   - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
+    //   - layer: The coordinate space of this layer.
+    //   - input: The coordinate space in which this layer will receive input events. This could be
+    //            different than layer space if a surfaceInset is used, which changes the origin
+    //            of the input space.
+    const FloatRect inputBoundsInLayer = tmpBounds.toFloatRect();
 
-    const float xScale = t.getScaleX();
-    const float yScale = t.getScaleY();
-    if (xScale != 1.0f || yScale != 1.0f) {
-        xSurfaceInset = std::round(xSurfaceInset * xScale);
-        ySurfaceInset = std::round(ySurfaceInset * yScale);
-    }
+    // Clamp surface inset to the input bounds.
+    const auto surfaceInset = static_cast<float>(info.surfaceInset);
+    const float xSurfaceInset =
+            std::max(0.f, std::min(surfaceInset, inputBoundsInLayer.getWidth() / 2.f));
+    const float ySurfaceInset =
+            std::max(0.f, std::min(surfaceInset, inputBoundsInLayer.getHeight() / 2.f));
 
-    // Transform the layer bounds from layer coordinate space to display coordinate space.
-    Rect transformedLayerBounds = t.transform(layerBounds);
+    // Apply the insets to the input bounds.
+    const FloatRect insetBoundsInLayer(inputBoundsInLayer.left + xSurfaceInset,
+                                       inputBoundsInLayer.top + ySurfaceInset,
+                                       inputBoundsInLayer.right - xSurfaceInset,
+                                       inputBoundsInLayer.bottom - ySurfaceInset);
 
-    // clamp inset to layer bounds
-    xSurfaceInset = (xSurfaceInset >= 0)
-            ? std::min(xSurfaceInset, transformedLayerBounds.getWidth() / 2)
-            : 0;
-    ySurfaceInset = (ySurfaceInset >= 0)
-            ? std::min(ySurfaceInset, transformedLayerBounds.getHeight() / 2)
-            : 0;
+    // Crop the input bounds to ensure it is within the parent's bounds.
+    const FloatRect croppedInsetBoundsInLayer = mBounds.intersect(insetBoundsInLayer);
 
-    // inset while protecting from overflow TODO(b/161235021): What is going wrong
-    // in the overflow scenario?
-    {
-    int32_t tmp;
-    if (!__builtin_add_overflow(transformedLayerBounds.left, xSurfaceInset, &tmp))
-        transformedLayerBounds.left = tmp;
-    if (!__builtin_sub_overflow(transformedLayerBounds.right, xSurfaceInset, &tmp))
-        transformedLayerBounds.right = tmp;
-    if (!__builtin_add_overflow(transformedLayerBounds.top, ySurfaceInset, &tmp))
-        transformedLayerBounds.top = tmp;
-    if (!__builtin_sub_overflow(transformedLayerBounds.bottom, ySurfaceInset, &tmp))
-        transformedLayerBounds.bottom = tmp;
-    }
+    const ui::Transform layerToScreen = getInputTransform();
+    const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
 
-    // Compute the correct transform to send to input. This will allow it to transform the
-    // input coordinates from display space into window space. Therefore, it needs to use the
-    // final layer frame to create the inverse transform. Since surface insets are added later,
-    // along with the overflow, the best way to ensure we get the correct transform is to use
-    // the final frame calculated.
-    // 1. Take the original transform set on the window and get the inverse transform. This is
-    //    used to get the final bounds in display space (ignorning the transform). Apply the
-    //    inverse transform on the layerBounds to get the untransformed frame (in layer space)
-    // 2. Take the top and left of the untransformed frame to get the real position on screen.
-    //    Apply the layer transform on top/left so it includes any scale or rotation. These will
-    //    be the new translation values for the transform.
-    // 3. Update the translation of the original transform to the new translation values.
-    // 4. Send the inverse transform to input so the coordinates can be transformed back into
-    //    window space.
-    ui::Transform inverseTransform = t.inverse();
-    Rect nonTransformedBounds = inverseTransform.transform(transformedLayerBounds);
-    vec2 translation = t.transform(nonTransformedBounds.left, nonTransformedBounds.top);
-    ui::Transform inputTransform(t);
-    inputTransform.set(translation.x, translation.y);
-    info.transform = inputTransform.inverse();
+    const Rect roundedFrameInDisplay{layerToDisplay.transform(croppedInsetBoundsInLayer)};
+    info.frameLeft = roundedFrameInDisplay.left;
+    info.frameTop = roundedFrameInDisplay.top;
+    info.frameRight = roundedFrameInDisplay.right;
+    info.frameBottom = roundedFrameInDisplay.bottom;
 
-    // We need to send the layer bounds cropped to the screenbounds since the layer can be cropped.
-    // The frame should be the area the user sees on screen since it's used for occlusion
-    // detection.
-    transformedLayerBounds.intersect(screenBounds, &transformedLayerBounds);
-    info.frameLeft = transformedLayerBounds.left;
-    info.frameTop = transformedLayerBounds.top;
-    info.frameRight = transformedLayerBounds.right;
-    info.frameBottom = transformedLayerBounds.bottom;
+    ui::Transform inputToLayer;
+    inputToLayer.set(insetBoundsInLayer.left, insetBoundsInLayer.top);
+    const ui::Transform inputToDisplay = layerToDisplay * inputToLayer;
 
-    // Position the touchable region relative to frame screen location and restrict it to frame
-    // bounds.
-    info.touchableRegion = inputTransform.transform(info.touchableRegion);
+    // InputDispatcher expects a display-to-input transform.
+    info.transform = inputToDisplay.inverse();
+
+    // The touchable region is specified in the input coordinate space. Change it to display space.
+    info.touchableRegion = inputToDisplay.transform(info.touchableRegion);
 }
 
 void Layer::fillTouchOcclusionMode(WindowInfo& info) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 40fb946..605a27e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1093,7 +1093,7 @@
     void fillTouchOcclusionMode(gui::WindowInfo& info);
 
     // Fills in the frame and transform info for the gui::WindowInfo.
-    void fillInputFrameInfo(gui::WindowInfo&, const ui::Transform& displayTransform);
+    void fillInputFrameInfo(gui::WindowInfo&, const ui::Transform& screenToDisplay);
 
     // Cached properties computed from drawing state
     // Effective transform taking into account parent transforms and any parent scaling, which is
diff --git a/services/surfaceflinger/fuzzer/Android.bp b/services/surfaceflinger/fuzzer/Android.bp
index 7eebd9b..0ead163 100644
--- a/services/surfaceflinger/fuzzer/Android.bp
+++ b/services/surfaceflinger/fuzzer/Android.bp
@@ -78,3 +78,17 @@
         "surfaceflinger_fuzzer.cpp",
     ],
 }
+
+cc_fuzz {
+    name: "surfaceflinger_displayhardware_fuzzer",
+    defaults: [
+        "surfaceflinger_fuzz_defaults",
+    ],
+    srcs: [
+        "surfaceflinger_displayhardware_fuzzer.cpp",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.4-command-buffer",
+        "android.hardware.graphics.composer@2.4-hal",
+    ],
+}
diff --git a/services/surfaceflinger/fuzzer/README.md b/services/surfaceflinger/fuzzer/README.md
index 7b244fc..4ecf770 100644
--- a/services/surfaceflinger/fuzzer/README.md
+++ b/services/surfaceflinger/fuzzer/README.md
@@ -1,6 +1,7 @@
 # Fuzzers for SurfaceFlinger
 ## Table of contents
 + [SurfaceFlinger](#SurfaceFlinger)
++ [DisplayHardware](#DisplayHardware)
 
 # <a name="SurfaceFlinger"></a> Fuzzer for SurfaceFlinger
 
@@ -22,3 +23,31 @@
   $ adb sync data
   $ adb shell /data/fuzz/arm64/surfaceflinger_fuzzer/surfaceflinger_fuzzer
 ```
+
+# <a name="DisplayHardware"></a> Fuzzer for DisplayHardware
+
+DisplayHardware supports the following parameters:
+1. Hal Capability (parameter name: `hasCapability`)
+2. Hal BlendMode (parameter name: `setBlendMode`)
+3. Hal Composition (parameter name: `setCompositionType`)
+4. Hal Display Capability (parameter name: `hasDisplayCapability`)
+5. Composition Types (parameter name: `prepareFrame`)
+6. Color Modes (parameter name: `setActiveColorMode`)
+7. Render Intents (parameter name: `setActiveColorMode`)
+8. Power Modes (parameter name: `setPowerMode`)
+9. Content Types (parameter name: `setContentType`)
+10. Data Space (parameter name: `setDataspace`)
+11. Transforms (parameter name: `setLayerTransform`)
+
+You can find the possible values in the fuzzer's source code.
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) surfaceflinger_displayhardware_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/surfaceflinger_displayhardware_fuzzer/surfaceflinger_displayhardware_fuzzer
+```
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp
new file mode 100644
index 0000000..816d2f1
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2021 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 <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <compositionengine/impl/OutputCompositionState.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <gui/BLASTBufferQueue.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/SurfaceComposerClient.h>
+#include <hidl/ServiceManagement.h>
+#include <hwbinder/ProcessState.h>
+#include <ui/DisplayIdentification.h>
+
+#include "DisplayHardware/AidlComposerHal.h"
+#include "DisplayHardware/DisplayMode.h"
+#include "DisplayHardware/FramebufferSurface.h"
+#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/PowerAdvisor.h"
+#include "DisplayHardware/VirtualDisplaySurface.h"
+#include "SurfaceFlinger.h"
+#include "surfaceflinger_displayhardware_fuzzer_utils.h"
+
+#include <FuzzableDataspaces.h>
+
+namespace android::fuzz {
+
+using namespace android::hardware::graphics::common;
+using namespace android::hardware::graphics::composer;
+namespace hal = android::hardware::graphics::composer::hal;
+using Config = hal::V2_1::Config;
+using Display = hal::V2_1::Display;
+using RenderIntent = V1_1::RenderIntent;
+using IComposerClient = hal::V2_4::IComposerClient;
+using VsyncPeriodChangeTimeline = hal::V2_4::VsyncPeriodChangeTimeline;
+using PerFrameMetadata = IComposerClient::PerFrameMetadata;
+using PerFrameMetadataBlob = IComposerClient::PerFrameMetadataBlob;
+using Vsync = IComposerClient::Vsync;
+
+static constexpr hal::Transform kTransforms[] = {hal::Transform::FLIP_H, hal::Transform::FLIP_V,
+                                                 hal::Transform::ROT_90, hal::Transform::ROT_180,
+                                                 hal::Transform::ROT_270};
+
+static constexpr hal::Capability kCapability[] = {hal::Capability::INVALID,
+                                                  hal::Capability::SIDEBAND_STREAM,
+                                                  hal::Capability::SKIP_CLIENT_COLOR_TRANSFORM,
+                                                  hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE};
+
+static constexpr hal::BlendMode kBlendModes[] = {hal::BlendMode::INVALID, hal::BlendMode::NONE,
+                                                 hal::BlendMode::PREMULTIPLIED,
+                                                 hal::BlendMode::COVERAGE};
+
+static constexpr Composition kCompositions[] = {Composition::INVALID, Composition::CLIENT,
+                                                Composition::DEVICE,  Composition::SOLID_COLOR,
+                                                Composition::CURSOR,  Composition::SIDEBAND};
+
+static constexpr DisplayCapability kDisplayCapability[] =
+        {DisplayCapability::INVALID,
+         DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM,
+         DisplayCapability::DOZE,
+         DisplayCapability::BRIGHTNESS,
+         DisplayCapability::PROTECTED_CONTENTS,
+         DisplayCapability::AUTO_LOW_LATENCY_MODE};
+
+static constexpr VirtualDisplaySurface::CompositionType kCompositionTypes[] =
+        {VirtualDisplaySurface::CompositionType::Unknown,
+         VirtualDisplaySurface::CompositionType::Gpu, VirtualDisplaySurface::CompositionType::Hwc,
+         VirtualDisplaySurface::CompositionType::Mixed};
+
+static constexpr ui::RenderIntent kRenderIntents[] = {ui::RenderIntent::COLORIMETRIC,
+                                                      ui::RenderIntent::ENHANCE,
+                                                      ui::RenderIntent::TONE_MAP_COLORIMETRIC,
+                                                      ui::RenderIntent::TONE_MAP_ENHANCE};
+
+static constexpr hal::PowerMode kPowerModes[] = {hal::PowerMode::OFF, hal::PowerMode::DOZE,
+                                                 hal::PowerMode::DOZE_SUSPEND, hal::PowerMode::ON,
+                                                 hal::PowerMode::ON_SUSPEND};
+
+static constexpr hal::ContentType kContentTypes[] = {hal::ContentType::NONE,
+                                                     hal::ContentType::GRAPHICS,
+                                                     hal::ContentType::PHOTO,
+                                                     hal::ContentType::CINEMA,
+                                                     hal::ContentType::GAME};
+
+const unsigned char kInternalEdid[] =
+        "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00"
+        "\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27"
+        "\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+        "\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30"
+        "\x13\x00\x05\xa3\x10\x00\x00\x19\x00\x00\x00\x0f\x00\x00\x00\x00"
+        "\x00\x00\x00\x00\x00\x23\x87\x02\x64\x00\x00\x00\x00\xfe\x00\x53"
+        "\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x00\x00\x00\xfe"
+        "\x00\x31\x32\x31\x41\x54\x31\x31\x2d\x38\x30\x31\x0a\x20\x00\x45";
+
+static constexpr hal::HWConfigId kActiveConfig = 0;
+
+class DisplayHardwareFuzzer {
+public:
+    DisplayHardwareFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+        mPhysicalDisplayId = SurfaceComposerClient::getInternalDisplayId().value();
+    };
+    void process();
+
+private:
+    void invokeComposer();
+    void invokeDisplayIdentification();
+    void invokeLayer(HWC2::Layer* layer);
+    void setSidebandStream(HWC2::Layer* layer);
+    void setCursorPosition(HWC2::Layer* layer);
+    void setBuffer(HWC2::Layer* layer);
+    void setSurfaceDamage(HWC2::Layer* layer);
+    void setDisplayFrame(HWC2::Layer* layer);
+    void setVisibleRegion(HWC2::Layer* layer);
+    void setLayerGenericMetadata(HWC2::Layer* layer);
+    void invokeFrameBufferSurface();
+    void invokeVirtualDisplaySurface();
+    void invokeAidlComposer();
+    Display createVirtualDisplay(Hwc2::AidlComposer*);
+    void validateDisplay(Hwc2::AidlComposer*, Display);
+    void presentOrValidateDisplay(Hwc2::AidlComposer*, Display);
+    void setOutputBuffer(Hwc2::AidlComposer*, Display);
+    void setLayerSidebandStream(Hwc2::AidlComposer*, Display, Hwc2::V2_4::hal::Layer);
+    void invokeComposerHal2_2(Hwc2::AidlComposer*, Display, Hwc2::V2_4::hal::Layer);
+    void invokeComposerHal2_3(Hwc2::AidlComposer*, Display, Hwc2::V2_4::hal::Layer);
+    void invokeComposerHal2_4(Hwc2::AidlComposer*, Display, Hwc2::V2_4::hal::Layer);
+    void getDisplayVsyncPeriod();
+    void setActiveModeWithConstraints();
+    void getDisplayIdentificationData();
+    void dumpHwc();
+    void getDisplayedContentSamplingAttributes(HalDisplayId);
+    void getDeviceCompositionChanges(HalDisplayId);
+    void getHdrCapabilities(HalDisplayId);
+    void getDisplayedContentSample(HalDisplayId);
+    void getSupportedContentTypes();
+    ui::Size getFuzzedSize();
+    mat4 getFuzzedMatrix();
+
+    DisplayIdGenerator<HalVirtualDisplayId> mGenerator;
+    FuzzedDataProvider mFdp;
+    PhysicalDisplayId mPhysicalDisplayId;
+    android::impl::HWComposer mHwc{std::make_unique<Hwc2::mock::Composer>()};
+};
+
+void DisplayHardwareFuzzer::validateDisplay(Hwc2::AidlComposer* composer, Display display) {
+    uint32_t outNumTypes, outNumRequests;
+    composer->validateDisplay(display, mFdp.ConsumeIntegral<nsecs_t>(), &outNumTypes,
+                              &outNumRequests);
+}
+
+void DisplayHardwareFuzzer::presentOrValidateDisplay(Hwc2::AidlComposer* composer,
+                                                     Display display) {
+    int32_t outPresentFence;
+    uint32_t outNumTypes, outNumRequests, state;
+    composer->presentOrValidateDisplay(display, mFdp.ConsumeIntegral<nsecs_t>(), &outNumTypes,
+                                       &outNumRequests, &outPresentFence, &state);
+}
+
+void DisplayHardwareFuzzer::setOutputBuffer(Hwc2::AidlComposer* composer, Display display) {
+    const native_handle_t buffer{};
+    composer->setOutputBuffer(display, &buffer, mFdp.ConsumeIntegral<int32_t>() /*releaseFence*/);
+}
+
+void DisplayHardwareFuzzer::setLayerSidebandStream(Hwc2::AidlComposer* composer, Display display,
+                                                   Hwc2::V2_4::hal::Layer outLayer) {
+    const native_handle_t stream{};
+    composer->setLayerSidebandStream(display, outLayer, &stream);
+}
+
+Display DisplayHardwareFuzzer::createVirtualDisplay(Hwc2::AidlComposer* composer) {
+    namespace types = hardware::graphics::common;
+    using types::V1_2::PixelFormat;
+    PixelFormat format{};
+    Display display;
+    composer->createVirtualDisplay(mFdp.ConsumeIntegral<uint32_t>() /*width*/,
+                                   mFdp.ConsumeIntegral<uint32_t>() /*height*/, &format, &display);
+    return display;
+}
+
+void DisplayHardwareFuzzer::getDisplayVsyncPeriod() {
+    nsecs_t outVsyncPeriod;
+    mHwc.getDisplayVsyncPeriod(mPhysicalDisplayId, &outVsyncPeriod);
+}
+
+void DisplayHardwareFuzzer::setActiveModeWithConstraints() {
+    hal::VsyncPeriodChangeTimeline outTimeline;
+    mHwc.setActiveModeWithConstraints(mPhysicalDisplayId, kActiveConfig, {} /*constraints*/,
+                                      &outTimeline);
+}
+
+void DisplayHardwareFuzzer::getDisplayIdentificationData() {
+    uint8_t outPort;
+    DisplayIdentificationData outData;
+    mHwc.getDisplayIdentificationData(kHwDisplayId, &outPort, &outData);
+}
+
+void DisplayHardwareFuzzer::dumpHwc() {
+    std::string string = mFdp.ConsumeRandomLengthString().c_str();
+    mHwc.dump(string);
+}
+
+void DisplayHardwareFuzzer::getDeviceCompositionChanges(HalDisplayId halDisplayID) {
+    std::optional<impl::HWComposer::DeviceRequestedChanges> outChanges;
+    mHwc.getDeviceCompositionChanges(halDisplayID,
+                                     mFdp.ConsumeBool() /*frameUsesClientComposition*/,
+                                     std::chrono::steady_clock::now(), FenceTime::NO_FENCE,
+                                     mFdp.ConsumeIntegral<nsecs_t>(), &outChanges);
+}
+
+void DisplayHardwareFuzzer::getDisplayedContentSamplingAttributes(HalDisplayId halDisplayID) {
+    uint8_t outComponentMask;
+    ui::Dataspace dataSpace;
+    ui::PixelFormat pixelFormat;
+    mHwc.getDisplayedContentSamplingAttributes(halDisplayID, &pixelFormat, &dataSpace,
+                                               &outComponentMask);
+}
+
+void DisplayHardwareFuzzer::getHdrCapabilities(HalDisplayId halDisplayID) {
+    HdrCapabilities outCapabilities;
+    mHwc.getHdrCapabilities(halDisplayID, &outCapabilities);
+}
+
+void DisplayHardwareFuzzer::getDisplayedContentSample(HalDisplayId halDisplayID) {
+    DisplayedFrameStats outStats;
+    mHwc.getDisplayedContentSample(halDisplayID, mFdp.ConsumeIntegral<uint64_t>() /* maxFrames*/,
+                                   mFdp.ConsumeIntegral<uint64_t>() /*timestamps*/, &outStats);
+}
+
+void DisplayHardwareFuzzer::getSupportedContentTypes() {
+    std::vector<hal::ContentType> contentType{};
+    mHwc.getSupportedContentTypes(mPhysicalDisplayId, &contentType);
+}
+
+void DisplayHardwareFuzzer::invokeAidlComposer() {
+    hardware::ProcessState::self()->startThreadPool();
+    ProcessState::self()->startThreadPool();
+
+    if (!Hwc2::AidlComposer::isDeclared("default")) {
+        return;
+    }
+
+    Hwc2::AidlComposer composer("default");
+
+    android::hardware::graphics::composer::hal::TestHWC2ComposerCallback composerCallback{};
+    composer.registerCallback(composerCallback);
+
+    Display display = createVirtualDisplay(&composer);
+
+    composer.acceptDisplayChanges(display);
+
+    Hwc2::V2_4::hal::Layer outLayer;
+    composer.createLayer(display, &outLayer);
+
+    int32_t outPresentFence;
+    composer.presentDisplay(display, &outPresentFence);
+
+    composer.setActiveConfig(display, Config{});
+
+    composer.setClientTarget(display, mFdp.ConsumeIntegral<uint32_t>(), sp<GraphicBuffer>(),
+                             mFdp.ConsumeIntegral<int32_t>(), mFdp.PickValueInArray(kDataspaces),
+                             {});
+
+    composer.setColorMode(display, mFdp.PickValueInArray(kColormodes),
+                          mFdp.PickValueInArray(kRenderIntents));
+
+    setOutputBuffer(&composer, display);
+
+    composer.setPowerMode(display, mFdp.PickValueInArray(kPowerModes));
+    composer.setVsyncEnabled(display, mFdp.ConsumeBool() ? Vsync::ENABLE : Vsync::DISABLE);
+
+    composer.setClientTargetSlotCount(display);
+
+    validateDisplay(&composer, display);
+
+    presentOrValidateDisplay(&composer, display);
+
+    composer.setCursorPosition(display, outLayer, mFdp.ConsumeIntegral<uint8_t>() /*x*/,
+                               mFdp.ConsumeIntegral<uint8_t>() /*y*/);
+
+    composer.setLayerBuffer(display, outLayer, mFdp.ConsumeIntegral<uint32_t>() /*slot*/,
+                            sp<GraphicBuffer>(), mFdp.ConsumeIntegral<int32_t>() /*acquireFence*/);
+
+    composer.setLayerSurfaceDamage(display, outLayer, {} /*damage*/);
+
+    composer.setLayerBlendMode(display, outLayer, mFdp.PickValueInArray(kBlendModes));
+
+    composer.setLayerColor(display, outLayer,
+                           {mFdp.ConsumeFloatingPoint<float>() /*red*/,
+                            mFdp.ConsumeFloatingPoint<float>() /*green*/,
+                            mFdp.ConsumeFloatingPoint<float>() /*blue*/,
+                            mFdp.ConsumeFloatingPoint<float>() /*alpha*/});
+    composer.setLayerCompositionType(display, outLayer, mFdp.PickValueInArray(kCompositions));
+    composer.setLayerDataspace(display, outLayer, mFdp.PickValueInArray(kDataspaces));
+    composer.setLayerDisplayFrame(display, outLayer, {} /*frame*/);
+    composer.setLayerPlaneAlpha(display, outLayer, mFdp.ConsumeFloatingPoint<float>());
+
+    setLayerSidebandStream(&composer, display, outLayer);
+
+    composer.setLayerSourceCrop(display, outLayer, {} /*crop*/);
+
+    composer.setLayerTransform(display, outLayer, mFdp.PickValueInArray(kTransforms));
+
+    composer.setLayerVisibleRegion(display, outLayer, std::vector<IComposerClient::Rect>{});
+    composer.setLayerZOrder(display, outLayer, mFdp.ConsumeIntegral<uint32_t>());
+
+    invokeComposerHal2_2(&composer, display, outLayer);
+    invokeComposerHal2_3(&composer, display, outLayer);
+    invokeComposerHal2_4(&composer, display, outLayer);
+
+    composer.executeCommands();
+    composer.resetCommands();
+
+    composer.destroyLayer(display, outLayer);
+    composer.destroyVirtualDisplay(display);
+}
+
+void DisplayHardwareFuzzer::invokeComposerHal2_2(Hwc2::AidlComposer* composer, Display display,
+                                                 Hwc2::V2_4::hal::Layer outLayer) {
+    const std::vector<PerFrameMetadata> perFrameMetadatas;
+    composer->setLayerPerFrameMetadata(display, outLayer, perFrameMetadatas);
+
+    composer->getPerFrameMetadataKeys(display);
+    std::vector<RenderIntent> outRenderIntents;
+
+    composer->getRenderIntents(display, mFdp.PickValueInArray(kColormodes), &outRenderIntents);
+    mat4 outMatrix;
+    composer->getDataspaceSaturationMatrix(mFdp.PickValueInArray(kDataspaces), &outMatrix);
+}
+
+void DisplayHardwareFuzzer::invokeComposerHal2_3(Hwc2::AidlComposer* composer, Display display,
+                                                 Hwc2::V2_4::hal::Layer outLayer) {
+    composer->setDisplayContentSamplingEnabled(display, mFdp.ConsumeBool() /*enabled*/,
+                                               mFdp.ConsumeIntegral<uint8_t>() /*componentMask*/,
+                                               mFdp.ConsumeIntegral<uint64_t>() /*maxFrames*/);
+
+    DisplayedFrameStats outStats;
+    composer->getDisplayedContentSample(display, mFdp.ConsumeIntegral<uint64_t>() /*maxFrames*/,
+                                        mFdp.ConsumeIntegral<uint64_t>() /*timestamp*/, &outStats);
+
+    composer->setLayerPerFrameMetadataBlobs(display, outLayer, std::vector<PerFrameMetadataBlob>{});
+
+    composer->setDisplayBrightness(display, mFdp.ConsumeFloatingPoint<float>(),
+                                   Hwc2::Composer::DisplayBrightnessOptions{
+                                           .applyImmediately = mFdp.ConsumeIntegral<bool>()});
+}
+
+void DisplayHardwareFuzzer::invokeComposerHal2_4(Hwc2::AidlComposer* composer, Display display,
+                                                 Hwc2::V2_4::hal::Layer outLayer) {
+    VsyncPeriodChangeTimeline outTimeline;
+    composer->setActiveConfigWithConstraints(display, Config{},
+                                             IComposerClient::VsyncPeriodChangeConstraints{},
+                                             &outTimeline);
+
+    composer->setAutoLowLatencyMode(display, mFdp.ConsumeBool());
+
+    composer->setContentType(display, mFdp.PickValueInArray(kContentTypes));
+
+    std::vector<uint8_t> value;
+    value.push_back(mFdp.ConsumeIntegral<uint8_t>());
+    composer->setLayerGenericMetadata(display, outLayer, mFdp.ConsumeRandomLengthString() /*key*/,
+                                      mFdp.ConsumeBool() /*mandatory*/, value);
+}
+
+ui::Size DisplayHardwareFuzzer::getFuzzedSize() {
+    ui::Size size{mFdp.ConsumeIntegral<int32_t>() /*width*/,
+                  mFdp.ConsumeIntegral<int32_t>() /*height*/};
+    return size;
+}
+
+mat4 DisplayHardwareFuzzer::getFuzzedMatrix() {
+    mat4 matrix{mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(),
+                mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(),
+                mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(),
+                mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(),
+                mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(),
+                mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(),
+                mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>(),
+                mFdp.ConsumeFloatingPoint<float>(), mFdp.ConsumeFloatingPoint<float>()};
+    return matrix;
+}
+
+void DisplayHardwareFuzzer::setCursorPosition(HWC2::Layer* layer) {
+    layer->setCursorPosition(mFdp.ConsumeIntegral<int32_t>() /*x*/,
+                             mFdp.ConsumeIntegral<int32_t>() /*y*/);
+}
+
+void DisplayHardwareFuzzer::setBuffer(HWC2::Layer* layer) {
+    layer->setBuffer(mFdp.ConsumeIntegral<uint32_t>() /*slot*/, sp<GraphicBuffer>(),
+                     sp<Fence>::make());
+}
+
+void DisplayHardwareFuzzer::setSurfaceDamage(HWC2::Layer* layer) {
+    Rect rhs{mFdp.ConsumeIntegral<uint32_t>() /*width*/,
+             mFdp.ConsumeIntegral<uint32_t>() /*height*/};
+    const Region damage{rhs};
+    layer->setSurfaceDamage(damage);
+}
+
+void DisplayHardwareFuzzer::setVisibleRegion(HWC2::Layer* layer) {
+    uint32_t width = mFdp.ConsumeIntegral<uint32_t>();
+    uint32_t height = mFdp.ConsumeIntegral<uint32_t>();
+    Rect rect{width, height};
+    const Region region{rect};
+    layer->setVisibleRegion(region);
+}
+
+void DisplayHardwareFuzzer::setDisplayFrame(HWC2::Layer* layer) {
+    uint32_t width = mFdp.ConsumeIntegral<uint32_t>();
+    uint32_t height = mFdp.ConsumeIntegral<uint32_t>();
+    const Rect frame{width, height};
+    layer->setDisplayFrame(frame);
+}
+
+void DisplayHardwareFuzzer::setLayerGenericMetadata(HWC2::Layer* layer) {
+    std::vector<uint8_t> value;
+    value.push_back(mFdp.ConsumeIntegral<uint8_t>());
+    layer->setLayerGenericMetadata(mFdp.ConsumeRandomLengthString().c_str() /*name*/,
+                                   mFdp.ConsumeBool() /*mandatory*/, value);
+}
+
+void DisplayHardwareFuzzer::setSidebandStream(HWC2::Layer* layer) {
+    const native_handle_t stream{};
+    layer->setSidebandStream(&stream);
+}
+
+void DisplayHardwareFuzzer::invokeLayer(HWC2::Layer* layer) {
+    setCursorPosition(layer);
+    setBuffer(layer);
+    setSurfaceDamage(layer);
+
+    layer->setBlendMode(mFdp.PickValueInArray(kBlendModes));
+    layer->setColor({mFdp.ConsumeFloatingPoint<float>() /*red*/,
+                     mFdp.ConsumeFloatingPoint<float>() /*green*/,
+                     mFdp.ConsumeFloatingPoint<float>() /*blue*/,
+                     mFdp.ConsumeFloatingPoint<float>() /*alpha*/});
+    layer->setCompositionType(mFdp.PickValueInArray(kCompositions));
+    layer->setDataspace(mFdp.PickValueInArray(kDataspaces));
+
+    layer->setPerFrameMetadata(mFdp.ConsumeIntegral<int32_t>(), getFuzzedHdrMetadata(&mFdp));
+    setDisplayFrame(layer);
+
+    layer->setPlaneAlpha(mFdp.ConsumeFloatingPoint<float>());
+
+    setSidebandStream(layer);
+
+    layer->setSourceCrop(getFuzzedFloatRect(&mFdp));
+    layer->setTransform(mFdp.PickValueInArray(kTransforms));
+
+    setVisibleRegion(layer);
+
+    layer->setZOrder(mFdp.ConsumeIntegral<uint32_t>());
+
+    layer->setColorTransform(getFuzzedMatrix());
+
+    setLayerGenericMetadata(layer);
+}
+
+void DisplayHardwareFuzzer::invokeFrameBufferSurface() {
+    sp<IGraphicBufferProducer> bqProducer = sp<mock::GraphicBufferProducer>::make();
+    sp<IGraphicBufferConsumer> bqConsumer;
+    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
+
+    sp<FramebufferSurface> surface =
+            new FramebufferSurface(mHwc, mPhysicalDisplayId, bqConsumer, getFuzzedSize() /*size*/,
+                                   getFuzzedSize() /*maxSize*/);
+    surface->beginFrame(mFdp.ConsumeBool());
+
+    surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes));
+    surface->advanceFrame();
+    surface->onFrameCommitted();
+    String8 result = String8(mFdp.ConsumeRandomLengthString().c_str());
+    surface->dumpAsString(result);
+    surface->resizeBuffers(getFuzzedSize());
+    surface->getClientTargetAcquireFence();
+}
+
+void DisplayHardwareFuzzer::invokeVirtualDisplaySurface() {
+    DisplayIdGenerator<HalVirtualDisplayId> mGenerator;
+    VirtualDisplayId VirtualDisplayId = mGenerator.generateId().value();
+
+    sp<SurfaceComposerClient> mClient = new SurfaceComposerClient();
+    sp<SurfaceControl> mSurfaceControl =
+            mClient->createSurface(String8("TestSurface"), 100, 100, PIXEL_FORMAT_RGBA_8888,
+                                   ISurfaceComposerClient::eFXSurfaceBufferState,
+                                   /*parent*/ nullptr);
+
+    sp<BLASTBufferQueue> mBlastBufferQueueAdapter =
+            new BLASTBufferQueue("TestBLASTBufferQueue", mSurfaceControl, 100, 100,
+                                 PIXEL_FORMAT_RGBA_8888);
+
+    sp<IGraphicBufferProducer> sink = mBlastBufferQueueAdapter->getIGraphicBufferProducer();
+    sp<IGraphicBufferProducer> bqProducer = mBlastBufferQueueAdapter->getIGraphicBufferProducer();
+    sp<IGraphicBufferConsumer> bqConsumer;
+    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
+    BufferQueue::createBufferQueue(&sink, &bqConsumer);
+
+    sp<VirtualDisplaySurface> surface =
+            new VirtualDisplaySurface(mHwc, VirtualDisplayId, sink, bqProducer, bqConsumer,
+                                      mFdp.ConsumeRandomLengthString().c_str() /*name*/);
+
+    surface->beginFrame(mFdp.ConsumeBool());
+    surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes));
+    surface->resizeBuffers(getFuzzedSize());
+    surface->getClientTargetAcquireFence();
+    surface->advanceFrame();
+    surface->onFrameCommitted();
+    String8 result = String8(mFdp.ConsumeRandomLengthString().c_str());
+    surface->dumpAsString(result);
+}
+
+void DisplayHardwareFuzzer::invokeComposer() {
+    HalVirtualDisplayId halVirtualDisplayId = mGenerator.generateId().value();
+    HalDisplayId halDisplayID = HalDisplayId{halVirtualDisplayId};
+
+    android::hardware::graphics::composer::hal::TestHWC2ComposerCallback composerCallback{};
+    mHwc.setCallback(composerCallback);
+
+    ui::PixelFormat pixelFormat{};
+    if (!mHwc.allocateVirtualDisplay(halVirtualDisplayId, getFuzzedSize(), &pixelFormat)) {
+        return;
+    }
+
+    getDisplayIdentificationData();
+
+    mHwc.hasDisplayCapability(halDisplayID, mFdp.PickValueInArray(kDisplayCapability));
+
+    mHwc.allocatePhysicalDisplay(kHwDisplayId, mPhysicalDisplayId);
+
+    static auto hwcLayer = mHwc.createLayer(halDisplayID);
+    HWC2::Layer* layer = hwcLayer.get();
+    invokeLayer(layer);
+
+    getDeviceCompositionChanges(halDisplayID);
+
+    mHwc.setClientTarget(halDisplayID, mFdp.ConsumeIntegral<uint32_t>(), Fence::NO_FENCE,
+                         sp<GraphicBuffer>::make(), mFdp.PickValueInArray(kDataspaces));
+
+    mHwc.presentAndGetReleaseFences(halDisplayID, std::chrono::steady_clock::now(),
+                                    FenceTime::NO_FENCE);
+
+    mHwc.setPowerMode(mPhysicalDisplayId, mFdp.PickValueInArray(kPowerModes));
+
+    mHwc.setColorTransform(halDisplayID, getFuzzedMatrix());
+
+    mHwc.getPresentFence(halDisplayID);
+
+    mHwc.getLayerReleaseFence(halDisplayID, layer);
+
+    mHwc.setOutputBuffer(halVirtualDisplayId, sp<Fence>::make().get(), sp<GraphicBuffer>::make());
+
+    mHwc.clearReleaseFences(halDisplayID);
+
+    getHdrCapabilities(halDisplayID);
+
+    mHwc.getSupportedPerFrameMetadata(halDisplayID);
+
+    mHwc.getRenderIntents(halDisplayID, ui::ColorMode());
+
+    mHwc.getDataspaceSaturationMatrix(halDisplayID, ui::Dataspace());
+
+    getDisplayedContentSamplingAttributes(halDisplayID);
+
+    mHwc.setDisplayContentSamplingEnabled(halDisplayID, mFdp.ConsumeBool() /*enabled*/,
+                                          mFdp.ConsumeIntegral<uint8_t>() /*componentMask*/,
+                                          mFdp.ConsumeIntegral<uint64_t>() /*maxFrames*/);
+
+    getDisplayedContentSample(halDisplayID);
+
+    mHwc.setDisplayBrightness(mPhysicalDisplayId, mFdp.ConsumeFloatingPoint<float>(),
+                              Hwc2::Composer::DisplayBrightnessOptions{
+                                      .applyImmediately = mFdp.ConsumeIntegral<bool>()});
+
+    mHwc.onHotplug(kHwDisplayId, hal::Connection::CONNECTED);
+    mHwc.updatesDeviceProductInfoOnHotplugReconnect();
+
+    mHwc.onVsync(kHwDisplayId, mFdp.ConsumeIntegral<int64_t>());
+    mHwc.setVsyncEnabled(mPhysicalDisplayId,
+                         mFdp.ConsumeBool() ? hal::Vsync::ENABLE : hal::Vsync::DISABLE);
+
+    mHwc.isConnected(mPhysicalDisplayId);
+    mHwc.getModes(mPhysicalDisplayId);
+    mHwc.getActiveMode(mPhysicalDisplayId);
+    mHwc.getColorModes(mPhysicalDisplayId);
+    mHwc.hasCapability(mFdp.PickValueInArray(kCapability));
+
+    mHwc.setActiveColorMode(mPhysicalDisplayId, mFdp.PickValueInArray(kColormodes),
+                            mFdp.PickValueInArray(kRenderIntents));
+
+    mHwc.getDisplayConnectionType(mPhysicalDisplayId);
+    mHwc.isVsyncPeriodSwitchSupported(mPhysicalDisplayId);
+
+    getDisplayVsyncPeriod();
+
+    setActiveModeWithConstraints();
+
+    mHwc.setAutoLowLatencyMode(mPhysicalDisplayId, mFdp.ConsumeBool());
+
+    getSupportedContentTypes();
+
+    mHwc.setContentType(mPhysicalDisplayId, mFdp.PickValueInArray(kContentTypes));
+
+    dumpHwc();
+
+    mHwc.toPhysicalDisplayId(kHwDisplayId);
+    mHwc.fromPhysicalDisplayId(mPhysicalDisplayId);
+    mHwc.disconnectDisplay(halDisplayID);
+
+    static hal::HWDisplayId displayId = mFdp.ConsumeIntegral<hal::HWDisplayId>();
+    mHwc.onHotplug(displayId,
+                   mFdp.ConsumeBool() ? hal::Connection::DISCONNECTED : hal::Connection::CONNECTED);
+}
+
+template <size_t N>
+DisplayIdentificationData asDisplayIdentificationData(const unsigned char (&bytes)[N]) {
+    return DisplayIdentificationData(bytes, bytes + N - 1);
+}
+
+void DisplayHardwareFuzzer::invokeDisplayIdentification() {
+    static const DisplayIdentificationData data = asDisplayIdentificationData(kInternalEdid);
+    isEdid(data);
+    parseEdid(data);
+    parseDisplayIdentificationData(mFdp.ConsumeIntegral<uint8_t>(), data);
+    getPnpId(getVirtualDisplayId(mFdp.ConsumeIntegral<uint32_t>()));
+    getPnpId(mFdp.ConsumeIntegral<uint8_t>());
+}
+
+void DisplayHardwareFuzzer::process() {
+    invokeComposer();
+    invokeAidlComposer();
+    invokeDisplayIdentification();
+    invokeFrameBufferSurface();
+    invokeVirtualDisplaySurface();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    DisplayHardwareFuzzer displayHardwareFuzzer(data, size);
+    displayHardwareFuzzer.process();
+    return 0;
+}
+
+} // namespace android::fuzz
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer_utils.h
new file mode 100644
index 0000000..6a6e3db
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer_utils.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#pragma once
+
+#include <utils/Condition.h>
+#include <chrono>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.4/IComposer.h>
+#include <composer-hal/2.1/ComposerClient.h>
+#include <composer-hal/2.2/ComposerClient.h>
+#include <composer-hal/2.3/ComposerClient.h>
+#include <composer-hal/2.4/ComposerClient.h>
+
+#include "DisplayHardware/HWC2.h"
+#include "surfaceflinger_fuzzers_utils.h"
+
+namespace {
+class LayerImpl;
+class Frame;
+class DelayedEventGenerator;
+} // namespace
+
+namespace android {
+class SurfaceComposerClient;
+} // namespace android
+
+namespace android::hardware::graphics::composer::hal {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::HWC2::ComposerCallback;
+
+class ComposerCallbackBridge : public IComposerCallback {
+public:
+    ComposerCallbackBridge(ComposerCallback* callback, bool vsyncSwitchingSupported)
+          : mCallback(callback), mVsyncSwitchingSupported(vsyncSwitchingSupported) {}
+
+    Return<void> onHotplug(HWDisplayId display, Connection connection) override {
+        mCallback->onComposerHalHotplug(display, connection);
+        return Void();
+    }
+
+    Return<void> onRefresh(HWDisplayId display) override {
+        mCallback->onComposerHalRefresh(display);
+        return Void();
+    }
+
+    Return<void> onVsync(HWDisplayId display, int64_t timestamp) override {
+        if (!mVsyncSwitchingSupported) {
+            mCallback->onComposerHalVsync(display, timestamp, std::nullopt);
+        }
+        return Void();
+    }
+
+    Return<void> onVsync_2_4(HWDisplayId display, int64_t timestamp,
+                             VsyncPeriodNanos vsyncPeriodNanos) override {
+        if (mVsyncSwitchingSupported) {
+            mCallback->onComposerHalVsync(display, timestamp, vsyncPeriodNanos);
+        }
+        return Void();
+    }
+
+    Return<void> onVsyncPeriodTimingChanged(HWDisplayId display,
+                                            const VsyncPeriodChangeTimeline& timeline) override {
+        mCallback->onComposerHalVsyncPeriodTimingChanged(display, timeline);
+        return Void();
+    }
+
+    Return<void> onSeamlessPossible(HWDisplayId display) override {
+        mCallback->onComposerHalSeamlessPossible(display);
+        return Void();
+    }
+
+private:
+    ComposerCallback* const mCallback;
+    const bool mVsyncSwitchingSupported;
+};
+
+struct TestHWC2ComposerCallback : public HWC2::ComposerCallback {
+    virtual ~TestHWC2ComposerCallback() = default;
+    void onComposerHalHotplug(HWDisplayId, Connection){};
+    void onComposerHalRefresh(HWDisplayId) {}
+    void onComposerHalVsync(HWDisplayId, int64_t, std::optional<VsyncPeriodNanos>) {}
+    void onComposerHalVsyncPeriodTimingChanged(HWDisplayId, const VsyncPeriodChangeTimeline&) {}
+    void onComposerHalSeamlessPossible(HWDisplayId) {}
+    void onComposerHalVsyncIdle(HWDisplayId) {}
+};
+
+} // namespace android::hardware::graphics::composer::hal