diff options
8 files changed, 155 insertions, 36 deletions
diff --git a/core/java/android/window/TransitionRequestInfo.java b/core/java/android/window/TransitionRequestInfo.java index edea2978c340..9b10a7ff5d12 100644 --- a/core/java/android/window/TransitionRequestInfo.java +++ b/core/java/android/window/TransitionRequestInfo.java @@ -36,11 +36,17 @@ public final class TransitionRequestInfo implements Parcelable { private final @WindowManager.TransitionType int mType; /** - * If non-null, If non-null, the task containing the activity whose lifecycle change (start or + * If non-null, the task containing the activity whose lifecycle change (start or * finish) has caused this transition to occur. */ private @Nullable ActivityManager.RunningTaskInfo mTriggerTask; + /** + * If non-null, the task containing the pip activity that participates in this + * transition. + */ + private @Nullable ActivityManager.RunningTaskInfo mPipTask; + /** If non-null, a remote-transition associated with the source of this transition. */ private @Nullable RemoteTransition mRemoteTransition; @@ -59,7 +65,8 @@ public final class TransitionRequestInfo implements Parcelable { @WindowManager.TransitionType int type, @Nullable ActivityManager.RunningTaskInfo triggerTask, @Nullable RemoteTransition remoteTransition) { - this(type, triggerTask, remoteTransition, null /* displayChange */, 0 /* flags */); + this(type, triggerTask, null /* pipTask */, + remoteTransition, null /* displayChange */, 0 /* flags */); } /** constructor override */ @@ -68,7 +75,17 @@ public final class TransitionRequestInfo implements Parcelable { @Nullable ActivityManager.RunningTaskInfo triggerTask, @Nullable RemoteTransition remoteTransition, int flags) { - this(type, triggerTask, remoteTransition, null /* displayChange */, flags); + this(type, triggerTask, null /* pipTask */, + remoteTransition, null /* displayChange */, flags); + } + + public TransitionRequestInfo( + @WindowManager.TransitionType int type, + @Nullable ActivityManager.RunningTaskInfo triggerTask, + @Nullable RemoteTransition remoteTransition, + @Nullable TransitionRequestInfo.DisplayChange displayChange, + int flags) { + this(type, triggerTask, null /* pipTask */, remoteTransition, displayChange, flags); } /** Requested change to a display. */ @@ -246,7 +263,7 @@ public final class TransitionRequestInfo implements Parcelable { }; @DataClass.Generated( - time = 1691627678294L, + time = 1693425051905L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java", inputSignatures = "private final int mDisplayId\nprivate @android.annotation.Nullable android.graphics.Rect mStartAbsBounds\nprivate @android.annotation.Nullable android.graphics.Rect mEndAbsBounds\nprivate int mStartRotation\nprivate int mEndRotation\nprivate boolean mPhysicalDisplayChanged\nclass DisplayChange extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genBuilder=false, genConstructor=false)") @@ -283,6 +300,9 @@ public final class TransitionRequestInfo implements Parcelable { * @param triggerTask * If non-null, If non-null, the task containing the activity whose lifecycle change (start or * finish) has caused this transition to occur. + * @param pipTask + * If non-null, If non-null, the task containing the activity whose lifecycle change (start or + * finish) has caused this transition to occur. * @param remoteTransition * If non-null, a remote-transition associated with the source of this transition. * @param displayChange @@ -296,6 +316,7 @@ public final class TransitionRequestInfo implements Parcelable { public TransitionRequestInfo( @WindowManager.TransitionType int type, @Nullable ActivityManager.RunningTaskInfo triggerTask, + @Nullable ActivityManager.RunningTaskInfo pipTask, @Nullable RemoteTransition remoteTransition, @Nullable TransitionRequestInfo.DisplayChange displayChange, int flags) { @@ -303,6 +324,7 @@ public final class TransitionRequestInfo implements Parcelable { com.android.internal.util.AnnotationValidations.validate( WindowManager.TransitionType.class, null, mType); this.mTriggerTask = triggerTask; + this.mPipTask = pipTask; this.mRemoteTransition = remoteTransition; this.mDisplayChange = displayChange; this.mFlags = flags; @@ -319,7 +341,7 @@ public final class TransitionRequestInfo implements Parcelable { } /** - * If non-null, If non-null, the task containing the activity whose lifecycle change (start or + * If non-null, the task containing the activity whose lifecycle change (start or * finish) has caused this transition to occur. */ @DataClass.Generated.Member @@ -328,6 +350,15 @@ public final class TransitionRequestInfo implements Parcelable { } /** + * If non-null, the task containing the pip activity that participates in this + * transition. + */ + @DataClass.Generated.Member + public @Nullable ActivityManager.RunningTaskInfo getPipTask() { + return mPipTask; + } + + /** * If non-null, a remote-transition associated with the source of this transition. */ @DataClass.Generated.Member @@ -354,7 +385,7 @@ public final class TransitionRequestInfo implements Parcelable { } /** - * If non-null, If non-null, the task containing the activity whose lifecycle change (start or + * If non-null, the task containing the activity whose lifecycle change (start or * finish) has caused this transition to occur. */ @DataClass.Generated.Member @@ -364,6 +395,16 @@ public final class TransitionRequestInfo implements Parcelable { } /** + * If non-null, the task containing the pip activity that participates in this + * transition. + */ + @DataClass.Generated.Member + public @android.annotation.NonNull TransitionRequestInfo setPipTask(@android.annotation.NonNull ActivityManager.RunningTaskInfo value) { + mPipTask = value; + return this; + } + + /** * If non-null, a remote-transition associated with the source of this transition. */ @DataClass.Generated.Member @@ -392,6 +433,7 @@ public final class TransitionRequestInfo implements Parcelable { return "TransitionRequestInfo { " + "type = " + mType + ", " + "triggerTask = " + mTriggerTask + ", " + + "pipTask = " + mPipTask + ", " + "remoteTransition = " + mRemoteTransition + ", " + "displayChange = " + mDisplayChange + ", " + "flags = " + mFlags + @@ -406,11 +448,13 @@ public final class TransitionRequestInfo implements Parcelable { byte flg = 0; if (mTriggerTask != null) flg |= 0x2; - if (mRemoteTransition != null) flg |= 0x4; - if (mDisplayChange != null) flg |= 0x8; + if (mPipTask != null) flg |= 0x4; + if (mRemoteTransition != null) flg |= 0x8; + if (mDisplayChange != null) flg |= 0x10; dest.writeByte(flg); dest.writeInt(mType); if (mTriggerTask != null) dest.writeTypedObject(mTriggerTask, flags); + if (mPipTask != null) dest.writeTypedObject(mPipTask, flags); if (mRemoteTransition != null) dest.writeTypedObject(mRemoteTransition, flags); if (mDisplayChange != null) dest.writeTypedObject(mDisplayChange, flags); dest.writeInt(mFlags); @@ -430,14 +474,16 @@ public final class TransitionRequestInfo implements Parcelable { byte flg = in.readByte(); int type = in.readInt(); ActivityManager.RunningTaskInfo triggerTask = (flg & 0x2) == 0 ? null : (ActivityManager.RunningTaskInfo) in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR); - RemoteTransition remoteTransition = (flg & 0x4) == 0 ? null : (RemoteTransition) in.readTypedObject(RemoteTransition.CREATOR); - TransitionRequestInfo.DisplayChange displayChange = (flg & 0x8) == 0 ? null : (TransitionRequestInfo.DisplayChange) in.readTypedObject(TransitionRequestInfo.DisplayChange.CREATOR); + ActivityManager.RunningTaskInfo pipTask = (flg & 0x4) == 0 ? null : (ActivityManager.RunningTaskInfo) in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR); + RemoteTransition remoteTransition = (flg & 0x8) == 0 ? null : (RemoteTransition) in.readTypedObject(RemoteTransition.CREATOR); + TransitionRequestInfo.DisplayChange displayChange = (flg & 0x10) == 0 ? null : (TransitionRequestInfo.DisplayChange) in.readTypedObject(TransitionRequestInfo.DisplayChange.CREATOR); int flags = in.readInt(); this.mType = type; com.android.internal.util.AnnotationValidations.validate( WindowManager.TransitionType.class, null, mType); this.mTriggerTask = triggerTask; + this.mPipTask = pipTask; this.mRemoteTransition = remoteTransition; this.mDisplayChange = displayChange; this.mFlags = flags; @@ -460,10 +506,10 @@ public final class TransitionRequestInfo implements Parcelable { }; @DataClass.Generated( - time = 1691627678327L, + time = 1693425051928L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java", - inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.window.RemoteTransition mRemoteTransition\nprivate @android.annotation.Nullable android.window.TransitionRequestInfo.DisplayChange mDisplayChange\nprivate final int mFlags\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)") + inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mPipTask\nprivate @android.annotation.Nullable android.window.RemoteTransition mRemoteTransition\nprivate @android.annotation.Nullable android.window.TransitionRequestInfo.DisplayChange mDisplayChange\nprivate final int mFlags\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)") @Deprecated private void __metadata() {} diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 6057852a7e4b..f72cc1d9f3d2 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -2401,6 +2401,12 @@ "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, + "61363198": { + "message": "Auto-PIP allowed, requesting PIP mode via requestStartTransition(): %s, willAutoPip: %b", + "level": "DEBUG", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" + }, "74885950": { "message": "Waiting for top state to be released by %s", "level": "VERBOSE", @@ -2413,12 +2419,6 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "90764070": { - "message": "Could not report token removal to the window token client.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowContextListenerController.java" - }, "95216706": { "message": "hideIme target: %s ", "level": "DEBUG", @@ -4333,12 +4333,6 @@ "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, - "1948483534": { - "message": "Could not report config changes to the window token client.", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowContextListenerController.java" - }, "1964565370": { "message": "Starting remote animation", "level": "INFO", diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 60854885d5bb..590dbda19c67 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -566,8 +566,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean forceNewConfig; // force re-create with new config next time boolean supportsEnterPipOnTaskSwitch; // This flag is set by the system to indicate that the // activity can enter picture in picture while pausing (only when switching to another task) + // The PiP params used when deferring the entering of picture-in-picture. PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build(); - // The PiP params used when deferring the entering of picture-in-picture. boolean shouldDockBigOverlays; int launchCount; // count of launches since last state long lastLaunchTime; // time of last launch of this activity @@ -1733,6 +1733,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAnimatingActivityRegistry = registry; } + boolean canAutoEnterPip() { + // beforeStopping=false since the actual pip-ing will take place after startPausing() + final boolean activityCanPip = checkEnterPictureInPictureState( + "startActivityUnchecked", false /* beforeStopping */); + + // check if this activity is about to auto-enter pip + return activityCanPip && pictureInPictureArgs != null + && pictureInPictureArgs.isAutoEnterEnabled(); + } + /** * Sets {@link #mLastParentBeforePip} to the current parent Task, it's caller's job to ensure * {@link #getTask()} is set before this is called. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 42c363085017..52f8997ba76a 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -314,6 +314,8 @@ import java.util.Set; public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private static final String GRAMMATICAL_GENDER_PROPERTY = "persist.sys.grammatical_gender"; private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityTaskManagerService" : TAG_ATM; + private static final String ENABLE_PIP2_IMPLEMENTATION = + "persist.wm.debug.enable_pip2_implementation"; static final String TAG_ROOT_TASK = TAG + POSTFIX_ROOT_TASK; static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; @@ -3608,6 +3610,28 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } + /** + * Prepare to enter PiP mode after {@link TransitionController#requestStartTransition}. + * + * @param r activity auto entering pip + * @return true if the activity is about to auto-enter pip or is already in pip mode. + */ + boolean prepareAutoEnterPictureAndPictureMode(ActivityRecord r) { + // If the activity is already in picture in picture mode, then just return early + if (r.inPinnedWindowingMode()) { + return true; + } + + if (r.canAutoEnterPip() && getTransitionController().getCollectingTransition() != null) { + // This will be used later to construct TransitionRequestInfo for Shell to resolve. + // It will also be passed into a direct moveActivityToPinnedRootTask() call via + // startTransition() + getTransitionController().getCollectingTransition().setPipActivity(r); + return true; + } + return false; + } + boolean enterPictureInPictureMode(@NonNull ActivityRecord r, @NonNull PictureInPictureParams params, boolean fromClient) { return enterPictureInPictureMode(r, params, fromClient, false /* isAutoEnter */); @@ -7164,4 +7188,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ActivityTaskManagerService.this.unregisterTaskStackListener(listener); } } + + static boolean isPip2ExperimentEnabled() { + return SystemProperties.getBoolean(ENABLE_PIP2_IMPLEMENTATION, false); + } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 387a8767ced3..fbbba5a2edec 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -5107,7 +5107,6 @@ class Task extends TaskFragment { void startActivityLocked(ActivityRecord r, @Nullable Task topTask, boolean newTask, boolean isTaskSwitch, ActivityOptions options, @Nullable ActivityRecord sourceRecord) { - final ActivityRecord pipCandidate = findEnterPipOnTaskSwitchCandidate(topTask); Task rTask = r.getTask(); final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront(); final boolean isOrhasTask = rTask == this || hasChild(rTask); @@ -5171,8 +5170,10 @@ class Task extends TaskFragment { // supporting picture-in-picture while pausing only if the starting activity // would not be considered an overlay on top of the current activity // (eg. not fullscreen, or the assistant) - enableEnterPipOnTaskSwitch(pipCandidate, - null /* toFrontTask */, r, options); + if (!ActivityTaskManagerService.isPip2ExperimentEnabled()) { + final ActivityRecord pipCandidate = findEnterPipOnTaskSwitchCandidate(topTask); + enableEnterPipOnTaskSwitch(pipCandidate, null /* toFrontTask */, r, options); + } } boolean doShow = true; if (newTask) { @@ -5245,7 +5246,7 @@ class Task extends TaskFragment { * enter PiP while it is pausing (if supported). Only one of {@param toFrontTask} or * {@param toFrontActivity} should be set. */ - private static void enableEnterPipOnTaskSwitch(@Nullable ActivityRecord pipCandidate, + static void enableEnterPipOnTaskSwitch(@Nullable ActivityRecord pipCandidate, @Nullable Task toFrontTask, @Nullable ActivityRecord toFrontActivity, @Nullable ActivityOptions opts) { if (pipCandidate == null) { diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 6dc896a92e52..10efb3bee8ef 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -1643,7 +1643,17 @@ class TaskFragment extends WindowContainer<WindowContainer> { // next activity. final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState( "shouldAutoPipWhilePausing", userLeaving); - if (userLeaving && resumingOccludesParent && lastResumedCanPip + + if (ActivityTaskManagerService.isPip2ExperimentEnabled()) { + // If a new task is being launched, then mark the existing top activity as + // supporting picture-in-picture while pausing only if the starting activity + // would not be considered an overlay on top of the current activity + // (eg. not fullscreen, or the assistant) + Task.enableEnterPipOnTaskSwitch(prev, resuming.getTask(), + resuming, resuming.getOptions()); + } + if (prev.supportsEnterPipOnTaskSwitch && userLeaving + && resumingOccludesParent && lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterEnabled()) { shouldAutoPip = true; } else if (!lastResumedCanPip) { @@ -1656,7 +1666,12 @@ class TaskFragment extends WindowContainer<WindowContainer> { } if (prev.attachedToProcess()) { - if (shouldAutoPip) { + if (shouldAutoPip && ActivityTaskManagerService.isPip2ExperimentEnabled()) { + prev.mPauseSchedulePendingForPip = true; + boolean willAutoPip = mAtmService.prepareAutoEnterPictureAndPictureMode(prev); + ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, requesting PIP mode " + + "via requestStartTransition(): %s, willAutoPip: %b", prev, willAutoPip); + } else if (shouldAutoPip) { prev.mPauseSchedulePendingForPip = true; boolean didAutoPip = mAtmService.enterPictureInPictureMode( prev, prev.pictureInPictureArgs, false /* fromClient */); diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 81f91c739bc3..218580b04462 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -174,6 +174,8 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { private final Token mToken; private IApplicationThread mRemoteAnimApp; + private @Nullable ActivityRecord mPipActivity; + /** Only use for clean-up after binder death! */ private SurfaceControl.Transaction mStartTransaction = null; private SurfaceControl.Transaction mFinishTransaction = null; @@ -509,6 +511,21 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } /** + * Set the pip-able activity participating in this transition. + * @param pipActivity activity about to enter pip + */ + void setPipActivity(@Nullable ActivityRecord pipActivity) { + mPipActivity = pipActivity; + } + + /** + * @return pip-able activity participating in this transition. + */ + @Nullable ActivityRecord getPipActivity() { + return mPipActivity; + } + + /** * Only set flag to the parent tasks and activity itself. */ private void setTransientLaunchToChanges(@NonNull WindowContainer wc) { diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index e4b9571d0028..b53f1f39b8c2 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -705,13 +705,21 @@ class TransitionController { try { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Requesting StartTransition: %s", transition); - ActivityManager.RunningTaskInfo info = null; + ActivityManager.RunningTaskInfo startTaskInfo = null; + ActivityManager.RunningTaskInfo pipTaskInfo = null; if (startTask != null) { - info = new ActivityManager.RunningTaskInfo(); - startTask.fillTaskInfo(info); + startTaskInfo = startTask.getTaskInfo(); } - final TransitionRequestInfo request = new TransitionRequestInfo( - transition.mType, info, remoteTransition, displayChange, transition.getFlags()); + + // set the pip task in the request if provided + if (mCollectingTransition.getPipActivity() != null) { + pipTaskInfo = mCollectingTransition.getPipActivity().getTask().getTaskInfo(); + } + + final TransitionRequestInfo request = new TransitionRequestInfo(transition.mType, + startTaskInfo, pipTaskInfo, remoteTransition, displayChange, + transition.getFlags()); + transition.mLogger.mRequestTimeNs = SystemClock.elapsedRealtimeNanos(); transition.mLogger.mRequest = request; mTransitionPlayer.requestStartTransition(transition.getToken(), request); |