Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +14 −2 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.content.Context; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.common.pip.PipBoundsAlgorithm; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipDisplayLayoutState; Loading @@ -29,6 +31,7 @@ import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.dagger.WMShellBaseModule; import com.android.wm.shell.dagger.WMSingleton; import com.android.wm.shell.pip2.phone.PipController; import com.android.wm.shell.pip2.phone.PipScheduler; import com.android.wm.shell.pip2.phone.PipTransition; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; Loading @@ -52,9 +55,10 @@ public abstract class Pip2Module { @NonNull Transitions transitions, PipBoundsState pipBoundsState, PipBoundsAlgorithm pipBoundsAlgorithm, Optional<PipController> pipController) { Optional<PipController> pipController, @NonNull PipScheduler pipScheduler) { return new PipTransition(shellInit, shellTaskOrganizer, transitions, pipBoundsState, null, pipBoundsAlgorithm); pipBoundsAlgorithm, pipScheduler); } @WMSingleton Loading @@ -73,4 +77,12 @@ public abstract class Pip2Module { pipDisplayLayoutState)); } } @WMSingleton @Provides static PipScheduler providePipScheduler(Context context, PipBoundsState pipBoundsState, @ShellMainThread ShellExecutor mainExecutor) { return new PipScheduler(context, pipBoundsState, mainExecutor); } } libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.pip2.phone; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.view.SurfaceControl; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.pip.PipTransitionController; /** * Scheduler for Shell initiated PiP transitions and animations. */ public class PipScheduler { private static final String TAG = PipScheduler.class.getSimpleName(); private static final String BROADCAST_FILTER = PipScheduler.class.getCanonicalName(); private final Context mContext; private final PipBoundsState mPipBoundsState; private final ShellExecutor mMainExecutor; private PipSchedulerReceiver mSchedulerReceiver; private PipTransitionController mPipTransitionController; // pinned PiP task's WC token @Nullable private WindowContainerToken mPipTaskToken; // pinned PiP task's leash @Nullable private SurfaceControl mPinnedTaskLeash; // the leash of the original task of the PiP activity; // used to synchronize app drawings in the multi-activity case @Nullable private SurfaceControl mOriginalTaskLeash; /** * A temporary broadcast receiver to initiate exit PiP via expand. * This will later be modified to be triggered by the PiP menu. */ private class PipSchedulerReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { scheduleExitPipViaExpand(); } } public PipScheduler(Context context, PipBoundsState pipBoundsState, ShellExecutor mainExecutor) { mContext = context; mPipBoundsState = pipBoundsState; mMainExecutor = mainExecutor; if (PipUtils.isPip2ExperimentEnabled()) { // temporary broadcast receiver to initiate exit PiP via expand mSchedulerReceiver = new PipSchedulerReceiver(); ContextCompat.registerReceiver(mContext, mSchedulerReceiver, new IntentFilter(BROADCAST_FILTER), ContextCompat.RECEIVER_EXPORTED); } } void setPipTransitionController(PipTransitionController pipTransitionController) { mPipTransitionController = pipTransitionController; } void setPinnedTaskLeash(SurfaceControl pinnedTaskLeash) { mPinnedTaskLeash = pinnedTaskLeash; } void setOriginalTaskLeash(SurfaceControl originalTaskLeash) { mOriginalTaskLeash = originalTaskLeash; } void setPipTaskToken(@Nullable WindowContainerToken pipTaskToken) { mPipTaskToken = pipTaskToken; } @Nullable private WindowContainerTransaction getExitPipViaExpandTransaction() { if (mPipTaskToken == null || mPinnedTaskLeash == null) { return null; } WindowContainerTransaction wct = new WindowContainerTransaction(); // final expanded bounds to be inherited from the parent wct.setBounds(mPipTaskToken, null); // if we are hitting a multi-activity case // windowing mode change will reparent to original host task wct.setWindowingMode(mPipTaskToken, WINDOWING_MODE_UNDEFINED); return wct; } /** * Schedules exit PiP via expand transition. */ public void scheduleExitPipViaExpand() { WindowContainerTransaction wct = getExitPipViaExpandTransaction(); if (wct != null) { mMainExecutor.execute(() -> { mPipTransitionController.startExitTransition(TRANSIT_EXIT_PIP, wct, null /* destinationBounds */); }); } } void onExitPip() { mPipTaskToken = null; mPinnedTaskLeash = null; mOriginalTaskLeash = null; } } libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +88 −8 Original line number Diff line number Diff line Loading @@ -16,8 +16,12 @@ package com.android.wm.shell.pip2.phone; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.WindowManager.TRANSIT_OPEN; import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.PictureInPictureParams; Loading @@ -26,6 +30,7 @@ import android.os.IBinder; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.annotation.Nullable; Loading @@ -43,8 +48,15 @@ import com.android.wm.shell.transition.Transitions; * Implementation of transitions for PiP on phone. */ public class PipTransition extends PipTransitionController { private static final String TAG = PipTransition.class.getSimpleName(); private PipScheduler mPipScheduler; @Nullable private WindowContainerToken mPipTaskToken; @Nullable private IBinder mAutoEnterButtonNavTransition; @Nullable private IBinder mExitViaExpandTransition; public PipTransition( @NonNull ShellInit shellInit, Loading @@ -52,9 +64,13 @@ public class PipTransition extends PipTransitionController { @NonNull Transitions transitions, PipBoundsState pipBoundsState, PipMenuController pipMenuController, PipBoundsAlgorithm pipBoundsAlgorithm) { PipBoundsAlgorithm pipBoundsAlgorithm, PipScheduler pipScheduler) { super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController, pipBoundsAlgorithm); mPipScheduler = pipScheduler; mPipScheduler.setPipTransitionController(this); } @Override Loading @@ -64,6 +80,18 @@ public class PipTransition extends PipTransitionController { } } @Override public void startExitTransition(int type, WindowContainerTransaction out, @android.annotation.Nullable Rect destinationBounds) { if (out == null) { return; } IBinder transition = mTransitions.startTransition(type, out, this); if (type == TRANSIT_EXIT_PIP) { mExitViaExpandTransition = transition; } } @Nullable @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, Loading @@ -84,8 +112,18 @@ public class PipTransition extends PipTransitionController { } } @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) {} @Override public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, @Nullable SurfaceControl.Transaction finishT) {} private WindowContainerTransaction getEnterPipTransaction(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { // cache the original task token to check for multi-activity case later final ActivityManager.RunningTaskInfo pipTask = request.getPipTask(); PictureInPictureParams pipParams = pipTask.pictureInPictureParams; mPipBoundsState.setBoundsStateForEntry(pipTask.topActivity, pipTask.topActivityInfo, Loading @@ -93,6 +131,8 @@ public class PipTransition extends PipTransitionController { // calculate the entry bounds and notify core to move task to pinned with final bounds final Rect entryBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); mPipBoundsState.setBounds(entryBounds); WindowContainerTransaction wct = new WindowContainerTransaction(); wct.movePipActivityToPinnedRootTask(pipTask.token, entryBounds); return wct; Loading Loading @@ -121,19 +161,59 @@ public class PipTransition extends PipTransitionController { @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (transition == mAutoEnterButtonNavTransition) { mAutoEnterButtonNavTransition = null; TransitionInfo.Change pipChange = getPipChange(info); if (pipChange == null) { return false; } mPipTaskToken = pipChange.getContainer(); // cache the PiP task token and the relevant leashes mPipScheduler.setPipTaskToken(mPipTaskToken); mPipScheduler.setPinnedTaskLeash(pipChange.getLeash()); // check if we entered PiP from a multi-activity task and set the original task leash final int lastParentTaskId = pipChange.getTaskInfo().lastParentTaskIdBeforePip; final boolean isSingleActivity = lastParentTaskId == INVALID_TASK_ID; mPipScheduler.setOriginalTaskLeash(isSingleActivity ? null : findChangeByTaskId(info, lastParentTaskId).getLeash()); startTransaction.apply(); finishCallback.onTransitionFinished(null); return true; } else if (transition == mExitViaExpandTransition) { mExitViaExpandTransition = null; startTransaction.apply(); finishCallback.onTransitionFinished(null); onExitPip(); return true; } return false; } @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) {} @Nullable private TransitionInfo.Change getPipChange(TransitionInfo info) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getTaskInfo() != null && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_PINNED) { return change; } } return null; } @Override public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, @Nullable SurfaceControl.Transaction finishT) {} @Nullable private TransitionInfo.Change findChangeByTaskId(TransitionInfo info, int taskId) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getTaskInfo() != null && change.getTaskInfo().taskId == taskId) { return change; } } return null; } private void onExitPip() { mPipTaskToken = null; mPipScheduler.onExitPip(); } } services/core/java/com/android/server/wm/WindowOrganizerController.java +3 −7 Original line number Diff line number Diff line Loading @@ -1144,16 +1144,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub if (pipTask == null) { break; } ActivityRecord[] pipActivity = new ActivityRecord[1]; pipTask.forAllActivities((activity) -> { if (activity.pictureInPictureArgs != null) { pipActivity[0] = activity; } }); ActivityRecord pipActivity = pipTask.getActivity( (activity) -> activity.pictureInPictureArgs != null); Rect entryBounds = hop.getBounds(); mService.mRootWindowContainer.moveActivityToPinnedRootTask( pipActivity[0], null /* launchIntoPipHostActivity */, pipActivity, null /* launchIntoPipHostActivity */, "moveActivityToPinnedRootTask", null /* transition */, entryBounds); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +14 −2 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.content.Context; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.common.pip.PipBoundsAlgorithm; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipDisplayLayoutState; Loading @@ -29,6 +31,7 @@ import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.dagger.WMShellBaseModule; import com.android.wm.shell.dagger.WMSingleton; import com.android.wm.shell.pip2.phone.PipController; import com.android.wm.shell.pip2.phone.PipScheduler; import com.android.wm.shell.pip2.phone.PipTransition; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; Loading @@ -52,9 +55,10 @@ public abstract class Pip2Module { @NonNull Transitions transitions, PipBoundsState pipBoundsState, PipBoundsAlgorithm pipBoundsAlgorithm, Optional<PipController> pipController) { Optional<PipController> pipController, @NonNull PipScheduler pipScheduler) { return new PipTransition(shellInit, shellTaskOrganizer, transitions, pipBoundsState, null, pipBoundsAlgorithm); pipBoundsAlgorithm, pipScheduler); } @WMSingleton Loading @@ -73,4 +77,12 @@ public abstract class Pip2Module { pipDisplayLayoutState)); } } @WMSingleton @Provides static PipScheduler providePipScheduler(Context context, PipBoundsState pipBoundsState, @ShellMainThread ShellExecutor mainExecutor) { return new PipScheduler(context, pipBoundsState, mainExecutor); } }
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.pip2.phone; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.view.SurfaceControl; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.pip.PipTransitionController; /** * Scheduler for Shell initiated PiP transitions and animations. */ public class PipScheduler { private static final String TAG = PipScheduler.class.getSimpleName(); private static final String BROADCAST_FILTER = PipScheduler.class.getCanonicalName(); private final Context mContext; private final PipBoundsState mPipBoundsState; private final ShellExecutor mMainExecutor; private PipSchedulerReceiver mSchedulerReceiver; private PipTransitionController mPipTransitionController; // pinned PiP task's WC token @Nullable private WindowContainerToken mPipTaskToken; // pinned PiP task's leash @Nullable private SurfaceControl mPinnedTaskLeash; // the leash of the original task of the PiP activity; // used to synchronize app drawings in the multi-activity case @Nullable private SurfaceControl mOriginalTaskLeash; /** * A temporary broadcast receiver to initiate exit PiP via expand. * This will later be modified to be triggered by the PiP menu. */ private class PipSchedulerReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { scheduleExitPipViaExpand(); } } public PipScheduler(Context context, PipBoundsState pipBoundsState, ShellExecutor mainExecutor) { mContext = context; mPipBoundsState = pipBoundsState; mMainExecutor = mainExecutor; if (PipUtils.isPip2ExperimentEnabled()) { // temporary broadcast receiver to initiate exit PiP via expand mSchedulerReceiver = new PipSchedulerReceiver(); ContextCompat.registerReceiver(mContext, mSchedulerReceiver, new IntentFilter(BROADCAST_FILTER), ContextCompat.RECEIVER_EXPORTED); } } void setPipTransitionController(PipTransitionController pipTransitionController) { mPipTransitionController = pipTransitionController; } void setPinnedTaskLeash(SurfaceControl pinnedTaskLeash) { mPinnedTaskLeash = pinnedTaskLeash; } void setOriginalTaskLeash(SurfaceControl originalTaskLeash) { mOriginalTaskLeash = originalTaskLeash; } void setPipTaskToken(@Nullable WindowContainerToken pipTaskToken) { mPipTaskToken = pipTaskToken; } @Nullable private WindowContainerTransaction getExitPipViaExpandTransaction() { if (mPipTaskToken == null || mPinnedTaskLeash == null) { return null; } WindowContainerTransaction wct = new WindowContainerTransaction(); // final expanded bounds to be inherited from the parent wct.setBounds(mPipTaskToken, null); // if we are hitting a multi-activity case // windowing mode change will reparent to original host task wct.setWindowingMode(mPipTaskToken, WINDOWING_MODE_UNDEFINED); return wct; } /** * Schedules exit PiP via expand transition. */ public void scheduleExitPipViaExpand() { WindowContainerTransaction wct = getExitPipViaExpandTransaction(); if (wct != null) { mMainExecutor.execute(() -> { mPipTransitionController.startExitTransition(TRANSIT_EXIT_PIP, wct, null /* destinationBounds */); }); } } void onExitPip() { mPipTaskToken = null; mPinnedTaskLeash = null; mOriginalTaskLeash = null; } }
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +88 −8 Original line number Diff line number Diff line Loading @@ -16,8 +16,12 @@ package com.android.wm.shell.pip2.phone; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.WindowManager.TRANSIT_OPEN; import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.PictureInPictureParams; Loading @@ -26,6 +30,7 @@ import android.os.IBinder; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.annotation.Nullable; Loading @@ -43,8 +48,15 @@ import com.android.wm.shell.transition.Transitions; * Implementation of transitions for PiP on phone. */ public class PipTransition extends PipTransitionController { private static final String TAG = PipTransition.class.getSimpleName(); private PipScheduler mPipScheduler; @Nullable private WindowContainerToken mPipTaskToken; @Nullable private IBinder mAutoEnterButtonNavTransition; @Nullable private IBinder mExitViaExpandTransition; public PipTransition( @NonNull ShellInit shellInit, Loading @@ -52,9 +64,13 @@ public class PipTransition extends PipTransitionController { @NonNull Transitions transitions, PipBoundsState pipBoundsState, PipMenuController pipMenuController, PipBoundsAlgorithm pipBoundsAlgorithm) { PipBoundsAlgorithm pipBoundsAlgorithm, PipScheduler pipScheduler) { super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController, pipBoundsAlgorithm); mPipScheduler = pipScheduler; mPipScheduler.setPipTransitionController(this); } @Override Loading @@ -64,6 +80,18 @@ public class PipTransition extends PipTransitionController { } } @Override public void startExitTransition(int type, WindowContainerTransaction out, @android.annotation.Nullable Rect destinationBounds) { if (out == null) { return; } IBinder transition = mTransitions.startTransition(type, out, this); if (type == TRANSIT_EXIT_PIP) { mExitViaExpandTransition = transition; } } @Nullable @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, Loading @@ -84,8 +112,18 @@ public class PipTransition extends PipTransitionController { } } @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) {} @Override public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, @Nullable SurfaceControl.Transaction finishT) {} private WindowContainerTransaction getEnterPipTransaction(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { // cache the original task token to check for multi-activity case later final ActivityManager.RunningTaskInfo pipTask = request.getPipTask(); PictureInPictureParams pipParams = pipTask.pictureInPictureParams; mPipBoundsState.setBoundsStateForEntry(pipTask.topActivity, pipTask.topActivityInfo, Loading @@ -93,6 +131,8 @@ public class PipTransition extends PipTransitionController { // calculate the entry bounds and notify core to move task to pinned with final bounds final Rect entryBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); mPipBoundsState.setBounds(entryBounds); WindowContainerTransaction wct = new WindowContainerTransaction(); wct.movePipActivityToPinnedRootTask(pipTask.token, entryBounds); return wct; Loading Loading @@ -121,19 +161,59 @@ public class PipTransition extends PipTransitionController { @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (transition == mAutoEnterButtonNavTransition) { mAutoEnterButtonNavTransition = null; TransitionInfo.Change pipChange = getPipChange(info); if (pipChange == null) { return false; } mPipTaskToken = pipChange.getContainer(); // cache the PiP task token and the relevant leashes mPipScheduler.setPipTaskToken(mPipTaskToken); mPipScheduler.setPinnedTaskLeash(pipChange.getLeash()); // check if we entered PiP from a multi-activity task and set the original task leash final int lastParentTaskId = pipChange.getTaskInfo().lastParentTaskIdBeforePip; final boolean isSingleActivity = lastParentTaskId == INVALID_TASK_ID; mPipScheduler.setOriginalTaskLeash(isSingleActivity ? null : findChangeByTaskId(info, lastParentTaskId).getLeash()); startTransaction.apply(); finishCallback.onTransitionFinished(null); return true; } else if (transition == mExitViaExpandTransition) { mExitViaExpandTransition = null; startTransaction.apply(); finishCallback.onTransitionFinished(null); onExitPip(); return true; } return false; } @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) {} @Nullable private TransitionInfo.Change getPipChange(TransitionInfo info) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getTaskInfo() != null && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_PINNED) { return change; } } return null; } @Override public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, @Nullable SurfaceControl.Transaction finishT) {} @Nullable private TransitionInfo.Change findChangeByTaskId(TransitionInfo info, int taskId) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getTaskInfo() != null && change.getTaskInfo().taskId == taskId) { return change; } } return null; } private void onExitPip() { mPipTaskToken = null; mPipScheduler.onExitPip(); } }
services/core/java/com/android/server/wm/WindowOrganizerController.java +3 −7 Original line number Diff line number Diff line Loading @@ -1144,16 +1144,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub if (pipTask == null) { break; } ActivityRecord[] pipActivity = new ActivityRecord[1]; pipTask.forAllActivities((activity) -> { if (activity.pictureInPictureArgs != null) { pipActivity[0] = activity; } }); ActivityRecord pipActivity = pipTask.getActivity( (activity) -> activity.pictureInPictureArgs != null); Rect entryBounds = hop.getBounds(); mService.mRootWindowContainer.moveActivityToPinnedRootTask( pipActivity[0], null /* launchIntoPipHostActivity */, pipActivity, null /* launchIntoPipHostActivity */, "moveActivityToPinnedRootTask", null /* transition */, entryBounds); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; Loading