Disallow onExitPipFinished() from being called multiple times

- We really should fix the root cause, but return early for now to
  unblock shell transitions
- Ensure tests call onTaskAppeared() with a valid surface control

Bug: 239461594
Test: atest WMShellFlickerTests
Change-Id: I9ca41537ab6128ffde9d2061be3e2bc16d0a3f0b
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index da88c2d..913e4b7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -62,6 +62,7 @@
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.util.Log;
 import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -930,6 +931,12 @@
 
     /** Called when exiting PIP transition is finished to do the state cleanup. */
     void onExitPipFinished(TaskInfo info) {
+        if (mLeash == null) {
+            // TODO(239461594): Remove once the double call to onExitPipFinished() is fixed
+            Log.w(TAG, "Warning, onExitPipFinished() called multiple times in the same sessino");
+            return;
+        }
+
         clearWaitForFixedRotation();
         if (mSwipePipToHomeOverlay != null) {
             removeContentOverlay(mSwipePipToHomeOverlay, null /* callback */);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index b351f8f..857f578 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -42,6 +42,7 @@
 import android.util.Rational;
 import android.util.Size;
 import android.view.DisplayInfo;
+import android.view.SurfaceControl;
 import android.window.WindowContainerToken;
 
 import com.android.wm.shell.MockSurfaceControlHelper;
@@ -150,7 +151,7 @@
         final Rational aspectRatio = new Rational(2, 1);
 
         mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
-                createPipParams(aspectRatio)), null /* leash */);
+                createPipParams(aspectRatio)), mock(SurfaceControl.class));
 
         assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f);
     }
@@ -158,7 +159,7 @@
     @Test
     public void onTaskAppeared_updatesLastPipComponentName() {
         mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)),
-                null /* leash */);
+                mock(SurfaceControl.class));
 
         assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName());
     }
@@ -169,7 +170,7 @@
 
         mSpiedPipTaskOrganizer.onTaskAppeared(
                 createTaskInfo(mComponent1, createPipParams(null), minSize),
-                null /* leash */);
+                mock(SurfaceControl.class));
 
         assertEquals(minSize, mPipBoundsState.getOverrideMinSize());
     }
@@ -179,7 +180,7 @@
         final Rational startAspectRatio = new Rational(2, 1);
         final Rational newAspectRatio = new Rational(1, 2);
         mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
-                createPipParams(startAspectRatio)), null /* leash */);
+                createPipParams(startAspectRatio)), mock(SurfaceControl.class));
 
         // It is in entering transition, should defer onTaskInfoChanged callback in this case.
         mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
@@ -197,7 +198,7 @@
         final Rational startAspectRatio = new Rational(2, 1);
         final Rational newAspectRatio = new Rational(1, 2);
         mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
-                createPipParams(startAspectRatio)), null /* leash */);
+                createPipParams(startAspectRatio)), mock(SurfaceControl.class));
         mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
 
         mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
@@ -210,7 +211,7 @@
     @Test
     public void onTaskInfoChanged_inPip_updatesLastPipComponentName() {
         mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
-                createPipParams(null)), null /* leash */);
+                createPipParams(null)), mock(SurfaceControl.class));
         mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
 
         mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
@@ -222,7 +223,7 @@
     @Test
     public void onTaskInfoChanged_inPip_updatesOverrideMinSize() {
         mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
-                createPipParams(null)), null /* leash */);
+                createPipParams(null)), mock(SurfaceControl.class));
         mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
 
         final Size minSize = new Size(400, 320);
@@ -235,7 +236,7 @@
     @Test
     public void onTaskVanished_clearsPipBounds() {
         mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
-                createPipParams(null)), null /* leash */);
+                createPipParams(null)), mock(SurfaceControl.class));
         mPipBoundsState.setBounds(new Rect(100, 100, 200, 150));
 
         mSpiedPipTaskOrganizer.onTaskVanished(createTaskInfo(mComponent1, createPipParams(null)));