diff options
| author | 2020-10-06 13:56:02 -0700 | |
|---|---|---|
| committer | 2020-10-22 22:36:40 -0700 | |
| commit | 0065703423feca30642afba7606e8484ff7bbdb7 (patch) | |
| tree | fb8aea1b4a492efce25a76bf588f70e34d47fbba | |
| parent | 5eec4cefd16a819786b4c4191bef74a0aa3adae6 (diff) | |
Enter PiP directly if the transition is handled in Launcher
Added also a AIDL method Launcher would issue when the entering pip
animation is completed on Launcher side and WM should update the task
surface when doing cleanup.
Bug: 143965596
Test: see ag/12838262
Change-Id: I5396f9637b4760df014f63b46543d4f399229bba
5 files changed, 86 insertions, 11 deletions
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl index 983ab2eedf5c..f209d88ac825 100644 --- a/core/java/android/view/IRecentsAnimationController.aidl +++ b/core/java/android/view/IRecentsAnimationController.aidl @@ -19,6 +19,7 @@ package android.view; import android.app.ActivityManager; import android.view.IRemoteAnimationFinishedCallback; import android.graphics.GraphicBuffer; +import android.graphics.Rect; /** * Passed to the {@link IRecentsAnimationRunner} in order for the runner to control to let the @@ -37,6 +38,15 @@ interface IRecentsAnimationController { ActivityManager.TaskSnapshot screenshotTask(int taskId); /** + * Sets the final bounds on a Task. This is used by Launcher to notify the system that + * animating Activity to PiP has completed and the associated task surface should be updated + * accordingly. This should be called before `finish` + * @param taskId for which the leash should be updated + * @param destinationBounds bounds of the final PiP window + */ + void setFinishTaskBounds(int taskId, in Rect destinationBounds); + + /** * Notifies to the system that the animation into Recents should end, and all leashes associated * with remote animation targets should be relinquished. If {@param moveHomeToTop} is true, then * the home activity should be moved to the top. Otherwise, the home activity is hidden and the diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 98c33705255a..a430dcdda247 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -319,6 +319,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/DisplayRotation.java" }, + "-1729340764": { + "message": "setFinishTaskBounds(%d): bounds=%s", + "level": "DEBUG", + "group": "WM_DEBUG_RECENTS_ANIMATIONS", + "at": "com\/android\/server\/wm\/RecentsAnimationController.java" + }, "-1715268616": { "message": "Last window, removing starting window %s", "level": "VERBOSE", diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index a7bf9aea46bc..a28477574605 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -68,7 +68,6 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.pip.phone.PipMenuActivityController; import com.android.wm.shell.pip.phone.PipMotionHelper; import com.android.wm.shell.pip.phone.PipUpdateThread; -import com.android.wm.shell.pip.phone.PipUtils; import com.android.wm.shell.splitscreen.SplitScreen; import java.io.PrintWriter; @@ -339,7 +338,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo, PictureInPictureParams pictureInPictureParams) { mShouldIgnoreEnteringPipTransition = true; - mState = State.ENTERING_PIP; + sendOnPipTransitionStarted(componentName, TRANSITION_DIRECTION_TO_PIP); mPipBoundsState.setLastPipComponentName(componentName); mPipBoundsState.setAspectRatio(getAspectRatioOrDefault(pictureInPictureParams)); return mPipBoundsHandler.getDestinationBounds(null /* bounds */, @@ -351,7 +350,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, * Expect {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)} afterwards. */ public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) { - mPipBoundsState.setBounds(destinationBounds); + // do nothing if there is no startSwipePipToHome being called before + if (mShouldIgnoreEnteringPipTransition) { + mPipBoundsState.setBounds(destinationBounds); + } } /** @@ -494,11 +496,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } if (mShouldIgnoreEnteringPipTransition) { - // Animation has been finished together with Recents, directly apply the sync - // transaction to PiP here. - applyEnterPipSyncTransaction(mPipBoundsState.getBounds(), () -> { - mState = State.ENTERED_PIP; - }); + // animation is finished in the Launcher and here we directly apply the final touch. + applyEnterPipSyncTransaction(mPipBoundsState.getBounds(), + () -> sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP)); mShouldIgnoreEnteringPipTransition = false; return; } @@ -589,11 +589,19 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, private void sendOnPipTransitionStarted( @PipAnimationController.TransitionDirection int direction) { + sendOnPipTransitionStarted(mTaskInfo.baseActivity, direction); + } + + private void sendOnPipTransitionStarted(ComponentName componentName, + @PipAnimationController.TransitionDirection int direction) { + if (direction == TRANSITION_DIRECTION_TO_PIP) { + mState = State.ENTERING_PIP; + } final Rect pipBounds = mPipBoundsState.getBounds(); runOnMainHandler(() -> { for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) { final PipTransitionCallback callback = mPipTransitionCallbacks.get(i); - callback.onPipTransitionStarted(mTaskInfo.baseActivity, direction, pipBounds); + callback.onPipTransitionStarted(componentName, direction, pipBounds); } }); } @@ -703,6 +711,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, return; } mShouldDeferEnteringPip = false; + mShouldIgnoreEnteringPipTransition = false; mPictureInPictureParams = null; mState = State.UNDEFINED; mPipUiEventLoggerLogger.setTaskInfo(null); @@ -1081,7 +1090,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, return WINDOWING_MODE_UNDEFINED; } - private void animateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction, int durationMs) { if (Looper.myLooper() != mUpdateHandler.getLooper()) { diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java index 76513c6ff3d5..611c4b766b4e 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java @@ -17,6 +17,7 @@ package com.android.systemui.shared.system; import android.app.ActivityManager.TaskSnapshot; +import android.graphics.Rect; import android.os.RemoteException; import android.util.Log; import android.view.IRecentsAnimationController; @@ -70,6 +71,21 @@ public class RecentsAnimationControllerCompat { } /** + * Sets the final bounds on a Task. This is used by Launcher to notify the system that + * animating Activity to PiP has completed and the associated task surface should be updated + * accordingly. This should be called before `finish` + * @param taskId Task id of the Activity in PiP mode. + * @param destinationBounds Bounds of the PiP window on home. + */ + public void setFinishTaskBounds(int taskId, Rect destinationBounds) { + try { + mAnimationController.setFinishTaskBounds(taskId, destinationBounds); + } catch (RemoteException e) { + Log.d(TAG, "Failed to set finish task bounds", e); + } + } + + /** * Finish the current recents animation. * @param toHome Going to home or back to the previous app. * @param sendUserLeaveHint determines whether userLeaveHint will be set true to the previous diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 4ad2575c9490..1736ac933a80 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -214,6 +214,26 @@ public class RecentsAnimationController implements DeathRecipient { } @Override + public void setFinishTaskBounds(int taskId, Rect destinationBounds) { + ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, + "setFinishTaskBounds(%d): bounds=%s", taskId, destinationBounds); + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mService.getWindowManagerLock()) { + for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { + final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i); + if (taskAdapter.mTask.mTaskId == taskId) { + taskAdapter.mFinishBounds.set(destinationBounds); + break; + } + } + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override public void finish(boolean moveHomeToTop, boolean sendUserLeaveHint) { ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "finish(%b): mCanceled=%b", moveHomeToTop, mCanceled); @@ -739,6 +759,7 @@ public class RecentsAnimationController implements DeathRecipient { taskAdapter.mTask.dontAnimateDimExit(); } removeAnimation(taskAdapter); + taskAdapter.maybeApplyFinishBounds(); } for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) { @@ -925,7 +946,9 @@ public class RecentsAnimationController implements DeathRecipient { private RemoteAnimationTarget mTarget; private final Rect mBounds = new Rect(); // The bounds of the target relative to its parent. - private Rect mLocalBounds = new Rect(); + private final Rect mLocalBounds = new Rect(); + // The bounds of the target when animation is finished + private final Rect mFinishBounds = new Rect(); TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) { mTask = task; @@ -960,6 +983,17 @@ public class RecentsAnimationController implements DeathRecipient { return mTarget; } + void maybeApplyFinishBounds() { + if (!mFinishBounds.isEmpty()) { + final SurfaceControl taskSurface = mTask.getSurfaceControl(); + mTask.getPendingTransaction() + .setPosition(taskSurface, mFinishBounds.left, mFinishBounds.top) + .setWindowCrop(taskSurface, mFinishBounds.width(), mFinishBounds.height()) + .apply(); + mFinishBounds.setEmpty(); + } + } + @Override public boolean getShowWallpaper() { return false; @@ -1005,6 +1039,7 @@ public class RecentsAnimationController implements DeathRecipient { } pw.println("mIsRecentTaskInvisible=" + mIsRecentTaskInvisible); pw.println("mLocalBounds=" + mLocalBounds); + pw.println("mFinishBounds=" + mFinishBounds); pw.println("mBounds=" + mBounds); pw.println("mIsRecentTaskInvisible=" + mIsRecentTaskInvisible); } |