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

Commit ab73e4cb authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Extra common logic of default transition animation" into main

parents 9cbf2acd cdc00f51
Loading
Loading
Loading
Loading
+89 −36
Original line number Diff line number Diff line
@@ -826,24 +826,26 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
            @NonNull Runnable finishCallback, @NonNull TransactionPool pool,
            @NonNull ShellExecutor mainExecutor, @Nullable Point position, float cornerRadius,
            @Nullable Rect clipRect, boolean isActivity) {
        final DefaultAnimationAdapter adapter = new DefaultAnimationAdapter(anim, leash,
                position, clipRect, cornerRadius, isActivity);
        buildSurfaceAnimation(animations, anim, finishCallback, pool, mainExecutor, adapter);
    }

    /** Builds an animator for the surface and adds it to the `animations` list. */
    static void buildSurfaceAnimation(@NonNull ArrayList<Animator> animations,
            @NonNull Animation anim, @NonNull Runnable finishCallback,
            @NonNull TransactionPool pool, @NonNull ShellExecutor mainExecutor,
            @NonNull AnimationAdapter updateListener) {
        final SurfaceControl.Transaction transaction = pool.acquire();
        updateListener.setTransaction(transaction);
        final ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
        final Transformation transformation = new Transformation();
        final float[] matrix = new float[9];
        // Animation length is already expected to be scaled.
        va.overrideDurationScale(1.0f);
        va.setDuration(anim.computeDurationHint());
        final ValueAnimator.AnimatorUpdateListener updateListener = animation -> {
            final long currentPlayTime = Math.min(va.getDuration(), va.getCurrentPlayTime());

            applyTransformation(currentPlayTime, transaction, leash, anim, transformation, matrix,
                    position, cornerRadius, clipRect, isActivity);
        };
        va.addUpdateListener(updateListener);

        final Runnable finisher = () -> {
            applyTransformation(va.getDuration(), transaction, leash, anim, transformation, matrix,
                    position, cornerRadius, clipRect, isActivity);
            updateListener.onAnimationUpdate(va);

            pool.release(transaction);
            mainExecutor.execute(() -> {
@@ -1007,37 +1009,88 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
                || animType == ANIM_FROM_STYLE;
    }

    private static void applyTransformation(long time, SurfaceControl.Transaction t,
            SurfaceControl leash, Animation anim, Transformation tmpTransformation, float[] matrix,
            Point position, float cornerRadius, @Nullable Rect immutableClipRect,
    /** The animation adapter for buildSurfaceAnimation. */
    abstract static class AnimationAdapter implements ValueAnimator.AnimatorUpdateListener {
        @NonNull final SurfaceControl mLeash;
        @NonNull SurfaceControl.Transaction mTransaction;
        private Choreographer mChoreographer;

        AnimationAdapter(@NonNull SurfaceControl leash) {
            mLeash = leash;
        }

        void setTransaction(@NonNull SurfaceControl.Transaction transaction) {
            mTransaction = transaction;
        }

        @Override
        public void onAnimationUpdate(@NonNull ValueAnimator animator) {
            applyTransformation(animator);
            if (mChoreographer == null) {
                mChoreographer = Choreographer.getInstance();
            }
            mTransaction.setFrameTimelineVsync(mChoreographer.getVsyncId());
            mTransaction.apply();
        }

        abstract void applyTransformation(@NonNull ValueAnimator animator);
    }

    private static class DefaultAnimationAdapter extends AnimationAdapter {
        final Transformation mTransformation = new Transformation();
        final float[] mMatrix = new float[9];
        @NonNull final Animation mAnim;
        @Nullable final Point mPosition;
        @Nullable final Rect mClipRect;
        final float mCornerRadius;
        final boolean mIsActivity;

        DefaultAnimationAdapter(@NonNull Animation anim, @NonNull SurfaceControl leash,
                @Nullable Point position, @Nullable Rect clipRect, float cornerRadius,
                boolean isActivity) {
        tmpTransformation.clear();
        anim.getTransformation(time, tmpTransformation);
            super(leash);
            mAnim = anim;
            mPosition = (position != null && (position.x != 0 || position.y != 0))
                    ? position : null;
            mClipRect = (clipRect != null && !clipRect.isEmpty()) ? clipRect : null;
            mCornerRadius = cornerRadius;
            mIsActivity = isActivity;
        }

        @Override
        void applyTransformation(@NonNull ValueAnimator animator) {
            final long currentPlayTime = Math.min(animator.getDuration(),
                    animator.getCurrentPlayTime());
            final Transformation transformation = mTransformation;
            final SurfaceControl.Transaction t = mTransaction;
            final SurfaceControl leash = mLeash;
            transformation.clear();
            mAnim.getTransformation(currentPlayTime, transformation);
            if (com.android.graphics.libgui.flags.Flags.edgeExtensionShader()
                && anim.getExtensionEdges() != 0x0 && isActivity) {
            t.setEdgeExtensionEffect(leash, anim.getExtensionEdges());
                    && mIsActivity && mAnim.getExtensionEdges() != 0) {
                t.setEdgeExtensionEffect(leash, mAnim.getExtensionEdges());
            }
        if (position != null) {
            tmpTransformation.getMatrix().postTranslate(position.x, position.y);
            if (mPosition != null) {
                transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
            }
        t.setMatrix(leash, tmpTransformation.getMatrix(), matrix);
        t.setAlpha(leash, tmpTransformation.getAlpha());
            t.setMatrix(leash, transformation.getMatrix(), mMatrix);
            t.setAlpha(leash, transformation.getAlpha());

        final Rect clipRect = immutableClipRect == null ? null : new Rect(immutableClipRect);
        Insets extensionInsets = Insets.min(tmpTransformation.getInsets(), Insets.NONE);
        if (!extensionInsets.equals(Insets.NONE) && clipRect != null && !clipRect.isEmpty()) {
            // Clip out any overflowing edge extension
            if (mClipRect != null) {
                Rect clipRect = mClipRect;
                final Insets extensionInsets = Insets.min(transformation.getInsets(), Insets.NONE);
                if (!extensionInsets.equals(Insets.NONE)) {
                    // Clip out any overflowing edge extension.
                    clipRect = new Rect(mClipRect);
                    clipRect.inset(extensionInsets);
                    t.setCrop(leash, clipRect);
                }

        if (anim.hasRoundedCorners() && cornerRadius > 0 && clipRect != null) {
            // We can only apply rounded corner if a crop is set
                if (mCornerRadius > 0 && mAnim.hasRoundedCorners()) {
                    // Rounded corner can only be applied if a crop is set.
                    t.setCrop(leash, clipRect);
            t.setCornerRadius(leash, cornerRadius);
                    t.setCornerRadius(leash, mCornerRadius);
                }
            }
        }

        t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
        t.apply();
    }
}