Notify WM that app is delayed closing due to the possibility of PIP.

WM determines the IME target after it sets up all the app transitions
and handles visiblity. In most cases, this is fine since everything is
set up properly at once. However, in cases where the app can enter PIP,
the transition to close the app is delayed in case the app decides to
enter PIP. In this case AM needs to notify WM of this information so it
can properly calculate the IME target when the app transitions aren't
fully set up.

The specific usecase is the following:
1. App with the ability to enter PIP is open with IME
2. Home is pressed.
3. Launcher is brought to the front, previous app is not yet hidden
since the close is delayed.
4. IME is recalculated and doesn't see any closing app. IME is
targeted to launcher.
5. Prevous app is ready to close.

By this point, the IME was already incorrectly targeting launcher, which
causes the flicker since IME will get set relative to launcher.

Test: Open Chrome with IME. Press home. No flicker.
Change-Id: Ie3553b0a01ad567d8b34c3453ad838b88684e79d
Fixes: 80352830
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index d456f62..3168d7a 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -777,6 +777,13 @@
         }
     }
 
+    /**
+     * See {@link AppWindowContainerController#setWillCloseOrEnterPip(boolean)}
+     */
+    void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
+        getWindowContainerController().setWillCloseOrEnterPip(willCloseOrEnterPip);
+    }
+
     static class Token extends IApplicationToken.Stub {
         private final WeakReference<ActivityRecord> weakActivity;
         private final String name;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3ad461f..29650be 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -134,7 +134,6 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.Trace;
 import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.ArraySet;
@@ -1557,6 +1556,7 @@
         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
 
         if (prev != null) {
+            prev.setWillCloseOrEnterPip(false);
             final boolean wasStopping = prev.isState(STOPPING);
             prev.setState(PAUSED, "completePausedLocked");
             if (prev.finishing) {
@@ -2411,11 +2411,12 @@
         mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
 
         boolean lastResumedCanPip = false;
+        ActivityRecord lastResumed = null;
         final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
         if (lastFocusedStack != null && lastFocusedStack != this) {
             // So, why aren't we using prev here??? See the param comment on the method. prev doesn't
             // represent the last resumed activity. However, the last focus stack does if it isn't null.
-            final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity;
+            lastResumed = lastFocusedStack.mResumedActivity;
             if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) {
                 // The user isn't leaving if this stack is the multi-window mode and the last
                 // focused stack should still be visible.
@@ -2450,6 +2451,9 @@
                 mService.updateLruProcessLocked(next.app, true, null);
             }
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
+            if (lastResumed != null) {
+                lastResumed.setWillCloseOrEnterPip(true);
+            }
             return true;
         } else if (mResumedActivity == next && next.isState(RESUMED)
                 && mStackSupervisor.allResumedActivitiesComplete()) {
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 644e3c3..4f15c5d 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -753,6 +753,21 @@
         return mListener != null && mListener.keyDispatchingTimedOut(reason, windowPid);
     }
 
+    /**
+     * Notifies AWT that this app is waiting to pause in order to determine if it will enter PIP.
+     * This information helps AWT know that the app is in the process of pausing before it gets the
+     * signal on the WM side.
+     */
+    public void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
+        synchronized (mWindowMap) {
+            if (mContainer == null) {
+                return;
+            }
+
+            mContainer.setWillCloseOrEnterPip(willCloseOrEnterPip);
+        }
+    }
+
     @Override
     public String toString() {
         return "AppWindowContainerController{"
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 0ba5a56..e45de45 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -32,12 +32,11 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_UNSET;
-import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
+
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
@@ -257,6 +256,13 @@
     private RemoteAnimationDefinition mRemoteAnimationDefinition;
     private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
 
+    /**
+     * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
+     * to help AWT know that the app is in the process of closing but hasn't yet started closing on
+     * the WM side.
+     */
+    private boolean mWillCloseOrEnterPip;
+
     AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
             DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
             boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
@@ -2235,4 +2241,21 @@
     boolean isLetterboxOverlappingWith(Rect rect) {
         return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
     }
+
+    /**
+     * Sets if this AWT is in the process of closing or entering PIP.
+     * {@link #mWillCloseOrEnterPip}}
+     */
+    void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
+        mWillCloseOrEnterPip = willCloseOrEnterPip;
+    }
+
+    /**
+     * Returns whether this AWT is considered closing. Conditions are either
+     * 1. Is this app animating and was requested to be hidden
+     * 2. App is delayed closing since it might enter PIP.
+     */
+    boolean isClosingOrEnteringPip() {
+        return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b59e728..b0e6208 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2510,7 +2510,7 @@
         // since its above other stacks in the ordering list, but layed out below the others.
         if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
                 && (target == null || target.isActivityTypeHome())) {
-            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "New target is home while current target is"
+            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "New target is home while current target is "
                     + "closing, not changing");
             return curTarget;
         }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index febc1a9..bee70a0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -20,8 +20,6 @@
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.AppOpsManager.OP_NONE;
-import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
-import static android.app.AppOpsManager.OP_TOAST_WINDOW;
 import static android.os.PowerManager.DRAW_WAKE_LOCK;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
@@ -2737,8 +2735,7 @@
     }
 
     boolean isClosing() {
-        return mAnimatingExit || (mAppToken != null && mAppToken.isAnimating()
-                && mAppToken.hiddenRequested);
+        return mAnimatingExit || (mAppToken != null && mAppToken.isClosingOrEnteringPip());
     }
 
     void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {