Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d00c2e2 authored by Robert Carr's avatar Robert Carr
Browse files

Reimplement PIP animation to not use drag resizing.

When using drag resizing it is difficult to keep big surface
surfaces (e.g. main app windows) and child windows in sync
as we resize. Furthermore it's difficult to resize child windows
quick enough to achieve more than a few frames a second as we have
to propagate through the client UI thread. Our new implementation
uses window scaling.

Bug: 26454664

Change-Id: Iac96619cefc075b1412cfeba3d3c9bcd7ce22f52
parent c24d8f9c
Loading
Loading
Loading
Loading
+40 −1
Original line number Diff line number Diff line
@@ -822,7 +822,21 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            reply.writeNoException();
            return true;
        }

        case RESIZE_PINNED_STACK_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            final boolean hasBounds = data.readInt() != 0;
            Rect bounds = null;
            if (hasBounds) {
                bounds = Rect.CREATOR.createFromParcel(data);
            }
            final boolean hasTempPinnedTaskBounds = data.readInt() != 0;
            Rect tempPinnedTaskBounds = null;
            if (hasTempPinnedTaskBounds) {
                tempPinnedTaskBounds = Rect.CREATOR.createFromParcel(data);
            }
            resizePinnedStack(bounds, tempPinnedTaskBounds);
            return true;
        }
        case RESIZE_DOCKED_STACK_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            final boolean hasBounds = data.readInt() != 0;
