Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +18 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.view.SurfaceControl; import android.view.WindowManager; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; Loading Loading @@ -312,6 +313,23 @@ public abstract class PipTransitionController implements Transitions.TransitionH return false; } /** * @return a change representing a config-at-end activity for a given parent. */ @Nullable public TransitionInfo.Change getDeferConfigActivityChange(TransitionInfo info, @android.annotation.NonNull WindowContainerToken parent) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getTaskInfo() == null && change.hasFlags(TransitionInfo.FLAG_CONFIG_AT_END) && change.getParent() != null && change.getParent().equals(parent)) { return change; } } return null; } /** Whether a particular package is same as current pip package. */ public boolean isPackageActiveInPip(@Nullable String packageName) { // No-op, to be handled differently in PIP1 and PIP2 Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +28 −13 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_PIP; Loading @@ -30,6 +31,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP; import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP; import static com.android.wm.shell.transition.Transitions.TRANSIT_RESIZE_PIP; import static com.android.wm.shell.transition.Transitions.transitTypeToString; import android.animation.ValueAnimator; import android.annotation.NonNull; Loading @@ -44,6 +46,7 @@ import android.os.Bundle; import android.os.IBinder; import android.view.Surface; import android.view.SurfaceControl; import android.view.WindowManager; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerToken; Loading Loading @@ -281,6 +284,31 @@ public class PipTransition extends PipTransitionController implements return false; } @Override public boolean isEnteringPip(@NonNull TransitionInfo.Change change, @WindowManager.TransitionType int transitType) { if (change.getTaskInfo() != null && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_PINNED) { // TRANSIT_TO_FRONT, though uncommon with triggering PiP, should semantically also // be allowed to animate if the task in question is pinned already - see b/308054074. if (transitType == TRANSIT_PIP || transitType == TRANSIT_OPEN || transitType == TRANSIT_TO_FRONT) { return true; } // This can happen if the request to enter PIP happens when we are collecting for // another transition, such as TRANSIT_CHANGE (display rotation). if (transitType == TRANSIT_CHANGE) { return true; } // Please file a bug to handle the unexpected transition type. android.util.Slog.e(TAG, "Found new PIP in transition with mis-matched type=" + transitTypeToString(transitType), new Throwable()); } return false; } @Override public void end() { if (mTransitionAnimator != null && mTransitionAnimator.isRunning()) { Loading Loading @@ -661,19 +689,6 @@ public class PipTransition extends PipTransitionController implements return null; } @Nullable private TransitionInfo.Change getDeferConfigActivityChange(TransitionInfo info, @NonNull WindowContainerToken parent) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getTaskInfo() == null && change.hasFlags(TransitionInfo.FLAG_CONFIG_AT_END) && change.getParent() != null && change.getParent().equals(parent)) { return change; } } return null; } @Nullable private TransitionInfo.Change getChangeByToken(TransitionInfo info, WindowContainerToken token) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +1 −0 Original line number Diff line number Diff line Loading @@ -287,6 +287,7 @@ public class DefaultMixedHandler implements MixedTransitionHandler, MixedTransition.TYPE_ENTER_PIP_FROM_ACTIVITY_EMBEDDING, transition)); // Postpone transition splitting to later. WindowContainerTransaction out = new WindowContainerTransaction(); mPipHandler.augmentRequest(transition, request, out); return out; } else if (request.getRemoteTransition() != null && TransitionUtil.isOpeningType(request.getType()) Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java +22 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.transition; import static android.view.WindowManager.TRANSIT_PIP; import static android.view.WindowManager.TRANSIT_TO_BACK; import static com.android.wm.shell.transition.DefaultMixedHandler.subCopy; Loading @@ -37,6 +38,8 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.splitscreen.StageCoordinator; import com.android.wm.shell.unfold.UnfoldTransitionHandler; import java.util.List; class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { private final UnfoldTransitionHandler mUnfoldHandler; private final ActivityEmbeddingController mActivityEmbeddingController; Loading Loading @@ -127,6 +130,13 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { } } TransitionInfo.Change pipActivityChange = null; if (pipChange != null) { pipActivityChange = mPipHandler.getDeferConfigActivityChange( info, pipChange.getContainer()); everythingElse.getChanges().remove(pipActivityChange); } final Transitions.TransitionFinishCallback finishCB = (wct) -> { --mInFlightSubAnimations; joinFinishArgs(wct); Loading @@ -139,13 +149,23 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { return false; } // PIP window should always be on the highest Z order. if (pipChange != null) { if (pipChange != null && pipActivityChange == null) { // We are operating on a single PiP task for the enter animation here. mInFlightSubAnimations = 2; // PIP window should always be on the highest Z order. mPipHandler.startEnterAnimation( pipChange, startTransaction.setLayer(pipChange.getLeash(), Integer.MAX_VALUE), finishTransaction, finishCB); } else if (pipActivityChange != null) { // If there is both a PiP task and a PiP config-at-end activity change, // put them into a separate TransitionInfo, and send to be animated as TRANSIT_PIP. mInFlightSubAnimations = 2; TransitionInfo pipInfo = subCopy(info, TRANSIT_PIP, false /* withChanges */); pipInfo.getChanges().addAll(List.of(pipChange, pipActivityChange)); mPipHandler.startAnimation(mTransition, pipInfo, startTransaction.setLayer(pipChange.getLeash(), Integer.MAX_VALUE), finishTransaction, finishCB); } else { mInFlightSubAnimations = 1; } Loading services/core/java/com/android/server/wm/ActivityTaskManagerService.java +6 −0 Original line number Diff line number Diff line Loading @@ -3794,6 +3794,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { r.setPictureInPictureParams(params); enterPipTransition.setPipActivity(r); r.mAutoEnteringPip = isAutoEnter; if (r.getTaskFragment() != null && r.getTaskFragment().isEmbeddedWithBoundsOverride() && enterPipTransition != null) { enterPipTransition.addFlag(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY); } getTransitionController().startCollectOrQueue(enterPipTransition, (deferred) -> { getTransitionController().requestStartTransition(enterPipTransition, r.getTask(), null /* remoteTransition */, null /* displayChange */); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +18 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.view.SurfaceControl; import android.view.WindowManager; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; Loading Loading @@ -312,6 +313,23 @@ public abstract class PipTransitionController implements Transitions.TransitionH return false; } /** * @return a change representing a config-at-end activity for a given parent. */ @Nullable public TransitionInfo.Change getDeferConfigActivityChange(TransitionInfo info, @android.annotation.NonNull WindowContainerToken parent) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getTaskInfo() == null && change.hasFlags(TransitionInfo.FLAG_CONFIG_AT_END) && change.getParent() != null && change.getParent().equals(parent)) { return change; } } return null; } /** Whether a particular package is same as current pip package. */ public boolean isPackageActiveInPip(@Nullable String packageName) { // No-op, to be handled differently in PIP1 and PIP2 Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +28 −13 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_PIP; Loading @@ -30,6 +31,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP; import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP; import static com.android.wm.shell.transition.Transitions.TRANSIT_RESIZE_PIP; import static com.android.wm.shell.transition.Transitions.transitTypeToString; import android.animation.ValueAnimator; import android.annotation.NonNull; Loading @@ -44,6 +46,7 @@ import android.os.Bundle; import android.os.IBinder; import android.view.Surface; import android.view.SurfaceControl; import android.view.WindowManager; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerToken; Loading Loading @@ -281,6 +284,31 @@ public class PipTransition extends PipTransitionController implements return false; } @Override public boolean isEnteringPip(@NonNull TransitionInfo.Change change, @WindowManager.TransitionType int transitType) { if (change.getTaskInfo() != null && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_PINNED) { // TRANSIT_TO_FRONT, though uncommon with triggering PiP, should semantically also // be allowed to animate if the task in question is pinned already - see b/308054074. if (transitType == TRANSIT_PIP || transitType == TRANSIT_OPEN || transitType == TRANSIT_TO_FRONT) { return true; } // This can happen if the request to enter PIP happens when we are collecting for // another transition, such as TRANSIT_CHANGE (display rotation). if (transitType == TRANSIT_CHANGE) { return true; } // Please file a bug to handle the unexpected transition type. android.util.Slog.e(TAG, "Found new PIP in transition with mis-matched type=" + transitTypeToString(transitType), new Throwable()); } return false; } @Override public void end() { if (mTransitionAnimator != null && mTransitionAnimator.isRunning()) { Loading Loading @@ -661,19 +689,6 @@ public class PipTransition extends PipTransitionController implements return null; } @Nullable private TransitionInfo.Change getDeferConfigActivityChange(TransitionInfo info, @NonNull WindowContainerToken parent) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getTaskInfo() == null && change.hasFlags(TransitionInfo.FLAG_CONFIG_AT_END) && change.getParent() != null && change.getParent().equals(parent)) { return change; } } return null; } @Nullable private TransitionInfo.Change getChangeByToken(TransitionInfo info, WindowContainerToken token) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +1 −0 Original line number Diff line number Diff line Loading @@ -287,6 +287,7 @@ public class DefaultMixedHandler implements MixedTransitionHandler, MixedTransition.TYPE_ENTER_PIP_FROM_ACTIVITY_EMBEDDING, transition)); // Postpone transition splitting to later. WindowContainerTransaction out = new WindowContainerTransaction(); mPipHandler.augmentRequest(transition, request, out); return out; } else if (request.getRemoteTransition() != null && TransitionUtil.isOpeningType(request.getType()) Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java +22 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.transition; import static android.view.WindowManager.TRANSIT_PIP; import static android.view.WindowManager.TRANSIT_TO_BACK; import static com.android.wm.shell.transition.DefaultMixedHandler.subCopy; Loading @@ -37,6 +38,8 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.splitscreen.StageCoordinator; import com.android.wm.shell.unfold.UnfoldTransitionHandler; import java.util.List; class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { private final UnfoldTransitionHandler mUnfoldHandler; private final ActivityEmbeddingController mActivityEmbeddingController; Loading Loading @@ -127,6 +130,13 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { } } TransitionInfo.Change pipActivityChange = null; if (pipChange != null) { pipActivityChange = mPipHandler.getDeferConfigActivityChange( info, pipChange.getContainer()); everythingElse.getChanges().remove(pipActivityChange); } final Transitions.TransitionFinishCallback finishCB = (wct) -> { --mInFlightSubAnimations; joinFinishArgs(wct); Loading @@ -139,13 +149,23 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { return false; } // PIP window should always be on the highest Z order. if (pipChange != null) { if (pipChange != null && pipActivityChange == null) { // We are operating on a single PiP task for the enter animation here. mInFlightSubAnimations = 2; // PIP window should always be on the highest Z order. mPipHandler.startEnterAnimation( pipChange, startTransaction.setLayer(pipChange.getLeash(), Integer.MAX_VALUE), finishTransaction, finishCB); } else if (pipActivityChange != null) { // If there is both a PiP task and a PiP config-at-end activity change, // put them into a separate TransitionInfo, and send to be animated as TRANSIT_PIP. mInFlightSubAnimations = 2; TransitionInfo pipInfo = subCopy(info, TRANSIT_PIP, false /* withChanges */); pipInfo.getChanges().addAll(List.of(pipChange, pipActivityChange)); mPipHandler.startAnimation(mTransition, pipInfo, startTransaction.setLayer(pipChange.getLeash(), Integer.MAX_VALUE), finishTransaction, finishCB); } else { mInFlightSubAnimations = 1; } Loading
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +6 −0 Original line number Diff line number Diff line Loading @@ -3794,6 +3794,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { r.setPictureInPictureParams(params); enterPipTransition.setPipActivity(r); r.mAutoEnteringPip = isAutoEnter; if (r.getTaskFragment() != null && r.getTaskFragment().isEmbeddedWithBoundsOverride() && enterPipTransition != null) { enterPipTransition.addFlag(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY); } getTransitionController().startCollectOrQueue(enterPipTransition, (deferred) -> { getTransitionController().requestStartTransition(enterPipTransition, r.getTask(), null /* remoteTransition */, null /* displayChange */); Loading