Fix the source crop for screenshots for notch hide

* Orientation transform needs to be applied after the device transform
* Source crop needs to have a transform applied to it so that the
clipping window is in the right spot.

Bug: 129362302
Test: screenshots
Change-Id: I675be4d1fb2386f24ead69a77b08bec65d2f5d47
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index c80925e..0067b50 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -288,16 +288,21 @@
     }
 
     Rect getSourceCrop() const override {
-        // use the (projected) logical display viewport by default
+        // use the projected display viewport by default.
         if (mSourceCrop.isEmpty()) {
             return mDevice->getScissor();
         }
 
-        const int orientation = mDevice->getInstallOrientation();
-        if (orientation == DisplayState::eOrientationDefault) {
-            return mSourceCrop;
-        }
+        // Recompute the device transformation for the source crop.
+        ui::Transform rotation;
+        ui::Transform translatePhysical;
+        ui::Transform translateLogical;
+        ui::Transform scale;
+        const Rect& viewport = mDevice->getViewport();
+        const Rect& scissor = mDevice->getScissor();
+        const Rect& frame = mDevice->getFrame();
 
+        const int orientation = mDevice->getInstallOrientation();
         // Install orientation is transparent to the callers.  Apply it now.
         uint32_t flags = 0x00;
         switch (orientation) {
@@ -310,10 +315,17 @@
             case DisplayState::eOrientation270:
                 flags = ui::Transform::ROT_270;
                 break;
+            default:
+                break;
         }
-        ui::Transform tr;
-        tr.set(flags, getWidth(), getHeight());
-        return tr.transform(mSourceCrop);
+        rotation.set(flags, getWidth(), getHeight());
+        translateLogical.set(-viewport.left, -viewport.top);
+        translatePhysical.set(scissor.left, scissor.top);
+        scale.set(frame.getWidth() / float(viewport.getWidth()), 0, 0,
+                  frame.getHeight() / float(viewport.getHeight()));
+        const ui::Transform finalTransform =
+                rotation * translatePhysical * scale * translateLogical;
+        return finalTransform.transform(mSourceCrop);
     }
 
 private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0345baf..93a5b57 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5671,8 +5671,9 @@
 
     const auto reqWidth = renderArea.getReqWidth();
     const auto reqHeight = renderArea.getReqHeight();
-    const auto sourceCrop = renderArea.getSourceCrop();
     const auto rotation = renderArea.getRotationFlags();
+    const auto transform = renderArea.getTransform();
+    const auto sourceCrop = renderArea.getSourceCrop();
 
     renderengine::DisplaySettings clientCompositionDisplay;
     std::vector<renderengine::LayerSettings> clientCompositionLayers;
@@ -5680,31 +5681,34 @@
     // assume that bounds are never offset, and that they are the same as the
     // buffer bounds.
     clientCompositionDisplay.physicalDisplay = Rect(reqWidth, reqHeight);
-    ui::Transform transform = renderArea.getTransform();
+    clientCompositionDisplay.clip = sourceCrop;
     clientCompositionDisplay.globalTransform = transform.asMatrix4();
+
+    // Now take into account the rotation flag. We append a transform that
+    // rotates the layer stack about the origin, then translate by buffer
+    // boundaries to be in the right quadrant.
     mat4 rotMatrix;
-    // Displacement for repositioning the clipping rectangle after rotating it
-    // with the rotation hint.
     int displacementX = 0;
     int displacementY = 0;
     float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
     switch (rotation) {
         case ui::Transform::ROT_90:
             rotMatrix = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
-            displacementX = reqWidth;
+            displacementX = renderArea.getBounds().getHeight();
             break;
         case ui::Transform::ROT_180:
             rotMatrix = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
-            displacementX = reqWidth;
-            displacementY = reqHeight;
+            displacementY = renderArea.getBounds().getWidth();
+            displacementX = renderArea.getBounds().getHeight();
             break;
         case ui::Transform::ROT_270:
             rotMatrix = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
-            displacementY = reqHeight;
+            displacementY = renderArea.getBounds().getWidth();
             break;
         default:
             break;
     }
+
     // We need to transform the clipping window into the right spot.
     // First, rotate the clipping rectangle by the rotation hint to get the
     // right orientation
@@ -5720,15 +5724,14 @@
     // Now reposition the clipping rectangle with the displacement vector
     // computed above.
     const mat4 displacementMat = mat4::translate(vec4(displacementX, displacementY, 0, 1));
-
     clientCompositionDisplay.clip =
             Rect(newClipLeft + displacementX, newClipTop + displacementY,
                  newClipRight + displacementX, newClipBottom + displacementY);
 
-    // We need to perform the same transformation in layer space, so propagate
-    // it to the global transform.
     mat4 clipTransform = displacementMat * rotMatrix;
-    clientCompositionDisplay.globalTransform *= clipTransform;
+    clientCompositionDisplay.globalTransform =
+            clipTransform * clientCompositionDisplay.globalTransform;
+
     clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
     clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;