SF: Calculate WindowInfo frame correctly for all layers

The old logic skipped transform calculation using an early return if the
layer bounds were invalid. This skipped the calculations which
transformed the WindowInfo frame into display space. This also resulted in
container layers being misconfigured, since they did not have their
input bounds calculated correctly.

Allow all layers to have their WindowInfo calculated correctly in
display space, even if their input bounds happen to be invalid.

Bug: 162194035
Test: atest libgui_test
Test: manual
Change-Id: I7b3c361bb9a12adf52586d3a940501e4d8a9e667
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 6f1263b..83e9858 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -987,6 +987,82 @@
     EXPECT_EQ(surface->consumeEvent(100), nullptr);
 }
 
+/**
+ * If a cropped layer's touchable region is replaced with a null crop, it should receive input in
+ * its own crop.
+ */
+TEST_F(InputSurfacesTest, cropped_container_replaces_touchable_region_with_null_crop) {
+    std::unique_ptr<InputSurface> parentContainer =
+            InputSurface::makeContainerInputSurface(mComposerClient, 0, 0);
+    std::unique_ptr<InputSurface> containerSurface =
+            InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);
+    containerSurface->doTransaction(
+            [&](auto &t, auto &sc) { t.reparent(sc, parentContainer->mSurfaceControl); });
+    containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true;
+    containerSurface->mInputInfo.touchableRegionCropHandle = nullptr;
+    parentContainer->showAt(10, 10, Rect(0, 0, 20, 20));
+    containerSurface->showAt(10, 10, Rect(0, 0, 5, 5));
+
+    // Receives events inside its own crop
+    injectTap(21, 21);
+    containerSurface->expectTap(1, 1); // Event is in layer space
+
+    // Does not receive events outside its crop
+    injectTap(26, 26);
+    EXPECT_EQ(containerSurface->consumeEvent(100), nullptr);
+}
+
+/**
+ * If an un-cropped layer's touchable region is replaced with a null crop, it should receive input
+ * in its parent's touchable region. The input events should be in the layer's coordinate space.
+ */
+TEST_F(InputSurfacesTest, uncropped_container_replaces_touchable_region_with_null_crop) {
+    std::unique_ptr<InputSurface> parentContainer =
+            InputSurface::makeContainerInputSurface(mComposerClient, 0, 0);
+    std::unique_ptr<InputSurface> containerSurface =
+            InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);
+    containerSurface->doTransaction(
+            [&](auto &t, auto &sc) { t.reparent(sc, parentContainer->mSurfaceControl); });
+    containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true;
+    containerSurface->mInputInfo.touchableRegionCropHandle = nullptr;
+    parentContainer->showAt(10, 10, Rect(0, 0, 20, 20));
+    containerSurface->showAt(10, 10, Rect::INVALID_RECT);
+
+    // Receives events inside parent bounds
+    injectTap(21, 21);
+    containerSurface->expectTap(1, 1); // Event is in layer space
+
+    // Does not receive events outside parent bounds
+    injectTap(31, 31);
+    EXPECT_EQ(containerSurface->consumeEvent(100), nullptr);
+}
+
+/**
+ * If a layer's touchable region is replaced with a layer crop, it should receive input in the crop
+ * layer's bounds. The input events should be in the layer's coordinate space.
+ */
+TEST_F(InputSurfacesTest, replace_touchable_region_with_crop) {
+    std::unique_ptr<InputSurface> cropLayer =
+            InputSurface::makeContainerInputSurface(mComposerClient, 0, 0);
+    cropLayer->showAt(50, 50, Rect(0, 0, 20, 20));
+
+    std::unique_ptr<InputSurface> containerSurface =
+            InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);
+    containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true;
+    containerSurface->mInputInfo.touchableRegionCropHandle =
+            cropLayer->mSurfaceControl->getHandle();
+    containerSurface->showAt(10, 10, Rect::INVALID_RECT);
+
+    // Receives events inside crop layer bounds
+    injectTap(51, 51);
+    containerSurface->expectTap(41, 41); // Event is in layer space
+
+    // Does not receive events outside crop layer bounds
+    injectTap(21, 21);
+    injectTap(71, 71);
+    EXPECT_EQ(containerSurface->consumeEvent(100), nullptr);
+}
+
 class MultiDisplayTests : public InputSurfacesTest {
 public:
     MultiDisplayTests() : InputSurfacesTest() { ProcessState::self()->startThreadPool(); }