Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +42 −25 Original line number Diff line number Diff line Loading @@ -173,14 +173,25 @@ public class PipTransition extends PipTransitionController { return true; } // The previous PIP Task is no longer in PIP, but this is not an exit transition (This can // happen when a new activity requests enter PIP). In this case, we just show this Task in // its end state, and play other animation as normal. final TransitionInfo.Change currentPipChange = findCurrentPipChange(info); if (currentPipChange != null && currentPipChange.getTaskInfo().getWindowingMode() != WINDOWING_MODE_PINNED) { resetPrevPip(currentPipChange, startTransaction); } // Entering PIP. if (isEnteringPip(info, mCurrentPipTaskToken)) { return startEnterAnimation(info, startTransaction, finishTransaction, finishCallback); } // For transition that we don't animate, we may need to update the PIP surface, otherwise it // will be reset after the transition. updatePipForUnhandledTransition(info, startTransaction, finishTransaction); // For transition that we don't animate, but contains the PIP leash, we need to update the // PIP surface, otherwise it will be reset after the transition. if (currentPipChange != null) { updatePipForUnhandledTransition(currentPipChange, startTransaction, finishTransaction); } return false; } Loading Loading @@ -571,20 +582,28 @@ public class PipTransition extends PipTransitionController { finishCallback.onTransitionFinished(null, null); } private void updatePipForUnhandledTransition(@NonNull TransitionInfo info, private void resetPrevPip(@NonNull TransitionInfo.Change prevPipChange, @NonNull SurfaceControl.Transaction startTransaction) { final SurfaceControl leash = prevPipChange.getLeash(); final Rect bounds = prevPipChange.getEndAbsBounds(); final Point offset = prevPipChange.getEndRelOffset(); bounds.offset(-offset.x, -offset.y); startTransaction.setWindowCrop(leash, null); startTransaction.setMatrix(leash, 1, 0, 0, 1); startTransaction.setCornerRadius(leash, 0); startTransaction.setPosition(leash, bounds.left, bounds.top); mCurrentPipTaskToken = null; mPipOrganizer.onExitPipFinished(prevPipChange.getTaskInfo()); } private void updatePipForUnhandledTransition(@NonNull TransitionInfo.Change pipChange, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction) { if (mCurrentPipTaskToken == null) { return; } for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); if (!mCurrentPipTaskToken.equals(change.getContainer())) { continue; } // When the PIP window is visible and being a part of the transition, such as display // rotation, we need to update its bounds and rounded corner. final SurfaceControl leash = change.getLeash(); final SurfaceControl leash = pipChange.getLeash(); final Rect destBounds = mPipBoundsState.getBounds(); final boolean isInPip = mPipTransitionState.isInPip(); mSurfaceTransactionHelper Loading @@ -593,8 +612,6 @@ public class PipTransition extends PipTransitionController { mSurfaceTransactionHelper .crop(finishTransaction, leash, destBounds) .round(finishTransaction, leash, isInPip); break; } } private void finishResizeForMenu(Rect destinationBounds) { Loading services/core/java/com/android/server/wm/RootWindowContainer.java +19 −6 Original line number Diff line number Diff line Loading @@ -2051,19 +2051,25 @@ class RootWindowContainer extends WindowContainer<DisplayContent> try { final Task task = r.getTask(); final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask(); // This will change the root pinned task's windowing mode to its original mode, ensuring // we only have one root task that is in pinned mode. // If the activity in current PIP task needs to be moved back to the parent Task of next // PIP activity, we can't use that parent Task as the next PIP Task. // Because we need to start the Shell transition from the root Task, we delay to dismiss // the current PIP task until root Task is ready. boolean origPipWillBeMovedToTask = false; final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask(); if (rootPinnedTask != null) { rootPinnedTask.dismissPip(); final ActivityRecord topPipActivity = rootPinnedTask.getTopMostActivity(); if (topPipActivity != null && topPipActivity.getLastParentBeforePip() == task) { origPipWillBeMovedToTask = true; } } // Set a transition to ensure that we don't immediately try and update the visibility // of the activity entering PIP r.getDisplayContent().prepareAppTransition(TRANSIT_NONE); final boolean singleActivity = task.getChildCount() == 1; final boolean singleActivity = task.getChildCount() == 1 && !origPipWillBeMovedToTask; final Task rootTask; if (singleActivity) { rootTask = task; Loading Loading @@ -2117,7 +2123,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> final ActivityRecord oldTopActivity = task.getTopMostActivity(); if (oldTopActivity != null && oldTopActivity.isState(STOPPED) && task.getDisplayContent().mAppTransition.containsTransitRequest( TRANSIT_TO_BACK)) { TRANSIT_TO_BACK) && !origPipWillBeMovedToTask) { task.getDisplayContent().mClosingApps.add(oldTopActivity); oldTopActivity.mRequestForceTransition = true; } Loading @@ -2133,6 +2139,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } rootTask.mTransitionController.requestTransitionIfNeeded(TRANSIT_PIP, rootTask); // This will change the root pinned task's windowing mode to its original mode, ensuring // we only have one root task that is in pinned mode. if (rootPinnedTask != null) { rootTask.mTransitionController.collect(rootPinnedTask); rootPinnedTask.dismissPip(); } // Defer the windowing mode change until after the transition to prevent the activity // from doing work and changing the activity visuals while animating // TODO(task-org): Figure-out more structured way to do this long term. Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +42 −25 Original line number Diff line number Diff line Loading @@ -173,14 +173,25 @@ public class PipTransition extends PipTransitionController { return true; } // The previous PIP Task is no longer in PIP, but this is not an exit transition (This can // happen when a new activity requests enter PIP). In this case, we just show this Task in // its end state, and play other animation as normal. final TransitionInfo.Change currentPipChange = findCurrentPipChange(info); if (currentPipChange != null && currentPipChange.getTaskInfo().getWindowingMode() != WINDOWING_MODE_PINNED) { resetPrevPip(currentPipChange, startTransaction); } // Entering PIP. if (isEnteringPip(info, mCurrentPipTaskToken)) { return startEnterAnimation(info, startTransaction, finishTransaction, finishCallback); } // For transition that we don't animate, we may need to update the PIP surface, otherwise it // will be reset after the transition. updatePipForUnhandledTransition(info, startTransaction, finishTransaction); // For transition that we don't animate, but contains the PIP leash, we need to update the // PIP surface, otherwise it will be reset after the transition. if (currentPipChange != null) { updatePipForUnhandledTransition(currentPipChange, startTransaction, finishTransaction); } return false; } Loading Loading @@ -571,20 +582,28 @@ public class PipTransition extends PipTransitionController { finishCallback.onTransitionFinished(null, null); } private void updatePipForUnhandledTransition(@NonNull TransitionInfo info, private void resetPrevPip(@NonNull TransitionInfo.Change prevPipChange, @NonNull SurfaceControl.Transaction startTransaction) { final SurfaceControl leash = prevPipChange.getLeash(); final Rect bounds = prevPipChange.getEndAbsBounds(); final Point offset = prevPipChange.getEndRelOffset(); bounds.offset(-offset.x, -offset.y); startTransaction.setWindowCrop(leash, null); startTransaction.setMatrix(leash, 1, 0, 0, 1); startTransaction.setCornerRadius(leash, 0); startTransaction.setPosition(leash, bounds.left, bounds.top); mCurrentPipTaskToken = null; mPipOrganizer.onExitPipFinished(prevPipChange.getTaskInfo()); } private void updatePipForUnhandledTransition(@NonNull TransitionInfo.Change pipChange, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction) { if (mCurrentPipTaskToken == null) { return; } for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); if (!mCurrentPipTaskToken.equals(change.getContainer())) { continue; } // When the PIP window is visible and being a part of the transition, such as display // rotation, we need to update its bounds and rounded corner. final SurfaceControl leash = change.getLeash(); final SurfaceControl leash = pipChange.getLeash(); final Rect destBounds = mPipBoundsState.getBounds(); final boolean isInPip = mPipTransitionState.isInPip(); mSurfaceTransactionHelper Loading @@ -593,8 +612,6 @@ public class PipTransition extends PipTransitionController { mSurfaceTransactionHelper .crop(finishTransaction, leash, destBounds) .round(finishTransaction, leash, isInPip); break; } } private void finishResizeForMenu(Rect destinationBounds) { Loading
services/core/java/com/android/server/wm/RootWindowContainer.java +19 −6 Original line number Diff line number Diff line Loading @@ -2051,19 +2051,25 @@ class RootWindowContainer extends WindowContainer<DisplayContent> try { final Task task = r.getTask(); final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask(); // This will change the root pinned task's windowing mode to its original mode, ensuring // we only have one root task that is in pinned mode. // If the activity in current PIP task needs to be moved back to the parent Task of next // PIP activity, we can't use that parent Task as the next PIP Task. // Because we need to start the Shell transition from the root Task, we delay to dismiss // the current PIP task until root Task is ready. boolean origPipWillBeMovedToTask = false; final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask(); if (rootPinnedTask != null) { rootPinnedTask.dismissPip(); final ActivityRecord topPipActivity = rootPinnedTask.getTopMostActivity(); if (topPipActivity != null && topPipActivity.getLastParentBeforePip() == task) { origPipWillBeMovedToTask = true; } } // Set a transition to ensure that we don't immediately try and update the visibility // of the activity entering PIP r.getDisplayContent().prepareAppTransition(TRANSIT_NONE); final boolean singleActivity = task.getChildCount() == 1; final boolean singleActivity = task.getChildCount() == 1 && !origPipWillBeMovedToTask; final Task rootTask; if (singleActivity) { rootTask = task; Loading Loading @@ -2117,7 +2123,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> final ActivityRecord oldTopActivity = task.getTopMostActivity(); if (oldTopActivity != null && oldTopActivity.isState(STOPPED) && task.getDisplayContent().mAppTransition.containsTransitRequest( TRANSIT_TO_BACK)) { TRANSIT_TO_BACK) && !origPipWillBeMovedToTask) { task.getDisplayContent().mClosingApps.add(oldTopActivity); oldTopActivity.mRequestForceTransition = true; } Loading @@ -2133,6 +2139,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } rootTask.mTransitionController.requestTransitionIfNeeded(TRANSIT_PIP, rootTask); // This will change the root pinned task's windowing mode to its original mode, ensuring // we only have one root task that is in pinned mode. if (rootPinnedTask != null) { rootTask.mTransitionController.collect(rootPinnedTask); rootPinnedTask.dismissPip(); } // Defer the windowing mode change until after the transition to prevent the activity // from doing work and changing the activity visuals while animating // TODO(task-org): Figure-out more structured way to do this long term. Loading