From 303071233bff3cd4242f24d00a104a14091d54e0 Mon Sep 17 00:00:00 2001 From: Matthew Ng Date: Fri, 13 Apr 2018 11:36:34 -0700 Subject: [PATCH] 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 --- .../internal/policy/DividerSnapAlgorithm.java | 13 ++- .../systemui/stackdivider/DividerView.java | 91 ++++++++++++------- .../com/android/server/am/ActivityStack.java | 3 + 3 files changed, 73 insertions(+), 34 deletions(-) diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java index fbf690fa1457e..a8ad8102c6107 100644 --- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java +++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java @@ -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: diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 6d677ab74beeb..8d89314c2e210 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -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,7 +378,13 @@ public class DividerView extends FrameLayout implements OnTouchListener, if (mStableInsets.isEmpty()) { SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets); } - repositionSnapTargetBeforeMinimized(); + + if (mState.mRatioPositionBeforeMinimized == 0) { + // Set the middle target as the initial state + mSnapTargetBeforeMinimized = mSnapAlgorithm.getMiddleTarget(); + } else { + repositionSnapTargetBeforeMinimized(); + } } public WindowManagerProxy getWindowManagerProxy() { @@ -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,7 +636,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, } else { saveTarget = snapTarget; } - saveSnapTargetBeforeMinimized(saveTarget); + if (saveTarget.position != mSnapAlgorithm.getDismissEndTarget().position + && saveTarget.position != mSnapAlgorithm.getDismissStartTarget().position) { + saveSnapTargetBeforeMinimized(saveTarget); + } } }; Runnable notCancelledEndAction = () -> { @@ -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); - } + calculateBoundsForPosition(taskPosition, 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); + } } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index a85df03e97f68..87d3696482335 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -639,6 +639,9 @@ class ActivityStack 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 */);