Introduce fixed rotation transform

It allows activity to be shown in an orientation different
from the current display. This initial change only handles
the case when transiting to another activity with different
orientation.

The opening activity and its process will be updated with
rotated configuration. The rotated display frames and insets
are also associated to the activity, then the activity can
be layouted in the rotated bounds. The surface of activity
is rotated to fit current display. And the display will be
rotated seamlessly until the transition is done.

The function is disabled by default. It can be enabled by:
adb shell settings put global fixed_rotation_transform 1

Bug: 143053092
Bug: 146415879
Bug: 147469351
Test: atest DisplayContentTests#testApplyTopFixedRotationTransform

Change-Id: Iea15c6fc68133728e5fcda87ba4efd1850fdf5d4
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 294c36a..da996dc 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -141,6 +141,12 @@
     @ActivityInfo.ScreenOrientation
     protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
 
+    /**
+     * The window container which decides its orientation since the last time
+     * {@link #getOrientation(int) was called.
+     */
+    protected WindowContainer mLastOrientationSource;
+
     private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
             new Pools.SynchronizedPool<>(3);
 
@@ -1061,6 +1067,7 @@
      * @return The orientation as specified by this branch or the window hierarchy.
      */
     int getOrientation(int candidate) {
+        mLastOrientationSource = null;
         if (!fillsParent()) {
             // Ignore containers that don't completely fill their parents.
             return SCREEN_ORIENTATION_UNSET;
@@ -1072,6 +1079,7 @@
         // if none of the children have a better candidate for the orientation.
         if (mOrientation != SCREEN_ORIENTATION_UNSET
                 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
+            mLastOrientationSource = this;
             return mOrientation;
         }
 
@@ -1087,6 +1095,7 @@
                 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
                 // look behind this container.
                 candidate = orientation;
+                mLastOrientationSource = wc;
                 continue;
             }
 
@@ -1100,6 +1109,7 @@
                 ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)",
                         wc.toString(), orientation,
                         ActivityInfo.screenOrientationToString(orientation));
+                mLastOrientationSource = wc;
                 return orientation;
             }
         }
@@ -1108,6 +1118,22 @@
     }
 
     /**
+     * @return The deepest source which decides the orientation of this window container since the
+     *         last time {@link #getOrientation(int) was called.
+     */
+    @Nullable
+    WindowContainer getLastOrientationSource() {
+        final WindowContainer source = mLastOrientationSource;
+        if (source != null && source != this) {
+            final WindowContainer nextSource = source.getLastOrientationSource();
+            if (nextSource != null) {
+                return nextSource;
+            }
+        }
+        return source;
+    }
+
+    /**
      * Returns true if this container is opaque and fills all the space made available by its parent
      * container.
      *