@@ -3910,6 +3924,31 @@ class ActivityManagerProxy implements IActivityManager
        data.recycle();
        reply.recycle();
    }

    @Override
    public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        if (pinnedBounds != null) {
            data.writeInt(1);
            pinnedBounds.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        if (tempPinnedTaskBounds != null) {
            data.writeInt(1);
            tempPinnedTaskBounds.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(RESIZE_PINNED_STACK_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

    @Override
    public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException
    {
+11 −0
Original line number Diff line number Diff line
@@ -171,6 +171,16 @@ public interface IActivityManager extends IInterface {
    public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
            Rect tempDockedTaskInsetBounds,
            Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) throws RemoteException;
    /**
     * Resizes the pinned stack.
     *
     * @param pinnedBounds The bounds for the pinned stack.
     * @param tempPinnedTaskBounds The temporary bounds for the tasks in the pinned stack, which
     *                             might be different from the stack bounds to allow more
     *                             flexibility while resizing, or {@code null} if they should be the
     *                             same as the stack bounds.
     */
    public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException;
    public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException;
    public List<StackInfo> getAllStackInfos() throws RemoteException;
    public StackInfo getStackInfo(int stackId) throws RemoteException;
@@ -982,4 +992,5 @@ public interface IActivityManager extends IInterface {
    int REMOVE_STACK = IBinder.FIRST_CALL_TRANSACTION + 367;
    int SET_LENIENT_BACKGROUND_CHECK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+368;
    int GET_MEMORY_TRIM_LEVEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+369;
    int RESIZE_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 370;
}
+14 −0
Original line number Diff line number Diff line
@@ -9573,6 +9573,20 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    @Override
    public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
                "resizePinnedStack()");
        final long ident = Binder.clearCallingIdentity();
        try {
            synchronized (this) {
                mStackSupervisor.resizePinnedStackLocked(pinnedBounds, tempPinnedTaskBounds);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
    @Override
    public void positionTaskInStack(int taskId, int stackId, int position) {
        enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
+19 −0
Original line number Diff line number Diff line
@@ -2034,6 +2034,25 @@ public final class ActivityStackSupervisor implements DisplayListener {
                || tempOtherTaskInsetBounds != null);
    }

    void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
        final ActivityStack stack = getStack(PINNED_STACK_ID);
        if (stack == null) {
            Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
            return;
        }
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack");
        mWindowManager.deferSurfaceLayout();
        try {
            ActivityRecord r = stack.topRunningActivityLocked();
            resizeStackUncheckedLocked(stack, pinnedBounds, tempPinnedTaskBounds,
                    null);
            ensureConfigurationAndResume(stack, r, false);
        } finally {
            mWindowManager.continueSurfaceLayout();
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

    boolean resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow) {
        if (!task.isResizeable()) {
            Slog.w(TAG, "resizeTask: task " + task + " not resizeable.");
+44 −3
Original line number Diff line number Diff line
@@ -54,7 +54,8 @@ public class BoundsAnimationController {
        private final AnimateBoundsUser mTarget;
        private final Rect mFrom;
        private final Rect mTo;
        private final Rect mTmpRect;
        private final Rect mTmpRect = new Rect();
        private final Rect mTmpTaskBounds = new Rect();
        private final boolean mMoveToFullScreen;
        // True if this this animation was cancelled and will be replaced the another animation from
        // the same {@link #AnimateBoundsUser} target.
@@ -63,17 +64,40 @@ public class BoundsAnimationController {
        // {@link #AnimateBoundsUser} target.
        private final boolean mReplacement;

        // Depending on whether we are animating from
        // a smaller to a larger size
        private final int mFrozenTaskWidth;
        private final int mFrozenTaskHeight;

        BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to,
                boolean moveToFullScreen, boolean replacement) {
            super();
            mTarget = target;
            mFrom = from;
            mTo = to;
            mTmpRect = new Rect();
            mMoveToFullScreen = moveToFullScreen;
            mReplacement = replacement;
            addUpdateListener(this);
            addListener(this);

            // If we are animating from smaller to larger, we want to change the task bounds
            // to their final size immediately so we can use scaling to make the window
            // larger. Likewise if we are going from bigger to smaller, we want to wait until
            // the end so we don't have to upscale from the smaller finished size.
            if (animatingToLargerSize()) {
                mFrozenTaskWidth = mTo.width();
                mFrozenTaskHeight = mTo.height();
            } else {
                mFrozenTaskWidth = mFrom.width();
                mFrozenTaskHeight = mFrom.height();
            }
        }

        boolean animatingToLargerSize() {
            if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
                return false;
            }
            return true;
        }

        @Override
@@ -87,7 +111,13 @@ public class BoundsAnimationController {
            if (DEBUG) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + " mBounds="
                    + mTmpRect + " from=" + mFrom + " mTo=" + mTo + " value=" + value
                    + " remains=" + remains);
            if (!mTarget.setSize(mTmpRect)) {

            if (remains != 0) {
                mTmpTaskBounds.set(mTmpRect.left, mTmpRect.top,
                        mTmpRect.left + mFrozenTaskWidth, mTmpRect.top + mFrozenTaskHeight);
            }

            if (!mTarget.setPinnedStackSize(mTmpRect, remains != 0 ? mTmpTaskBounds : null)) {
                // Whoops, the target doesn't feel like animating anymore. Let's immediately finish
                // any further animation.
                animation.cancel();
@@ -99,6 +129,10 @@ public class BoundsAnimationController {
        public void onAnimationStart(Animator animation) {
            if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
                    + " mReplacement=" + mReplacement);
            if (animatingToLargerSize()) {
                mTarget.setPinnedStackSize(mFrom, mTo);
            }

            if (!mReplacement) {
                mTarget.onAnimationStart();
            }
@@ -108,6 +142,7 @@ public class BoundsAnimationController {
        public void onAnimationEnd(Animator animation) {
            if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
                    + " mMoveToFullScreen=" + mMoveToFullScreen + " mWillReplace=" + mWillReplace);

            finishAnimation();
            if (mMoveToFullScreen && !mWillReplace) {
                mTarget.moveToFullscreen();
@@ -159,6 +194,12 @@ public class BoundsAnimationController {
         * from the hierarchy and is not valid anymore.
         */
        boolean setSize(Rect bounds);
        /**
         * Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds,
         * to allow for more flexibility during resizing. Only
         * works for the pinned stack at the moment.
         */
        boolean setPinnedStackSize(Rect bounds, Rect taskBounds);

        void onAnimationStart();

Loading