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

Commit e8572720 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Ensure that task org updates all happen off the main thread" into rvc-dev

parents 320ecaca 5570147a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ public class InputConsumerController {
    private final class InputEventReceiver extends BatchedInputEventReceiver {

        public InputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper, Choreographer.getSfInstance());
            super(inputChannel, looper, Choreographer.getInstance());
        }

        @Override
+29 −38
Original line number Diff line number Diff line
@@ -19,11 +19,8 @@ package com.android.systemui.pip;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.MainThread;
import android.content.Context;
import android.graphics.Rect;
import android.os.RemoteException;
import android.view.IWindowContainer;
import android.view.SurfaceControl;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -61,31 +58,30 @@ public class PipAnimationController {
                com.android.internal.R.interpolator.fast_out_slow_in);
    }

    @MainThread
    PipTransitionAnimator getAnimator(IWindowContainer wc, boolean scheduleFinishPip,
    PipTransitionAnimator getAnimator(SurfaceControl leash, boolean scheduleFinishPip,
            Rect destinationBounds, float alphaStart, float alphaEnd) {
        if (mCurrentAnimator == null) {
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofAlpha(wc, scheduleFinishPip,
                            destinationBounds, alphaStart, alphaEnd));
                    PipTransitionAnimator.ofAlpha(leash, scheduleFinishPip, destinationBounds,
                            alphaStart, alphaEnd));
        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
                && mCurrentAnimator.isRunning()) {
            mCurrentAnimator.updateEndValue(alphaEnd);
        } else {
            mCurrentAnimator.cancel();
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofAlpha(wc, scheduleFinishPip,
                            destinationBounds, alphaStart, alphaEnd));
                    PipTransitionAnimator.ofAlpha(leash, scheduleFinishPip, destinationBounds,
                            alphaStart, alphaEnd));
        }
        return mCurrentAnimator;
    }

    @MainThread
    PipTransitionAnimator getAnimator(IWindowContainer wc, boolean scheduleFinishPip,
    PipTransitionAnimator getAnimator(SurfaceControl leash, boolean scheduleFinishPip,
            Rect startBounds, Rect endBounds) {
        if (mCurrentAnimator == null) {
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(wc, scheduleFinishPip, startBounds, endBounds));
                    PipTransitionAnimator.ofBounds(leash, scheduleFinishPip,
                            startBounds, endBounds));
        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_BOUNDS
                && mCurrentAnimator.isRunning()) {
            mCurrentAnimator.setDestinationBounds(endBounds);
@@ -94,7 +90,8 @@ public class PipAnimationController {
        } else {
            mCurrentAnimator.cancel();
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(wc, scheduleFinishPip, startBounds, endBounds));
                    PipTransitionAnimator.ofBounds(leash, scheduleFinishPip,
                            startBounds, endBounds));
        }
        return mCurrentAnimator;
    }
