diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java index fe70ff7a1dbf4..174165c5ba59f 100644 --- a/core/java/android/view/SurfaceControlViewHost.java +++ b/core/java/android/view/SurfaceControlViewHost.java @@ -124,8 +124,14 @@ public class SurfaceControlViewHost { /** @hide */ public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d, @NonNull WindowlessWindowManager wwm) { + this(c, d, wwm, false /* useSfChoreographer */); + } + + /** @hide */ + public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d, + @NonNull WindowlessWindowManager wwm, boolean useSfChoreographer) { mWm = wwm; - mViewRoot = new ViewRootImpl(c, d, mWm); + mViewRoot = new ViewRootImpl(c, d, mWm, useSfChoreographer); mViewRoot.forceDisableBLAST(); mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection(); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 3534bb0f763f1..2d309034e1c21 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -449,7 +449,7 @@ public final class ViewRootImpl implements ViewParent, InputQueue mInputQueue; @UnsupportedAppUsage FallbackEventHandler mFallbackEventHandler; - Choreographer mChoreographer; + final Choreographer mChoreographer; // used in relayout to get SurfaceControl size // for BLAST adapter surface setup @@ -692,11 +692,18 @@ public final class ViewRootImpl implements ViewParent, private SurfaceControl.Transaction mRtBLASTSyncTransaction = new SurfaceControl.Transaction(); private String mTag = TAG; + public ViewRootImpl(Context context, Display display) { - this(context, display, WindowManagerGlobal.getWindowSession()); + this(context, display, WindowManagerGlobal.getWindowSession(), + false /* useSfChoreographer */); } public ViewRootImpl(Context context, Display display, IWindowSession session) { + this(context, display, session, false /* useSfChoreographer */); + } + + public ViewRootImpl(Context context, Display display, IWindowSession session, + boolean useSfChoreographer) { mContext = context; mWindowSession = session; mDisplay = display; @@ -732,7 +739,8 @@ public final class ViewRootImpl implements ViewParent, mDensity = context.getResources().getDisplayMetrics().densityDpi; mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi; mFallbackEventHandler = new PhoneFallbackEventHandler(context); - mChoreographer = Choreographer.getInstance(); + mChoreographer = useSfChoreographer + ? Choreographer.getSfInstance() : Choreographer.getInstance(); mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); mInsetsController = new InsetsController(this); diff --git a/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java b/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java deleted file mode 100644 index 924b3f704f5be..0000000000000 --- a/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.internal.view; - -import android.os.Handler; -import android.os.Message; -import android.view.Choreographer; -import android.view.Display; - -/** - * Utility class to schedule things at vsync-sf instead of vsync-app - * @hide - */ -public class SurfaceFlingerVsyncChoreographer { - - private static final long ONE_MS_IN_NS = 1000000; - private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000; - - private final Handler mHandler; - private final Choreographer mChoreographer; - - /** - * The offset between vsync-app and vsync-surfaceflinger. See - * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary. - */ - private long mSurfaceFlingerOffsetMs; - - public SurfaceFlingerVsyncChoreographer(Handler handler, Display display, - Choreographer choreographer) { - mHandler = handler; - mChoreographer = choreographer; - mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs(display); - } - - public long getSurfaceFlingerOffsetMs() { - return mSurfaceFlingerOffsetMs; - } - - /** - * 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 a surface - * flinger transaction 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) { - - // 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); - } - - public void scheduleAtSfVsync(Runnable r) { - final long delay = calculateDelay(); - if (delay <= 0) { - r.run(); - } else { - mHandler.postDelayed(r, delay); - } - } - - public void scheduleAtSfVsync(Handler h, Message m) { - final long delay = calculateDelay(); - if (delay <= 0) { - h.handleMessage(m); - } else { - m.setAsynchronous(true); - h.sendMessageDelayed(m, delay); - } - } - - private long calculateDelay() { - final long sinceFrameStart = System.nanoTime() - mChoreographer.getLastFrameTimeNanos(); - return mSurfaceFlingerOffsetMs - sinceFrameStart / 1000000; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 3879c164a84cc..366ef931e1f59 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -21,6 +21,7 @@ import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW; import static android.view.WindowManager.DOCKED_RIGHT; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; +import android.animation.AnimationHandler; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; @@ -32,10 +33,8 @@ 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.util.Slog; -import android.view.Choreographer; import android.view.Display; import android.view.InsetsState; import android.view.MotionEvent; @@ -57,12 +56,12 @@ import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.widget.FrameLayout; +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget; import com.android.internal.policy.DockedDividerUtils; -import com.android.internal.view.SurfaceFlingerVsyncChoreographer; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -111,8 +110,6 @@ 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 int MSG_RESIZE_STACK = 0; - private DividerHandleView mHandle; private View mBackground; private MinimizedDockShadow mMinimizedShadow; @@ -149,6 +146,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, private SplitDisplayLayout mSplitLayout; private DividerCallbacks mCallback; private final Rect mStableInsets = new Rect(); + private final AnimationHandler mAnimationHandler = new AnimationHandler(); private boolean mGrowRecents; private ValueAnimator mCurrentAnimator; @@ -159,7 +157,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, private boolean mHomeStackResizable; private boolean mAdjustedForIme; private DividerState mState; - private final SurfaceFlingerVsyncChoreographer mSfChoreographer; private SplitScreenTaskOrganizer mTiles; boolean mFirstLayout = true; @@ -173,18 +170,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, // used interact with keyguard. private boolean mSurfaceHidden = false; - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_RESIZE_STACK: - resizeStackSurfaces(msg.arg1, msg.arg2, (SnapTarget) msg.obj); - break; - default: - super.handleMessage(msg); - } - } - }; + private final Handler mHandler = new Handler(); private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() { @Override @@ -277,11 +263,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { 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); + mAnimationHandler.setProvider(new SfVsyncFrameCallbackProvider()); } @Override @@ -326,7 +311,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, void onDividerRemoved() { mRemoved = true; mCallback = null; - mHandler.removeMessages(MSG_RESIZE_STACK); } @Override @@ -548,7 +532,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) { SnapTarget snapTarget = getSnapAlgorithm().calculateSnapTarget( mStartPosition, 0 /* velocity */, false /* hardDismiss */); - resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget); + resizeStackSurfaces(calculatePosition(x, y), mStartPosition, snapTarget); } break; case MotionEvent.ACTION_UP: @@ -633,7 +617,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, if (DEBUG) Slog.d(TAG, "Getting fling " + position + "->" + snapTarget.position); final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE; ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position); - anim.addUpdateListener(animation -> resizeStackDelayed((int) animation.getAnimatedValue(), + anim.addUpdateListener(animation -> resizeStackSurfaces((int) animation.getAnimatedValue(), taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f ? TASK_POSITION_SAME : snapTarget.taskPosition, @@ -682,7 +666,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, @Override public void onAnimationCancel(Animator animation) { - mHandler.removeMessages(MSG_RESIZE_STACK); mCancelled = true; } @@ -693,8 +676,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, delay = endDelay; } else if (mCancelled) { delay = 0; - } else if (mSfChoreographer.getSurfaceFlingerOffsetMs() > 0) { - delay = mSfChoreographer.getSurfaceFlingerOffsetMs(); } if (delay == 0) { endAction.accept(mCancelled); @@ -705,6 +686,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, } } }); + anim.setAnimationHandler(mAnimationHandler); mCurrentAnimator = anim; return anim; } @@ -1047,13 +1029,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, mDividerSize); } - public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) { - Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition, - taskSnapTarget); - message.setAsynchronous(true); - mSfChoreographer.scheduleAtSfVsync(mHandler, message); - } - private void resizeStackSurfaces(SnapTarget taskSnapTarget) { resizeStackSurfaces(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget); } diff --git a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java index 381ccdb50386f..1140b9aa3abb7 100644 --- a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java +++ b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java @@ -194,7 +194,9 @@ public class SystemWindows { return; } final Display display = mDisplayController.getDisplay(mDisplayId); - SurfaceControlViewHost viewRoot = new SurfaceControlViewHost(mContext, display, wwm); + SurfaceControlViewHost viewRoot = + new SurfaceControlViewHost(mContext, display, wwm, + true /* useSfChoreographer */); attrs.flags |= FLAG_HARDWARE_ACCELERATED; viewRoot.setView(view, attrs); mViewRoots.put(view, viewRoot);