Unrotate inputwindows into rotation display grew-up in

This way inputflinger internally works within one coordinate
space at all times and only transforms coordinates for dispatch
to targets

This is behind a flag:
   adb shell setprop persist.debug.per_window_input_rotation 1

Bug: 179274888
Test: phone should work as before
Change-Id: I503f9beea9863193801aa6422a416382374e48c8
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 237aaff..8ef7c90 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -25,6 +25,7 @@
 
 #include "Layer.h"
 
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android/native_window.h>
 #include <binder/IPCThreadState.h>
@@ -2480,7 +2481,7 @@
     if (traceFlags & SurfaceTracing::TRACE_INPUT) {
         InputWindowInfo info;
         if (useDrawing) {
-            info = fillInputInfo();
+            info = fillInputInfo({nullptr});
         } else {
             info = state.inputInfo;
         }
@@ -2501,7 +2502,7 @@
     return mRemovedFromCurrentState;
 }
 
-void Layer::fillInputFrameInfo(InputWindowInfo& info) {
+void Layer::fillInputFrameInfo(InputWindowInfo& info, const ui::Transform& toPhysicalDisplay) {
     // Transform layer size to screen space and inset it by surface insets.
     // If this is a portal window, set the touchableRegion to the layerBounds.
     Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE
@@ -2521,9 +2522,13 @@
         return;
     }
 
-    ui::Transform t = getTransform();
+    ui::Transform layerToDisplay = getTransform();
+    // Transform that takes window coordinates to unrotated display coordinates
+    ui::Transform t = toPhysicalDisplay * layerToDisplay;
     int32_t xSurfaceInset = info.surfaceInset;
     int32_t ySurfaceInset = info.surfaceInset;
+    // Bring screenBounds into unrotated space
+    Rect screenBounds = toPhysicalDisplay.transform(Rect{mScreenBounds});
 
     const float xScale = t.getScaleX();
     const float yScale = t.getScaleY();
@@ -2581,7 +2586,6 @@
     // 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.
-    Rect screenBounds = Rect{mScreenBounds};
     transformedLayerBounds.intersect(screenBounds, &transformedLayerBounds);
     info.frameLeft = transformedLayerBounds.left;
     info.frameTop = transformedLayerBounds.top;
@@ -2593,7 +2597,7 @@
     info.touchableRegion = inputTransform.transform(info.touchableRegion);
 }
 
-InputWindowInfo Layer::fillInputInfo() {
+InputWindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) {
     if (!hasInputInfo()) {
         mDrawingState.inputInfo.name = getName();
         mDrawingState.inputInfo.ownerUid = mOwnerUid;
@@ -2610,7 +2614,13 @@
         info.displayId = getLayerStack();
     }
 
-    fillInputFrameInfo(info);
+    // Transform that goes from "logical(rotated)" display to physical/unrotated display.
+    // This is for when inputflinger operates in physical display-space.
+    ui::Transform toPhysicalDisplay;
+    if (display) {
+        toPhysicalDisplay = display->getTransform();
+    }
+    fillInputFrameInfo(info, toPhysicalDisplay);
 
     // For compatibility reasons we let layers which can receive input
     // receive input before they have actually submitted a buffer. Because
@@ -2626,12 +2636,14 @@
     auto cropLayer = mDrawingState.touchableRegionCrop.promote();
     if (info.replaceTouchableRegionWithCrop) {
         if (cropLayer == nullptr) {
-            info.touchableRegion = Region(Rect{mScreenBounds});
+            info.touchableRegion = Region(toPhysicalDisplay.transform(Rect{mScreenBounds}));
         } else {
-            info.touchableRegion = Region(Rect{cropLayer->mScreenBounds});
+            info.touchableRegion =
+                    Region(toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds}));
         }
     } else if (cropLayer != nullptr) {
-        info.touchableRegion = info.touchableRegion.intersect(Rect{cropLayer->mScreenBounds});
+        info.touchableRegion = info.touchableRegion.intersect(
+                toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds}));
     }
 
     // If the layer is a clone, we need to crop the input region to cloned root to prevent
@@ -2639,7 +2651,7 @@
     if (isClone()) {
         sp<Layer> clonedRoot = getClonedRoot();
         if (clonedRoot != nullptr) {
-            Rect rect(clonedRoot->mScreenBounds);
+            Rect rect = toPhysicalDisplay.transform(Rect{clonedRoot->mScreenBounds});
             info.touchableRegion = info.touchableRegion.intersect(rect);
         }
     }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 687f473..1461756 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -913,7 +913,7 @@
     bool getPremultipledAlpha() const;
     void setInputInfo(const InputWindowInfo& info);
 
-    InputWindowInfo fillInputInfo();
+    InputWindowInfo fillInputInfo(const sp<DisplayDevice>& display);
     /**
      * Returns whether this layer has an explicitly set input-info.
      */
@@ -1193,7 +1193,7 @@
     sp<Layer> getRootLayer();
 
     // Fills in the frame and transform info for the InputWindowInfo
-    void fillInputFrameInfo(InputWindowInfo& info);
+    void fillInputFrameInfo(InputWindowInfo& info, const ui::Transform& toPhysicalDisplay);
 
     // Cached properties computed from drawing state
     // Effective transform taking into account parent transforms and any parent scaling, which is
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7fada82..e9438e9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2906,15 +2906,32 @@
     mInputWindowCommands.clear();
 }
 
+bool enablePerWindowInputRotation() {
+    static bool value =
+            android::base::GetBoolProperty("persist.debug.per_window_input_rotation", false);
+    return value;
+}
+
 void SurfaceFlinger::updateInputWindowInfo() {
     std::vector<InputWindowInfo> inputInfos;
 
     mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
-        if (layer->needsInputInfo()) {
-            // When calculating the screen bounds we ignore the transparent region since it may
-            // result in an unwanted offset.
-            inputInfos.push_back(layer->fillInputInfo());
+        if (!layer->needsInputInfo()) return;
+        sp<DisplayDevice> display;
+        if (enablePerWindowInputRotation()) {
+            for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
+                const auto& displayDevice = pair.second;
+                if (!displayDevice->getCompositionDisplay()
+                             ->belongsInOutput(layer->getLayerStack(),
+                                               layer->getPrimaryDisplayOnly())) {
+                    continue;
+                }
+                display = displayDevice;
+            }
         }
+        // When calculating the screen bounds we ignore the transparent region since it may
+        // result in an unwanted offset.
+        inputInfos.push_back(layer->fillInputInfo(display));
     });
 
     mInputFlinger->setInputWindows(inputInfos,