Fix NPE when animation doesn't get started

If animation start is delayed, there is no guarantee that
startAnimation is called on the adapter. Thus, protect
RemoteAnimationController against this case, as leash and
finishedCallback would be null.

Furthermore don't even try to start remote animation that is
delayed as it would leave it hanging forever.

Test: SurfaceAnimatorTest/RemoteAnimationControllerTest
Change-Id: I72c492c4fb6ca8eeae481d2c281e9c1fee95f921
Fixes: 76096628
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index a76857e..85436da 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1698,7 +1698,10 @@
                 stack.getBounds(mTmpRect);
                 mTmpRect.offsetTo(0, 0);
             }
-            if (mService.mAppTransition.getRemoteAnimationController() != null) {
+
+            // Delaying animation start isn't compatible with remote animations at all.
+            if (mService.mAppTransition.getRemoteAnimationController() != null
+                    && !mSurfaceAnimator.isAnimationStartDelayed()) {
                 adapter = mService.mAppTransition.getRemoteAnimationController()
                         .createAnimationAdapter(this, mTmpPoint, mTmpRect);
             } else {
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index d7f480b..c590067 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -99,6 +99,10 @@
         mFinishedCallback = new FinishedCallback(this);
 
         final RemoteAnimationTarget[] animations = createAnimations();
+        if (animations.length == 0) {
+            onAnimationFinished();
+            return;
+        }
         mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
             try {
                 mRemoteAnimationAdapter.getRunner().onAnimationStart(animations,
@@ -132,6 +136,8 @@
                     mPendingAnimations.get(i).createRemoteAppAnimation();
             if (target != null) {
                 targets.add(target);
+            } else {
+                mPendingAnimations.remove(i);
             }
         }
         return targets.toArray(new RemoteAnimationTarget[targets.size()]);
@@ -225,10 +231,8 @@
         RemoteAnimationTarget createRemoteAppAnimation() {
             final Task task = mAppWindowToken.getTask();
             final WindowState mainWindow = mAppWindowToken.findMainWindow();
-            if (task == null) {
-                return null;
-            }
-            if (mainWindow == null) {
+            if (task == null || mainWindow == null || mCapturedFinishCallback == null
+                    || mCapturedLeash == null) {
                 return null;
             }
             mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index e5928b1..ba3d091 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -234,6 +234,10 @@
         mService.mAnimationTransferMap.put(mAnimation, this);
     }
 
+    boolean isAnimationStartDelayed() {
+        return mAnimationStartDelayed;
+    }
+
     /**
      * Cancels the animation, and resets the leash.
      *