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

Commit e6abf0b7 authored by Tony Huang's avatar Tony Huang Committed by Automerger Merge Worker
Browse files

Merge "Fix split divider janky" into rvc-dev am: a171ec42

Change-Id: Idb5980625a652313eaa4335836a49c61d56f1f51
parents 226a97d5 a171ec42
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -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();
    }
+11 −3
Original line number Diff line number Diff line
@@ -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);

+0 −94
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+8 −33
Original line number Diff line number Diff line
@@ -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);
    }
+3 −1
Original line number Diff line number Diff line
@@ -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);