Loading packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +71 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.graphics.Region.Op; import android.hardware.display.DisplayManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.Display; import android.view.DisplayInfo; Loading Loading @@ -106,6 +107,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, private static final Interpolator IME_ADJUST_INTERPOLATOR = new PathInterpolator(0.2f, 0f, 0.1f, 1f); private static final long ONE_MS_IN_NS = 1000000; private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000; private static final int MSG_RESIZE_STACK = 0; private DividerHandleView mHandle; private View mBackground; private MinimizedDockShadow mMinimizedShadow; Loading Loading @@ -150,7 +156,25 @@ public class DividerView extends FrameLayout implements OnTouchListener, private boolean mDockedStackMinimized; private boolean mAdjustedForIme; private DividerState mState; private final Handler mHandler = new Handler(); /** * The offset between vsync-app and vsync-surfaceflinger. See * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary. */ private long mSurfaceFlingerOffsetMs; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_RESIZE_STACK: resizeStack(msg.arg1, msg.arg2, (SnapTarget) msg.obj); break; default: super.handleMessage(msg); } } }; private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() { @Override Loading Loading @@ -290,6 +314,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, protected void onAttachedToWindow() { super.onAttachedToWindow(); EventBus.getDefault().register(this); mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs(); } @Override Loading @@ -298,6 +323,25 @@ public class DividerView extends FrameLayout implements OnTouchListener, EventBus.getDefault().unregister(this); } /** * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app * is a couple of milliseconds before vsync-sf, a touch or animation event that causes the * stacks to be resized are sometimes processed before the vsync-sf tick, and sometimes after, * which leads to jank. Figure out this difference here and then post all the touch/animation * events to start being processed at vsync-sf. * * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf. */ private long calculateAppSurfaceFlingerVsyncOffsetMs() { Display display = getDisplay(); // Calculate vsync offset from SurfaceFlinger. // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate()); long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS); return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS); } @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { if (mStableInsets.left != insets.getStableInsetLeft() Loading Loading @@ -453,7 +497,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) { SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget( mStartPosition, 0 /* velocity */, false /* hardDismiss */); resizeStack(calculatePosition(x, y), mStartPosition, snapTarget); resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget); } break; case MotionEvent.ACTION_UP: Loading Loading @@ -532,10 +576,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, final long endDelay) { final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE; ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position); anim.addUpdateListener(animation -> resizeStack((Integer) animation.getAnimatedValue(), anim.addUpdateListener(animation -> resizeStackDelayed((int) animation.getAnimatedValue(), taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f ? TASK_POSITION_SAME : snapTarget.taskPosition, snapTarget)); : snapTarget.taskPosition, snapTarget)); Runnable endAction = () -> { commitSnapFlags(snapTarget); mWindowManagerProxy.setResizing(false); Loading @@ -551,15 +596,24 @@ public class DividerView extends FrameLayout implements OnTouchListener, @Override public void onAnimationCancel(Animator animation) { mHandler.removeMessages(MSG_RESIZE_STACK); mCancelled = true; } @Override public void onAnimationEnd(Animator animation) { if (endDelay == 0 || mCancelled) { long delay = 0; if (endDelay != 0) { delay = endDelay; } else if (mCancelled) { delay = 0; } else if (mSurfaceFlingerOffsetMs != 0) { delay = mSurfaceFlingerOffsetMs; } if (delay == 0) { endAction.run(); } else { mHandler.postDelayed(endAction, endDelay); mHandler.postDelayed(endAction, delay); } } }); Loading Loading @@ -793,6 +847,17 @@ public class DividerView extends FrameLayout implements OnTouchListener, mDisplayHeight, mDividerSize); } public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) { if (mSurfaceFlingerOffsetMs != 0) { Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition, taskSnapTarget); message.setAsynchronous(true); mHandler.sendMessageDelayed(message, mSurfaceFlingerOffsetMs); } else { resizeStack(position, taskPosition, taskSnapTarget); } } public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) { calculateBoundsForPosition(position, mDockSide, mDockedRect); Loading Loading
packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +71 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.graphics.Region.Op; import android.hardware.display.DisplayManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.Display; import android.view.DisplayInfo; Loading Loading @@ -106,6 +107,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, private static final Interpolator IME_ADJUST_INTERPOLATOR = new PathInterpolator(0.2f, 0f, 0.1f, 1f); private static final long ONE_MS_IN_NS = 1000000; private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000; private static final int MSG_RESIZE_STACK = 0; private DividerHandleView mHandle; private View mBackground; private MinimizedDockShadow mMinimizedShadow; Loading Loading @@ -150,7 +156,25 @@ public class DividerView extends FrameLayout implements OnTouchListener, private boolean mDockedStackMinimized; private boolean mAdjustedForIme; private DividerState mState; private final Handler mHandler = new Handler(); /** * The offset between vsync-app and vsync-surfaceflinger. See * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary. */ private long mSurfaceFlingerOffsetMs; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_RESIZE_STACK: resizeStack(msg.arg1, msg.arg2, (SnapTarget) msg.obj); break; default: super.handleMessage(msg); } } }; private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() { @Override Loading Loading @@ -290,6 +314,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, protected void onAttachedToWindow() { super.onAttachedToWindow(); EventBus.getDefault().register(this); mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs(); } @Override Loading @@ -298,6 +323,25 @@ public class DividerView extends FrameLayout implements OnTouchListener, EventBus.getDefault().unregister(this); } /** * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app * is a couple of milliseconds before vsync-sf, a touch or animation event that causes the * stacks to be resized are sometimes processed before the vsync-sf tick, and sometimes after, * which leads to jank. Figure out this difference here and then post all the touch/animation * events to start being processed at vsync-sf. * * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf. */ private long calculateAppSurfaceFlingerVsyncOffsetMs() { Display display = getDisplay(); // Calculate vsync offset from SurfaceFlinger. // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate()); long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS); return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS); } @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { if (mStableInsets.left != insets.getStableInsetLeft() Loading Loading @@ -453,7 +497,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) { SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget( mStartPosition, 0 /* velocity */, false /* hardDismiss */); resizeStack(calculatePosition(x, y), mStartPosition, snapTarget); resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget); } break; case MotionEvent.ACTION_UP: Loading Loading @@ -532,10 +576,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, final long endDelay) { final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE; ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position); anim.addUpdateListener(animation -> resizeStack((Integer) animation.getAnimatedValue(), anim.addUpdateListener(animation -> resizeStackDelayed((int) animation.getAnimatedValue(), taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f ? TASK_POSITION_SAME : snapTarget.taskPosition, snapTarget)); : snapTarget.taskPosition, snapTarget)); Runnable endAction = () -> { commitSnapFlags(snapTarget); mWindowManagerProxy.setResizing(false); Loading @@ -551,15 +596,24 @@ public class DividerView extends FrameLayout implements OnTouchListener, @Override public void onAnimationCancel(Animator animation) { mHandler.removeMessages(MSG_RESIZE_STACK); mCancelled = true; } @Override public void onAnimationEnd(Animator animation) { if (endDelay == 0 || mCancelled) { long delay = 0; if (endDelay != 0) { delay = endDelay; } else if (mCancelled) { delay = 0; } else if (mSurfaceFlingerOffsetMs != 0) { delay = mSurfaceFlingerOffsetMs; } if (delay == 0) { endAction.run(); } else { mHandler.postDelayed(endAction, endDelay); mHandler.postDelayed(endAction, delay); } } }); Loading Loading @@ -793,6 +847,17 @@ public class DividerView extends FrameLayout implements OnTouchListener, mDisplayHeight, mDividerSize); } public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) { if (mSurfaceFlingerOffsetMs != 0) { Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition, taskSnapTarget); message.setAsynchronous(true); mHandler.sendMessageDelayed(message, mSurfaceFlingerOffsetMs); } else { resizeStack(position, taskPosition, taskSnapTarget); } } public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) { calculateBoundsForPosition(position, mDockSide, mDockedRect); Loading