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

Commit 30307123 authored by Matthew Ng's avatar Matthew Ng
Browse files

Fixes splitscreen when executed from fullscreen app

Fixes splitscreen from the right for launching splitscreen from
fullscreen app including pixel launcher and 3rd party launchers. With
3rd party launchers, the experience is the same as Android O. With pixel
launcher since launcher and recents are merged, it will split to
minimized mode. When pixel launcher is used, the recents stack is
ignored.

Fixes: 73250406
Fixes: 78247419
Test: use split screen; invoke command with supportapp.apk in b/78247419
adb shell am broadcast -a launcher-acc --ei cmd 1
Change-Id: I70b0551c517465b3a059ff7d0641c27f71e8114e
parent 2b17e016
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;

@@ -107,6 +106,12 @@ public class DividerSnapAlgorithm {
                DOCKED_INVALID, false);
    }

    public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
        boolean isHorizontalDivision, Rect insets, int dockSide) {
        this(res, displayWidth, displayHeight, dividerSize, isHorizontalDivision, insets,
            dockSide, false);
    }

    public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
            boolean isHorizontalDivision, Rect insets, int dockSide, boolean isMinimizedMode) {
        mMinFlingVelocityPxPerSecond =
@@ -265,7 +270,11 @@ public class DividerSnapAlgorithm {
                ? mDisplayHeight
                : mDisplayWidth;
        int navBarSize = isHorizontalDivision ? mInsets.bottom : mInsets.right;
        mTargets.add(new SnapTarget(-mDividerSize, -mDividerSize, SnapTarget.FLAG_DISMISS_START,
        int startPos = -mDividerSize;
        if (dockedSide == DOCKED_RIGHT) {
            startPos += mInsets.left;
        }
        mTargets.add(new SnapTarget(startPos, startPos, SnapTarget.FLAG_DISMISS_START,
                0.35f));
        switch (mSnapMode) {
            case SNAP_MODE_16_9:
+59 −32
Original line number Diff line number Diff line
@@ -126,8 +126,10 @@ public class DividerView extends FrameLayout implements OnTouchListener,
    private SnapTarget mSnapTargetBeforeMinimized;

    private int mDividerInsets;
    private final Display mDefaultDisplay;
    private int mDisplayWidth;
    private int mDisplayHeight;
    private int mDisplayRotation;
    private int mDividerWindowWidth;
    private int mDividerSize;
    private int mTouchElevation;
@@ -140,7 +142,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
    private final Rect mDockedInsetRect = new Rect();
    private final Rect mOtherInsetRect = new Rect();
    private final Rect mLastResizeRect = new Rect();
    private final Rect mDisplayRect = new Rect();
    private final Rect mTmpRect = new Rect();
    private final WindowManagerProxy mWindowManagerProxy = WindowManagerProxy.getInstance();
    private DividerWindowManager mWindowManager;
    private VelocityTracker mVelocityTracker;
@@ -274,6 +276,9 @@ public class DividerView extends FrameLayout implements OnTouchListener,
        super(context, attrs, defStyleAttr, defStyleRes);
        mSfChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, context.getDisplay(),
                Choreographer.getInstance());
        final DisplayManager displayManager =
                (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
        mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
    }

    @Override
@@ -373,8 +378,14 @@ public class DividerView extends FrameLayout implements OnTouchListener,
        if (mStableInsets.isEmpty()) {
            SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
        }

        if (mState.mRatioPositionBeforeMinimized == 0) {
            // Set the middle target as the initial state
            mSnapTargetBeforeMinimized = mSnapAlgorithm.getMiddleTarget();
        } else {
            repositionSnapTargetBeforeMinimized();
        }
    }

    public WindowManagerProxy getWindowManagerProxy() {
        return mWindowManagerProxy;
@@ -403,6 +414,11 @@ public class DividerView extends FrameLayout implements OnTouchListener,
            mHandle.setTouching(true, animate);
        }
        mDockSide = mWindowManagerProxy.getDockSide();

        // Update snap algorithm if rotation has occurred
        if (mDisplayRotation != mDefaultDisplay.getRotation()) {
            updateDisplayInfo();
        }
        initializeSnapAlgorithm();
        mWindowManagerProxy.setResizing(true);
        if (touching) {
@@ -453,7 +469,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
    private void initializeSnapAlgorithm() {
        if (mSnapAlgorithm == null) {
            mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth,
                    mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets);
                    mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets, mDockSide);
        }
        if (mMinimizedSnapAlgorithm == null) {
            mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(),
@@ -620,8 +636,11 @@ public class DividerView extends FrameLayout implements OnTouchListener,
                } else {
                    saveTarget = snapTarget;
                }
                if (saveTarget.position != mSnapAlgorithm.getDismissEndTarget().position
                        && saveTarget.position != mSnapAlgorithm.getDismissStartTarget().position) {
                    saveSnapTargetBeforeMinimized(saveTarget);
                }
            }
        };
        Runnable notCancelledEndAction = () -> {
            // Reset minimized divider position after unminimized state animation finishes
@@ -764,6 +783,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
            initializeSnapAlgorithm();
            if (mIsInMinimizeInteraction != minimized) {
                if (minimized) {
                    // Relayout to recalculate the divider shadow when minimizing
                    requestLayout();
                    mIsInMinimizeInteraction = true;
                    resizeStack(mMinimizedSnapAlgorithm.getMiddleTarget());
                } else {
@@ -913,11 +934,9 @@ public class DividerView extends FrameLayout implements OnTouchListener,
    }

    private void updateDisplayInfo() {
        final DisplayManager displayManager =
                (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
        Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
        mDisplayRotation = mDefaultDisplay.getRotation();
        final DisplayInfo info = new DisplayInfo();
        display.getDisplayInfo(info);
        mDefaultDisplay.getDisplayInfo(info);
        mDisplayWidth = info.logicalWidth;
        mDisplayHeight = info.logicalHeight;
        mSnapAlgorithm = null;
@@ -991,44 +1010,47 @@ public class DividerView extends FrameLayout implements OnTouchListener,
        if (mHomeStackResizable && mIsInMinimizeInteraction) {
            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, mDockSide,
                    mDockedTaskRect);
            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);

            // Move a right-docked-app to line up with the divider while dragging it
            if (mDockSide == DOCKED_RIGHT) {
                mDockedTaskRect.offset(Math.max(position, mStableInsets.left - mDividerSize)
                        - mDockedTaskRect.left + mDividerSize, 0);
                mOtherTaskRect.offset(mStableInsets.left, 0);
            }
            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedTaskRect,
                    mOtherTaskRect, null);
            return;
        }

        if (mEntranceAnimationRunning && taskPosition != TASK_POSITION_SAME) {
            if (mCurrentAnimator != null) {
            calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
            } else {
                calculateBoundsForPosition(isHorizontalDivision() ? mDisplayHeight : mDisplayWidth,
                        mDockSide, mDockedTaskRect);
            }

            // Move a docked app if from the right in position with the divider up to insets
            if (mDockSide == DOCKED_RIGHT) {
                mDockedTaskRect.offset(Math.max(position,
                        mStableInsets.left) - mDockedTaskRect.left, 0);
                mDockedTaskRect.offset(Math.max(position, mStableInsets.left - mDividerSize)
                        - mDockedTaskRect.left + mDividerSize, 0);
                mOtherTaskRect.offset(mStableInsets.left, 0);
            }
            calculateBoundsForPosition(taskPosition, DockedDividerUtils.invertDockSide(mDockSide),
                    mOtherTaskRect);
            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,
                    mOtherTaskRect, null);
        } else if (mExitAnimationRunning && taskPosition != TASK_POSITION_SAME) {
            calculateBoundsForPosition(taskPosition,
                    mDockSide, mDockedTaskRect);
            calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
            mDockedInsetRect.set(mDockedTaskRect);
            calculateBoundsForPosition(mExitStartPosition,
                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
            mOtherInsetRect.set(mOtherTaskRect);
            applyExitAnimationParallax(mOtherTaskRect, position);
            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,

            // Move a right-docked-app to line up with the divider while dragging it
            if (mDockSide == DOCKED_RIGHT) {
                mDockedTaskRect.offset(position - mStableInsets.left + mDividerSize, 0);
                mOtherTaskRect.offset(mStableInsets.left, 0);
            }
            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedInsetRect,
                    mOtherTaskRect, mOtherInsetRect);
        } else if (taskPosition != TASK_POSITION_SAME) {
            calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
@@ -1040,17 +1062,17 @@ public class DividerView extends FrameLayout implements OnTouchListener,
                    restrictDismissingTaskPosition(taskPosition, dockSideInverted, taskSnapTarget);
            calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect);
            calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect);
            mDisplayRect.set(0, 0, mDisplayWidth, mDisplayHeight);
            mTmpRect.set(0, 0, mDisplayWidth, mDisplayHeight);
            alignTopLeft(mDockedRect, mDockedTaskRect);
            alignTopLeft(mOtherRect, mOtherTaskRect);
            mDockedInsetRect.set(mDockedTaskRect);
            mOtherInsetRect.set(mOtherTaskRect);
            if (dockSideTopLeft(mDockSide)) {
                alignTopLeft(mDisplayRect, mDockedInsetRect);
                alignBottomRight(mDisplayRect, mOtherInsetRect);
                alignTopLeft(mTmpRect, mDockedInsetRect);
                alignBottomRight(mTmpRect, mOtherInsetRect);
            } else {
                alignBottomRight(mDisplayRect, mDockedInsetRect);
                alignTopLeft(mDisplayRect, mOtherInsetRect);
                alignBottomRight(mTmpRect, mDockedInsetRect);
                alignTopLeft(mTmpRect, mOtherInsetRect);
            }
            applyDismissingParallax(mDockedTaskRect, mDockSide, taskSnapTarget, position,
                    taskPositionDocked);
