Check ROTATE_SURFACE_FLINGER permission on arbitrary rotation

This permission is granted for arbitrary rotation (other than 90
degreee) on a Surface. Which is useful for Launcher to rotate the app
leash when animating from fullscreen landscape to PiP window onto home
in portrait mode.

Bug: 109894387
Test: m -j
Change-Id: Ie2bac0d76e6f1187954b65d6689a6adb7836e09c
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 773b3ab..d27cd3f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -274,6 +274,7 @@
 
 const String16 sHardwareTest("android.permission.HARDWARE_TEST");
 const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
+const String16 sRotateSurfaceFlinger("android.permission.ROTATE_SURFACE_FLINGER");
 const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
 const String16 sDump("android.permission.DUMP");
 const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
@@ -324,6 +325,14 @@
     }
 }
 
+bool callingThreadHasRotateSurfaceFlingerAccess() {
+    IPCThreadState* ipc = IPCThreadState::self();
+    const int pid = ipc->getCallingPid();
+    const int uid = ipc->getCallingUid();
+    return uid == AID_GRAPHICS || uid == AID_SYSTEM ||
+            PermissionCache::checkPermission(sRotateSurfaceFlinger, pid, uid);
+}
+
 SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()) {}
 
 SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
@@ -3652,15 +3661,20 @@
         // must now be cropped to a non rectangular 8 sided region.
         //
         // Of course we can fix this in the future. 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 is not an issue.
+        // private API, and arbitrary rotation is used in limited use cases, for instance:
+        // - WindowManager only uses rotation in one case, which is on a top level layer in which
+        //   cropping is not an issue.
+        // - Launcher, as a privileged app, uses this to transition an application to PiP
+        //   (picture-in-picture) mode.
         //
         // However given that abuse of rotation matrices could lead to surfaces extending outside
-        // of cropped areas, 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.
-        if (layer->setMatrix(s.matrix, privileged))
-            flags |= eTraversalNeeded;
+        // of cropped areas, we need to prevent non-root clients without permission
+        // ACCESS_SURFACE_FLINGER nor ROTATE_SURFACE_FLINGER
+        // (a.k.a. everyone except WindowManager / tests / Launcher) from setting non rectangle
+        // preserving transformations.
+        bool allowNonRectPreservingTransforms =
+                privileged || callingThreadHasRotateSurfaceFlingerAccess();
+        if (layer->setMatrix(s.matrix, allowNonRectPreservingTransforms)) flags |= eTraversalNeeded;
     }
     if (what & layer_state_t::eTransparentRegionChanged) {
         if (layer->setTransparentRegionHint(s.transparentRegion))