SurfaceFlinger: Fixes around rotation and cropping.

SurfaceFlinger's renderer is not prepared to handle cropping in the face of
arbitrary rotation. To see the problem observe that if we have a square parent,
and a child of the same size, then we rotate the child 45 degrees around it's
center, the child must now be cropped to a non rectangular 8 sided region.

We can fix this problem in the future (b/109894387), but for now we are lucky.
SurfaceControl is private API, and the WindowManager only uses rotation in one
case, which is on a top level layer in which cropping need not be an issue
(this case is the screen rotation animation, where all the windows are rotated
together).

However given that the abuse of rotation matrices could lead to surfaces
extending outside of theire intended crop, we need to prevent non root-clients
without permission ACCESS_SURFACE_FLINGER (a.k.a. everyone except WindowManager
and tests) from setting non rectangle preserving transformations.

Our sad story continues, with the implementation of computeBounds. Notice the
intersection with the parent window is done in screen space by applying
and then inverting the transformation. However since the transformation doesn't
preserve rectangles, we get a different, in-correct, and larger result
from applying and inverting the transformation.

We don't need to be performing this computation in screen space, it's enough to
apply the local transform relative to the parent and then intersect with the
parent's computed bounds in the parent space. When we write the logic this way
it means we will only produce incorrect results for children who rotate outside
of their visible region. In the case of the WindowManager rotation animation
it rotates top level layers which do not have parents, and so we will
not produce incorrect results. We lock down other cases and clients
as described above.

Unfortunately our story continues, since our implementation of final crop was relying
on transforming Layers up to screen-space, this will no longer work with the
new implementation of compute bounds. We have to change setFinalCrop to crop
in parent-space rather than the final screen space. This is a semantic change, but
luckily there is only one user of setFinalCrop and it is on a layer whose parent
(The WM animation Layer) is already in screen space, so it's not a semantic change
for any actual clients.

Test: Manual.
Bug: 69913240
Bug: 109894387
Change-Id: I522e258cee03ac8e3609a40f53461119b7c45532
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2595ec1..6d5a598 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -345,20 +345,25 @@
         win.intersect(s.crop, &win);
     }
 
-    Rect bounds = win;
     const auto& p = mDrawingParent.promote();
+    FloatRect floatWin = win.toFloatRect();
+    FloatRect parentBounds = floatWin;
     if (p != nullptr) {
-        // Look in computeScreenBounds recursive call for explanation of
-        // why we pass false here.
-        bounds = p->computeScreenBounds(false /* reduceTransparentRegion */);
+        // We pass an empty Region here for reasons mirroring that of the case described in
+        // the computeScreenBounds reduceTransparentRegion=false case.
+        parentBounds = p->computeBounds(Region());
     }
 
-    Transform t = getTransform();
+    Transform t = s.active.transform;
 
-    FloatRect floatWin = win.toFloatRect();
-    if (p != nullptr) {
+
+    if (p != nullptr || !s.finalCrop.isEmpty()) {
         floatWin = t.transform(floatWin);
-        floatWin = floatWin.intersect(bounds.toFloatRect());
+        floatWin = floatWin.intersect(parentBounds);
+
+        if (!s.finalCrop.isEmpty()) {
+            floatWin = floatWin.intersect(s.finalCrop.toFloatRect());
+        }
         floatWin = t.inverse().transform(floatWin);
     }
 
@@ -1249,7 +1254,15 @@
     return true;
 }
 
-bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
+bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix,
+        bool allowNonRectPreservingTransforms) {
+    Transform t;
+    t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+
+    if (!allowNonRectPreservingTransforms && !t.preserveRects()) {
+        ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored");
+        return false;
+    }
     mCurrentState.sequence++;
     mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
     mCurrentState.modified = true;