[PiP2] Allow btn nav legacy fixed rotation

Implement legacy-enter PiP2 with fixed rotation,
by detecting fixed rotation signals in
PipTransition#startAlphaTypeEnterAnimation().

Allow PipController#onDisplayChange() to come in
while we are still entering PiP ans display rotation
TRANSIT_CHANGE transition can be requested during that time as well.

For PiP2, We also don't need to block Transition::setEndFixedRotation()
if both PiP task and its activity are in pinned windowing mode. This is
needed since, in PiP2, both the task and activity become pinned in the
collection phase as the startWCT gets applied.

Bug: 377508792
Flag: com.android.wm.shell.enable_pip2
Test: legacy-enter PiP from landscape orientation in btn-nav

Change-Id: I8c0c033fabfbbcf91521679effc961fc2853c596
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
index 119763f..4e341ac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
@@ -340,7 +340,8 @@
             mPipDisplayLayoutState.rotateTo(toRotation);
         }
 
-        if (!mPipTransitionState.isInPip()) {
+        if (!mPipTransitionState.isInPip()
+                && mPipTransitionState.getState() != PipTransitionState.ENTERING_PIP) {
             // Skip the PiP-relevant updates if we aren't in a valid PiP state.
             if (mPipTransitionState.isInFixedRotation()) {
                 ProtoLog.e(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index 9bb2e38..cfcd563 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -45,6 +45,7 @@
 import android.app.PictureInPictureParams;
 import android.app.TaskInfo;
 import android.content.Context;
+import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -452,7 +453,7 @@
         final int delta = getFixedRotationDelta(info, pipChange, mPipDisplayLayoutState);
         if (delta != ROTATION_0) {
             // Update transition target changes in place to prepare for fixed rotation.
-            handleBoundsEnterFixedRotation(info, pipChange, pipActivityChange);
+            updatePipChangesForFixedRotation(info, pipChange, pipActivityChange);
         }
 
         // Update the src-rect-hint in params in place, to set up initial animator transform.
@@ -513,7 +514,7 @@
         final int delta = getFixedRotationDelta(info, pipChange, mPipDisplayLayoutState);
         if (delta != ROTATION_0) {
             // Update transition target changes in place to prepare for fixed rotation.
-            handleBoundsEnterFixedRotation(info, pipChange, pipActivityChange);
+            updatePipChangesForFixedRotation(info, pipChange, pipActivityChange);
         }
 
         PipEnterAnimator animator = new PipEnterAnimator(mContext, pipLeash,
@@ -546,7 +547,7 @@
         return true;
     }
 
-    private void handleBoundsEnterFixedRotation(TransitionInfo info,
+    private void updatePipChangesForFixedRotation(TransitionInfo info,
             TransitionInfo.Change outPipTaskChange,
             TransitionInfo.Change outPipActivityChange) {
         final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info);
@@ -604,10 +605,33 @@
         SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash();
         Preconditions.checkNotNull(pipLeash, "Leash is null for alpha transition.");
 
-        // Start transition with 0 alpha at the entry bounds.
-        startTransaction.setPosition(pipLeash, destinationBounds.left, destinationBounds.top)
-                .setWindowCrop(pipLeash, destinationBounds.width(), destinationBounds.height())
-                .setAlpha(pipLeash, 0f);
+        final int delta = getFixedRotationDelta(info, pipChange, mPipDisplayLayoutState);
+        if (delta != ROTATION_0) {
+            updatePipChangesForFixedRotation(info, pipChange,
+                    // We don't have an activity change to animate in legacy enter,
+                    // so just use a placeholder one as the outPipActivityChange.
+                    new TransitionInfo.Change(null /* container */, new SurfaceControl()));
+        }
+        startTransaction.setWindowCrop(pipLeash,
+                destinationBounds.width(), destinationBounds.height());
+        if (delta != ROTATION_0) {
+            // In a fixed rotation case, rotate PiP leash in the old orientation to its final
+            // position, but keep the bounds visually invariant until async rotation changes
+            // the display rotation after
+            int normalizedRotation = delta;
+            if (normalizedRotation == ROTATION_270) {
+                normalizedRotation = -ROTATION_90;
+            }
+            Matrix transformTensor = new Matrix();
+            final float[] matrixTmp = new float[9];
+            transformTensor.setTranslate(destinationBounds.left, destinationBounds.top);
+            transformTensor.postRotate(-normalizedRotation * 90f);
+
+            startTransaction.setMatrix(pipLeash, transformTensor, matrixTmp);
+            finishTransaction.setMatrix(pipLeash, transformTensor, matrixTmp);
+        } else {
+            startTransaction.setPosition(pipLeash, destinationBounds.left, destinationBounds.top);
+        }
 
         PipAlphaAnimator animator = new PipAlphaAnimator(mContext, pipLeash, startTransaction,
                 finishTransaction, PipAlphaAnimator.FADE_IN);
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index c78cdaa..8917f4e 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -3194,7 +3194,8 @@
             // Fixed rotation only applies to opening or changing activity.
             return;
         }
-        if (task.inMultiWindowMode() && taskTopRunning.inMultiWindowMode()) {
+        if (!ActivityTaskManagerService.isPip2ExperimentEnabled()
+                && task.inMultiWindowMode() && taskTopRunning.inMultiWindowMode()) {
             // Display won't be rotated for multi window Task, so the fixed rotation won't be
             // applied. This can happen when the windowing mode is changed before the previous
             // fixed rotation is applied. Check both task and activity because the activity keeps