@@ -1269,23 +1291,22 @@ public class DividerView extends FrameLayout implements OnTouchListener,
            startDragging(false /* animate */, false /* touching */);
        }
        updateDockSide();
        int position = DockedDividerUtils.calculatePositionForBounds(event.initialRect,
                mDockSide, mDividerSize);
        mEntranceAnimationRunning = true;

        resizeStack(position, mSnapAlgorithm.getMiddleTarget().position,
        resizeStack(calculatePositionForInsetBounds(), mSnapAlgorithm.getMiddleTarget().position,
                mSnapAlgorithm.getMiddleTarget());
    }

    public void onRecentsDrawn() {
        updateDockSide();
        final int position = calculatePositionForInsetBounds();
        if (mState.animateAfterRecentsDrawn) {
            mState.animateAfterRecentsDrawn = false;
            updateDockSide();

            mHandler.post(() -> {
                // Delay switching resizing mode because this might cause jank in recents animation
                // that's longer than this animation.
                stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(),
                stopDragging(position, getSnapAlgorithm().getMiddleTarget(),
                        mLongPressEntraceAnimDuration, Interpolators.FAST_OUT_SLOW_IN,
                        200 /* endDelay */);
            });
@@ -1294,7 +1315,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
            mState.growAfterRecentsDrawn = false;
            updateDockSide();
            EventBus.getDefault().send(new RecentsGrowingEvent());
            stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 336,
            stopDragging(position, getSnapAlgorithm().getMiddleTarget(), 336,
                    Interpolators.FAST_OUT_SLOW_IN);
        }
    }
@@ -1315,4 +1336,10 @@ public class DividerView extends FrameLayout implements OnTouchListener,
                    0 /* endDelay */, Interpolators.FAST_OUT_SLOW_IN);
        }
    }

    private int calculatePositionForInsetBounds() {
        mTmpRect.set(0, 0, mDisplayWidth, mDisplayHeight);
        mTmpRect.inset(mStableInsets);
        return DockedDividerUtils.calculatePositionForBounds(mTmpRect, mDockSide, mDividerSize);
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -639,6 +639,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
                // so that the divider matches and remove this logic.
                // TODO: This is currently only called when entering split-screen while in another
                // task, and from the tests
                // TODO (b/78247419): Check if launcher and overview are same then move home stack
                // instead of recents stack. Then fix the rotation animation from fullscreen to
                // minimized mode
                final ActivityStack recentStack = display.getOrCreateStack(
                        WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_RECENTS,
                        true /* onTop */);