@@ -116,18 +113,18 @@ public class PipAnimationController {
        /**
         * Called when PiP animation is started.
         */
        public void onPipAnimationStart(IWindowContainer wc, PipTransitionAnimator animator) {}
        public void onPipAnimationStart(PipTransitionAnimator animator) {}

        /**
         * Called when PiP animation is ended.
         */
        public void onPipAnimationEnd(IWindowContainer wc, SurfaceControl.Transaction tx,
        public void onPipAnimationEnd(SurfaceControl.Transaction tx,
                PipTransitionAnimator animator) {}

        /**
         * Called when PiP animation is cancelled.
         */
        public void onPipAnimationCancel(IWindowContainer wc, PipTransitionAnimator animator) {}
        public void onPipAnimationCancel(PipTransitionAnimator animator) {}
    }

    /**
@@ -137,7 +134,6 @@ public class PipAnimationController {
    public abstract static class PipTransitionAnimator<T> extends ValueAnimator implements
            ValueAnimator.AnimatorUpdateListener,
            ValueAnimator.AnimatorListener {
        private final IWindowContainer mWindowContainer;
        private final boolean mScheduleFinishPip;
        private final SurfaceControl mLeash;
        private final @AnimationType int mAnimationType;
@@ -149,13 +145,11 @@ public class PipAnimationController {
        private PipAnimationCallback mPipAnimationCallback;
        private SurfaceControlTransactionFactory mSurfaceControlTransactionFactory;

        private PipTransitionAnimator(IWindowContainer wc, boolean scheduleFinishPip,
        private PipTransitionAnimator(SurfaceControl leash, boolean scheduleFinishPip,
                @AnimationType int animationType, Rect destinationBounds,
                T startValue, T endValue) {
            mWindowContainer = wc;
            mScheduleFinishPip = scheduleFinishPip;
            try {
                mLeash = wc.getLeash();
            mLeash = leash;
            mAnimationType = animationType;
            mDestinationBounds.set(destinationBounds);
            mStartValue = startValue;
@@ -163,9 +157,6 @@ public class PipAnimationController {
            addListener(this);
            addUpdateListener(this);
            mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
@@ -173,7 +164,7 @@ public class PipAnimationController {
            mCurrentValue = mStartValue;
            applySurfaceControlTransaction(mLeash, newSurfaceControlTransaction(), FRACTION_START);
            if (mPipAnimationCallback != null) {
                mPipAnimationCallback.onPipAnimationStart(mWindowContainer, this);
                mPipAnimationCallback.onPipAnimationStart(this);
            }
        }

@@ -189,14 +180,14 @@ public class PipAnimationController {
            final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
            applySurfaceControlTransaction(mLeash, tx, FRACTION_END);
            if (mPipAnimationCallback != null) {
                mPipAnimationCallback.onPipAnimationEnd(mWindowContainer, tx, this);
                mPipAnimationCallback.onPipAnimationEnd(tx, this);
            }
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            if (mPipAnimationCallback != null) {
                mPipAnimationCallback.onPipAnimationCancel(mWindowContainer, this);
                mPipAnimationCallback.onPipAnimationCancel(this);
            }
        }

@@ -260,9 +251,9 @@ public class PipAnimationController {
        abstract void applySurfaceControlTransaction(SurfaceControl leash,
                SurfaceControl.Transaction tx, float fraction);

        static PipTransitionAnimator<Float> ofAlpha(IWindowContainer wc, boolean scheduleFinishPip,
        static PipTransitionAnimator<Float> ofAlpha(SurfaceControl leash, boolean scheduleFinishPip,
                Rect destinationBounds, float startValue, float endValue) {
            return new PipTransitionAnimator<Float>(wc, scheduleFinishPip, ANIM_TYPE_ALPHA,
            return new PipTransitionAnimator<Float>(leash, scheduleFinishPip, ANIM_TYPE_ALPHA,
                    destinationBounds, startValue, endValue) {
                @Override
                void applySurfaceControlTransaction(SurfaceControl leash,
@@ -281,10 +272,10 @@ public class PipAnimationController {
            };
        }

        static PipTransitionAnimator<Rect> ofBounds(IWindowContainer wc, boolean scheduleFinishPip,
        static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash, boolean scheduleFinishPip,
                Rect startValue, Rect endValue) {
            // construct new Rect instances in case they are recycled
            return new PipTransitionAnimator<Rect>(wc, scheduleFinishPip, ANIM_TYPE_BOUNDS,
            return new PipTransitionAnimator<Rect>(leash, scheduleFinishPip, ANIM_TYPE_BOUNDS,
                    endValue, new Rect(startValue), new Rect(endValue)) {
                private final Rect mTmpRect = new Rect();

+216 −97

File changed.

Preview size limit exceeded, changes collapsed.

+19 −109
Original line number Diff line number Diff line
@@ -28,16 +28,11 @@ import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Debug;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.Choreographer;

import androidx.dynamicanimation.animation.SpringForce;

import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.os.SomeArgs;
import com.android.systemui.pip.PipSnapAlgorithm;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -47,11 +42,12 @@ import com.android.systemui.util.animation.FloatProperties;
import com.android.systemui.util.animation.PhysicsAnimator;

import java.io.PrintWriter;
import java.util.function.Consumer;

/**
 * A helper to animate and manipulate the PiP.
 */
public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Callback,
public class PipMotionHelper implements PipAppOpsListener.Callback,
        FloatingContentCoordinator.FloatingContent {

    private static final String TAG = "PipMotionHelper";
@@ -68,14 +64,9 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
    // The fraction of the stack height that the user has to drag offscreen to dismiss the PiP
    private static final float DISMISS_OFFSCREEN_FRACTION = 0.3f;

    private static final int MSG_RESIZE_IMMEDIATE = 1;
    private static final int MSG_RESIZE_ANIMATE = 2;
    private static final int MSG_OFFSET_ANIMATE = 3;

    private final Context mContext;
    private final IActivityTaskManager mActivityTaskManager;
    private final PipTaskOrganizer mPipTaskOrganizer;
    private final Handler mHandler;

    private PipMenuActivityController mMenuController;
    private PipSnapAlgorithm mSnapAlgorithm;
@@ -92,9 +83,6 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
    /** The region that all of PIP must stay within. */
    private Rect mFloatingAllowedArea = new Rect();

    private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider =
            new SfVsyncFrameCallbackProvider();

    /**
     * Bounds that are animated using the physics animator.
     */
@@ -112,16 +100,11 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
    private PhysicsAnimator<Rect> mAnimatedBoundsPhysicsAnimator = PhysicsAnimator.getInstance(
            mAnimatedBounds);

    /** Callback that re-sizes PIP to the animated bounds. */
    private final Choreographer.FrameCallback mResizePipVsyncCallback =
            l -> resizePipUnchecked(mAnimatedBounds);

    /**
     * Update listener that posts a vsync frame callback to resize PIP to {@link #mAnimatedBounds}.
     * Update listener that resizes the PIP to {@link #mAnimatedBounds}.
     */
    private final PhysicsAnimator.UpdateListener<Rect> mResizePipVsyncUpdateListener =
            (target, values) ->
                    mSfVsyncFrameProvider.postFrameCallback(mResizePipVsyncCallback);
    private final PhysicsAnimator.UpdateListener<Rect> mResizePipUpdateListener =
            (target, values) -> resizePipUnchecked(mAnimatedBounds);

    /** FlingConfig instances provided to PhysicsAnimator for fling gestures. */
    private PhysicsAnimator.FlingConfig mFlingConfigX;
@@ -137,12 +120,13 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
                new PhysicsAnimator.SpringConfig(
                        SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);

    private final Consumer<Rect> mUpdateBoundsCallback = (toBounds) -> mBounds.set(toBounds);

    public PipMotionHelper(Context context, IActivityTaskManager activityTaskManager,
            PipTaskOrganizer pipTaskOrganizer, PipMenuActivityController menuController,
            PipSnapAlgorithm snapAlgorithm, FlingAnimationUtils flingAnimationUtils,
            FloatingContentCoordinator floatingContentCoordinator) {
        mContext = context;
        mHandler = new Handler(ForegroundThread.get().getLooper(), this);
        mActivityTaskManager = activityTaskManager;
        mPipTaskOrganizer = pipTaskOrganizer;
        mMenuController = menuController;
@@ -234,7 +218,7 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
        }
        cancelAnimations();
        mMenuController.hideMenuWithoutResize();
        mHandler.post(() -> {
        mPipTaskOrganizer.getUpdateHandler().post(() -> {
            try {
                mActivityTaskManager.dismissPip(!skipAnimation, EXPAND_STACK_TO_FULLSCREEN_DURATION);
            } catch (RemoteException e) {
@@ -253,7 +237,7 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
        }
        cancelAnimations();
        mMenuController.hideMenuWithoutResize();
        mHandler.post(() -> {
        mPipTaskOrganizer.getUpdateHandler().post(() -> {
            try {
                mActivityTaskManager.removeStacksInWindowingModes(
                        new int[]{ WINDOWING_MODE_PINNED });
@@ -406,17 +390,13 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
     * Animates the PiP to offset it from the IME or shelf.
     */
    void animateToOffset(Rect originalBounds, int offset) {
        cancelAnimations();
        adjustAndAnimatePipOffset(originalBounds, offset, SHIFT_DURATION);
        if (DEBUG) {
            Log.d(TAG, "animateToOffset: originalBounds=" + originalBounds + " offset=" + offset
                    + " callers=\n" + Debug.getCallers(5, "    "));
        }

    private void adjustAndAnimatePipOffset(Rect originalBounds, int offset, int duration) {
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = originalBounds;
        // offset would be zero if triggered from screen rotation.
        args.argi1 = offset;
        args.argi2 = duration;
        mHandler.sendMessage(mHandler.obtainMessage(MSG_OFFSET_ANIMATE, args));
        cancelAnimations();
        mPipTaskOrganizer.scheduleOffsetPip(originalBounds, offset, SHIFT_DURATION,
                mUpdateBoundsCallback);
    }

    /**
@@ -437,8 +417,7 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call

    /**
     * Starts the physics animator which will update the animated PIP bounds using physics
     * animations, as well as the TimeAnimator which will apply those bounds to PIP at intervals
     * synchronized with the SurfaceFlinger vsync frame provider.
     * animations, as well as the TimeAnimator which will apply those bounds to PIP.
     *
     * This will also add end actions to the bounds animator that cancel the TimeAnimator and update
     * the 'real' bounds to equal the final animated bounds.
@@ -448,7 +427,7 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call

        mAnimatedBoundsPhysicsAnimator
                .withEndActions(() ->  mPipTaskOrganizer.onMotionMovementEnd(mAnimatedBounds))
                .addUpdateListener(mResizePipVsyncUpdateListener)
                .addUpdateListener(mResizePipUpdateListener)
                .start();
    }

@@ -471,9 +450,7 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
                    + " callers=\n" + Debug.getCallers(5, "    "));
        }
        if (!toBounds.equals(mBounds)) {
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = toBounds;
            mHandler.sendMessage(mHandler.obtainMessage(MSG_RESIZE_IMMEDIATE, args));
            mPipTaskOrganizer.scheduleResizePip(toBounds, mUpdateBoundsCallback);
        }
    }

@@ -486,10 +463,7 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
                    + " duration=" + duration + " callers=\n" + Debug.getCallers(5, "    "));
        }
        if (!toBounds.equals(mBounds)) {
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = toBounds;
            args.argi1 = duration;
            mHandler.sendMessage(mHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
            mPipTaskOrganizer.scheduleAnimateResizePip(toBounds, duration, mUpdateBoundsCallback);
            setAnimatingToBounds(toBounds);
        }
    }
@@ -538,70 +512,6 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
        return dismissArea.contains(endpoint.x, endpoint.y);
    }

    /**
     * Handles messages to be processed on the background thread.
     */
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_RESIZE_IMMEDIATE: {
                SomeArgs args = (SomeArgs) msg.obj;
                Rect toBounds = (Rect) args.arg1;
                mPipTaskOrganizer.resizePip(toBounds);
                mBounds.set(toBounds);
                return true;
            }

            case MSG_RESIZE_ANIMATE: {
                SomeArgs args = (SomeArgs) msg.obj;
                Rect toBounds = (Rect) args.arg1;
                int duration = args.argi1;
                try {
                    StackInfo stackInfo = mActivityTaskManager.getStackInfo(
                            WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
                    if (stackInfo == null) {
                        // In the case where we've already re-expanded or dismissed the PiP, then
                        // just skip the resize
                        return true;
                    }

                    mPipTaskOrganizer.animateResizePip(toBounds, duration);
                    mBounds.set(toBounds);
                } catch (RemoteException e) {
                    Log.e(TAG, "Could not animate resize pinned stack to bounds: " + toBounds, e);
                }
                return true;
            }

            case MSG_OFFSET_ANIMATE: {
                SomeArgs args = (SomeArgs) msg.obj;
                Rect originalBounds = (Rect) args.arg1;
                final int offset = args.argi1;
                final int duration = args.argi2;
                try {
                    StackInfo stackInfo = mActivityTaskManager.getStackInfo(
                            WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
                    if (stackInfo == null) {
                        // In the case where we've already re-expanded or dismissed the PiP, then
                        // just skip the resize
                        return true;
                    }

                    mPipTaskOrganizer.offsetPinnedStack(originalBounds,
                            0 /* xOffset */, offset, duration);
                    Rect toBounds = new Rect(originalBounds);
                    toBounds.offset(0, offset);
                    mBounds.set(toBounds);
                } catch (RemoteException e) {
                    Log.e(TAG, "Could not animate offset pinned stack with offset: " + offset, e);
                }
                return true;
            }

            default:
                return false;
        }
    }

    public void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + TAG);
+15 −10
Original line number Diff line number Diff line
@@ -21,33 +21,38 @@ import android.os.HandlerThread;

/**
 * Similar to {@link com.android.internal.os.BackgroundThread}, this is a shared singleton
 * foreground thread for each process.
 * foreground thread for each process for updating PIP.
 */
public final class ForegroundThread extends HandlerThread {
    private static ForegroundThread sInstance;
public final class PipUpdateThread extends HandlerThread {
    private static PipUpdateThread sInstance;
    private static Handler sHandler;

    private ForegroundThread() {
        super("recents.fg");
    private PipUpdateThread() {
        super("pip");
    }

    private static void ensureThreadLocked() {
        if (sInstance == null) {
            sInstance = new ForegroundThread();
            sInstance = new PipUpdateThread();
            sInstance.start();
            sHandler = new Handler(sInstance.getLooper());
        }
    }

    public static ForegroundThread get() {
        synchronized (ForegroundThread.class) {
    /**
     * @return the static update thread instance
     */
    public static PipUpdateThread get() {
        synchronized (PipUpdateThread.class) {
            ensureThreadLocked();
            return sInstance;
        }
    }

    /**
     * @return the static update thread handler instance
     */
    public static Handler getHandler() {
        synchronized (ForegroundThread.class) {
        synchronized (PipUpdateThread.class) {
            ensureThreadLocked();
            return sHandler;
        }
Loading