Merge "Fix pip bundling" into tm-qpr-dev am: 97b292f627

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18382174

Change-Id: I8051427e16798e7adb225c504e42a3a250060441
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 3e6fa56..494ae97 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -769,6 +769,12 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-1383884640": {
+      "message": " allReady query: used=%b override=%b defer=%d states=[%s]",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/Transition.java"
+    },
     "-1376035390": {
       "message": "No task found",
       "level": "DEBUG",
@@ -2551,12 +2557,6 @@
       "group": "WM_DEBUG_ADD_REMOVE",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
-    "352982444": {
-      "message": " allReady query: used=%b override=%b states=[%s]",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/Transition.java"
-    },
     "355720268": {
       "message": "stopFreezingDisplayLocked: Unfreezing now",
       "level": "DEBUG",
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 6113af4..47aa587 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -737,7 +737,7 @@
             synchronized (mGlobalLock) {
                 final ActivityRecord r = ensureValidPictureInPictureActivityParams(
                         "enterPictureInPictureMode", token, params);
-                return mService.enterPictureInPictureMode(r, params);
+                return mService.enterPictureInPictureMode(r, params, true /* fromClient */);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -868,7 +868,8 @@
         }
 
         if (r.pictureInPictureArgs.isAutoEnterEnabled()) {
-            return mService.enterPictureInPictureMode(r, r.pictureInPictureArgs);
+            return mService.enterPictureInPictureMode(r, r.pictureInPictureArgs,
+                    false /* fromClient */);
         }
 
         try {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 7524825..06242b3 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -95,6 +95,7 @@
 import static com.android.server.am.EventLogTags.writeConfigurationChanged;
 import static com.android.server.wm.ActivityInterceptorCallback.FIRST_ORDERED_ID;
 import static com.android.server.wm.ActivityInterceptorCallback.LAST_ORDERED_ID;
+import static com.android.server.wm.ActivityRecord.State.PAUSING;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ROOT_TASK;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
@@ -3449,10 +3450,12 @@
     /**
      * Puts the given activity in picture in picture mode if possible.
      *
+     * @param fromClient true if this comes from a client call (eg. Activity.enterPip).
      * @return true if the activity is now in picture-in-picture mode, or false if it could not
      * enter picture-in-picture mode.
      */
-    boolean enterPictureInPictureMode(@NonNull ActivityRecord r, PictureInPictureParams params) {
+    boolean enterPictureInPictureMode(@NonNull ActivityRecord r,
+            @NonNull PictureInPictureParams params, boolean fromClient) {
         // If the activity is already in picture in picture mode, then just return early
         if (r.inPinnedWindowingMode()) {
             return true;
@@ -3465,9 +3468,17 @@
             return false;
         }
 
-        // Create a transition for this pip entry. We guarantee that this gets its own transition
-        // by queueing this transition on SyncEngine. This is shared by all the entry paths.
-        final Transition transition = getTransitionController().isShellTransitionsEnabled()
+        // If the app is using legacy-entry (not auto-enter), then we will get a client-request
+        // that was actually a server-request (via pause(userLeaving=true)). This happens when
+        // the app is PAUSING, so detect that case here.
+        boolean originallyFromClient = fromClient
+                && (!r.isState(PAUSING) || params.isAutoEnterEnabled());
+
+        // Create a transition only for this pip entry if it is coming from the app without the
+        // system requesting that the app enter-pip. If the system requested it, that means it
+        // should be part of that transition if possible.
+        final Transition transition =
+                (getTransitionController().isShellTransitionsEnabled() && originallyFromClient)
                 ? new Transition(TRANSIT_PIP, 0 /* flags */,
                         getTransitionController(), mWindowManager.mSyncEngine)
                 : null;
@@ -3498,7 +3509,7 @@
             mActivityClientController.dismissKeyguard(r.token, new KeyguardDismissCallback() {
                 @Override
                 public void onDismissSucceeded() {
-                    if (mWindowManager.mSyncEngine.hasActiveSync()) {
+                    if (transition != null && mWindowManager.mSyncEngine.hasActiveSync()) {
                         ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                                 "Creating Pending Pip-Enter: %s", transition);
                         mWindowManager.mSyncEngine.queueSyncSet(
@@ -3516,7 +3527,7 @@
             }, null /* message */);
         } else {
             // Enter picture in picture immediately otherwise
-            if (mWindowManager.mSyncEngine.hasActiveSync()) {
+            if (transition != null && mWindowManager.mSyncEngine.hasActiveSync()) {
                 ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                         "Creating Pending Pip-Enter: %s", transition);
                 mWindowManager.mSyncEngine.queueSyncSet(
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index c62e859..0395f82 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1533,7 +1533,7 @@
         if (prev.attachedToProcess()) {
             if (shouldAutoPip) {
                 boolean didAutoPip = mAtmService.enterPictureInPictureMode(
-                        prev, prev.pictureInPictureArgs);
+                        prev, prev.pictureInPictureArgs, false /* fromClient */);
                 ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
                         + "directly: %s, didAutoPip: %b", prev, didAutoPip);
             } else {
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index d5acf4f..3fcaa5c 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -54,6 +54,7 @@
 import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
 import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
 
+import static com.android.server.wm.ActivityRecord.State.RESUMED;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
@@ -477,6 +478,58 @@
         mCanPipOnFinish = canPipOnFinish;
     }
 
+    private boolean didCommitTransientLaunch() {
+        if (mTransientLaunches == null) return false;
+        for (int j = 0; j < mTransientLaunches.size(); ++j) {
+            if (mTransientLaunches.keyAt(j).isVisibleRequested()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check if pip-entry is possible after finishing and enter-pip if it is.
+     *
+     * @return true if we are *guaranteed* to enter-pip. This means we return false if there's
+     *         a chance we won't thus legacy-entry (via pause+userLeaving) will return false.
+     */
+    private boolean checkEnterPipOnFinish(@NonNull ActivityRecord ar) {
+        if (!mCanPipOnFinish || !ar.isVisible() || ar.getTask() == null) return false;
+
+        if (ar.pictureInPictureArgs != null && ar.pictureInPictureArgs.isAutoEnterEnabled()) {
+            if (didCommitTransientLaunch()) {
+                // force enable pip-on-task-switch now that we've committed to actually launching
+                // to the transient activity.
+                ar.supportsEnterPipOnTaskSwitch = true;
+            }
+            return mController.mAtm.enterPictureInPictureMode(ar, ar.pictureInPictureArgs,
+                    false /* fromClient */);
+        }
+
+        // Legacy pip-entry (not via isAutoEnterEnabled).
+        boolean canPip = ar.getDeferHidingClient();
+        if (!canPip && didCommitTransientLaunch()) {
+            // force enable pip-on-task-switch now that we've committed to actually launching to the
+            // transient activity, and then recalculate whether we can attempt pip.
+            ar.supportsEnterPipOnTaskSwitch = true;
+            canPip = ar.checkEnterPictureInPictureState(
+                    "finishTransition", true /* beforeStopping */)
+                    && ar.isState(RESUMED);
+        }
+        if (!canPip) return false;
+        try {
+            // Legacy PIP-enter requires pause event with user-leaving.
+            mController.mAtm.mTaskSupervisor.mUserLeaving = true;
+            ar.getTaskFragment().startPausing(false /* uiSleeping */,
+                    null /* resuming */, "finishTransition");
+        } finally {
+            mController.mAtm.mTaskSupervisor.mUserLeaving = false;
+        }
+        // Return false anyway because there's no guarantee that the app will enter pip.
+        return false;
+    }
+
     /**
      * The transition has finished animating and is ready to finalize WM state. This should not
      * be called directly; use {@link TransitionController#finishTransition} instead.
@@ -503,32 +556,9 @@
                 // then doing commitVisibility here would actually be out-of-order and leave the
                 // activity in a bad state.
                 if (!visibleAtTransitionEnd && !ar.isVisibleRequested()) {
-                    boolean commitVisibility = true;
-                    if (mCanPipOnFinish && ar.isVisible() && ar.getTask() != null) {
-                        if (ar.pictureInPictureArgs != null
-                                && ar.pictureInPictureArgs.isAutoEnterEnabled()) {
-                            if (mTransientLaunches != null) {
-                                for (int j = 0; j < mTransientLaunches.size(); ++j) {
-                                    if (mTransientLaunches.keyAt(j).isVisibleRequested()) {
-                                        // force enable pip-on-task-switch now that we've committed
-                                        // to actually launching to the transient activity.
-                                        ar.supportsEnterPipOnTaskSwitch = true;
-                                        break;
-                                    }
-                                }
-                            }
-                            mController.mAtm.enterPictureInPictureMode(ar, ar.pictureInPictureArgs);
-                            // Avoid commit visibility to false here, or else we will get a sudden
-                            // "flash" / surface going invisible for a split second.
-                            commitVisibility = false;
-                        } else if (ar.getDeferHidingClient()) {
-                            // Legacy PIP-enter requires pause event with user-leaving.
-                            mController.mAtm.mTaskSupervisor.mUserLeaving = true;
-                            ar.getTaskFragment().startPausing(false /* uiSleeping */,
-                                    null /* resuming */, "finishTransition");
-                            mController.mAtm.mTaskSupervisor.mUserLeaving = false;
-                        }
-                    }
+                    final boolean commitVisibility = !checkEnterPipOnFinish(ar);
+                    // Avoid commit visibility if entering pip or else we will get a sudden
+                    // "flash" / surface going invisible for a split second.
                     if (commitVisibility) {
                         ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                                 "  Commit activity becoming invisible: %s", ar);
@@ -1720,7 +1750,8 @@
         /** @return true if all tracked subtrees are ready. */
         boolean allReady() {
             ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " allReady query: used=%b "
-                    + "override=%b states=[%s]", mUsed, mReadyOverride, groupsToString());
+                    + "override=%b defer=%d states=[%s]", mUsed, mReadyOverride, mDeferReadyDepth,
+                    groupsToString());
             // If the readiness has never been touched, mUsed will be false. We never want to
             // consider a transition ready if nothing has been reported on it.
             if (!mUsed) return false;