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

Commit 4fa7f3f1 authored by Ikram Gabiyev's avatar Ikram Gabiyev Committed by Android (Google) Code Review
Browse files

Merge "Fix cross-fade legacy enter PiP2" into main

parents bcf0b0be 0cc5c6ea
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.app.WindowConfiguration
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Rect
import android.os.RemoteException
import android.os.SystemProperties
import android.util.DisplayMetrics
@@ -138,6 +139,30 @@ object PipUtils {
        }
    }


    /**
     * Returns a fake source rect hint for animation purposes when app-provided one is invalid.
     * Resulting adjusted source rect hint lets the app icon in the content overlay to stay visible.
     */
    @JvmStatic
    fun getEnterPipWithOverlaySrcRectHint(appBounds: Rect, aspectRatio: Float): Rect {
        val appBoundsAspRatio = appBounds.width().toFloat() / appBounds.height()
        val width: Int
        val height: Int
        var left = 0
        var top = 0
        if (appBoundsAspRatio < aspectRatio) {
            width = appBounds.width()
            height = Math.round(width / aspectRatio)
            top = (appBounds.height() - height) / 2
        } else {
            height = appBounds.height()
            width = Math.round(height * aspectRatio)
            left = (appBounds.width() - width) / 2
        }
        return Rect(left, top, left + width, top + height)
    }

    private var isPip2ExperimentEnabled: Boolean? = null

    /**
+3 −13
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.protolog.common.ProtoLog;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.transition.Transitions;

@@ -619,19 +620,8 @@ public class PipAnimationController {
                // This is done for entering case only.
                if (isInPipDirection(direction)) {
                    final float aspectRatio = endValue.width() / (float) endValue.height();
                    if ((startValue.width() / (float) startValue.height()) > aspectRatio) {
                        // use the full height.
                        adjustedSourceRectHint.set(0, 0,
                                (int) (startValue.height() * aspectRatio), startValue.height());
                        adjustedSourceRectHint.offset(
                                (startValue.width() - adjustedSourceRectHint.width()) / 2, 0);
                    } else {
                        // use the full width.
                        adjustedSourceRectHint.set(0, 0,
                                startValue.width(), (int) (startValue.width() / aspectRatio));
                        adjustedSourceRectHint.offset(
                                0, (startValue.height() - adjustedSourceRectHint.height()) / 2);
                    }
                    adjustedSourceRectHint.set(PipUtils.getEnterPipWithOverlaySrcRectHint(
                            startValue, aspectRatio));
                }
            } else {
                adjustedSourceRectHint.set(sourceRectHint);
+8 −1
Original line number Diff line number Diff line
@@ -19,11 +19,13 @@ package com.android.wm.shell.pip2.animation;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.content.Context;
import android.view.SurfaceControl;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.wm.shell.R;
import com.android.wm.shell.pip2.PipSurfaceTransactionHelper;

import java.lang.annotation.Retention;
@@ -45,6 +47,7 @@ public class PipAlphaAnimator extends ValueAnimator implements ValueAnimator.Ani
    public static final int FADE_IN = 0;
    public static final int FADE_OUT = 1;

    private final int mEnterAnimationDuration;
    private final SurfaceControl mLeash;
    private final SurfaceControl.Transaction mStartTransaction;

@@ -55,7 +58,8 @@ public class PipAlphaAnimator extends ValueAnimator implements ValueAnimator.Ani
    private final PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
            mSurfaceControlTransactionFactory;

    public PipAlphaAnimator(SurfaceControl leash,
    public PipAlphaAnimator(Context context,
            SurfaceControl leash,
            SurfaceControl.Transaction tx,
            @Fade int direction) {
        mLeash = leash;
@@ -67,6 +71,9 @@ public class PipAlphaAnimator extends ValueAnimator implements ValueAnimator.Ani
        }
        mSurfaceControlTransactionFactory =
                new PipSurfaceTransactionHelper.VsyncSurfaceControlTransactionFactory();
        mEnterAnimationDuration = context.getResources()
                .getInteger(R.integer.config_pipEnterAnimationDuration);
        setDuration(mEnterAnimationDuration);
        addListener(this);
        addUpdateListener(this);
    }
+37 −34
Original line number Diff line number Diff line
@@ -293,37 +293,32 @@ public class PipTransition extends PipTransitionController implements
            return false;
        }

        SurfaceControl overlayLeash = mPipTransitionState.getSwipePipToHomeOverlay();
        PictureInPictureParams params = pipChange.getTaskInfo().pictureInPictureParams;
        Rect srcRectHint = params.getSourceRectHint();
        Rect startBounds = pipChange.getStartAbsBounds();

        Rect appBounds = mPipTransitionState.getSwipePipToHomeAppBounds();
        Rect destinationBounds = pipChange.getEndAbsBounds();

        float aspectRatio = pipChange.getTaskInfo().pictureInPictureParams.getAspectRatioFloat();

        // We fake the source rect hint when the one prvided by the app is invalid for
        // the animation with an app icon overlay.
        Rect animationSrcRectHint = overlayLeash == null ? params.getSourceRectHint()
                : PipUtils.getEnterPipWithOverlaySrcRectHint(appBounds, aspectRatio);

        WindowContainerTransaction finishWct = new WindowContainerTransaction();
        SurfaceControl.Transaction tx = new SurfaceControl.Transaction();

        if (PipBoundsAlgorithm.isSourceRectHintValidForEnterPip(srcRectHint, destinationBounds)) {
            final float scale = (float) destinationBounds.width() / srcRectHint.width();
            startTransaction.setWindowCrop(pipLeash, srcRectHint);
        final float scale = (float) destinationBounds.width() / animationSrcRectHint.width();
        startTransaction.setWindowCrop(pipLeash, animationSrcRectHint);
        startTransaction.setPosition(pipLeash,
                    destinationBounds.left - srcRectHint.left * scale,
                    destinationBounds.top - srcRectHint.top * scale);

            // Reset the scale in case we are in the multi-activity case.
            // TO_FRONT transition already scales down the task in single-activity case, but
            // in multi-activity case, reparenting yields new reset scales coming from pinned task.
                destinationBounds.left - animationSrcRectHint.left * scale,
                destinationBounds.top - animationSrcRectHint.top * scale);
        startTransaction.setScale(pipLeash, scale, scale);
        } else {
            final float scaleX = (float) destinationBounds.width() / startBounds.width();
            final float scaleY = (float) destinationBounds.height() / startBounds.height();

        if (overlayLeash != null) {
            final int overlaySize = PipContentOverlay.PipAppIconOverlay.getOverlaySize(
                    mPipTransitionState.getSwipePipToHomeAppBounds(), destinationBounds);
            SurfaceControl overlayLeash = mPipTransitionState.getSwipePipToHomeOverlay();

            startTransaction.setPosition(pipLeash, destinationBounds.left, destinationBounds.top)
                    .setScale(pipLeash, scaleX, scaleY)
                    .setWindowCrop(pipLeash, startBounds)
                    .reparent(overlayLeash, pipLeash)
                    .setLayer(overlayLeash, Integer.MAX_VALUE);

            // Overlay needs to be adjusted once a new draw comes in resetting surface transform.
            tx.setScale(overlayLeash, 1f, 1f);
@@ -390,15 +385,23 @@ public class PipTransition extends PipTransitionController implements
        if (pipChange == null) {
            return false;
        }
        // cache the PiP task token and leash
        WindowContainerToken pipTaskToken = pipChange.getContainer();

        Preconditions.checkNotNull(mPipLeash, "Leash is null for alpha transition.");
        // start transition with 0 alpha
        startTransaction.setAlpha(mPipLeash, 0f);
        PipAlphaAnimator animator = new PipAlphaAnimator(mPipLeash,
                startTransaction, PipAlphaAnimator.FADE_IN);
        animator.setAnimationEndCallback(() -> finishCallback.onTransitionFinished(null));
        Rect destinationBounds = pipChange.getEndAbsBounds();
        SurfaceControl pipLeash = mPipTransitionState.mPinnedTaskLeash;
        Preconditions.checkNotNull(pipLeash, "Leash is null for alpha transition.");

        // Start transition with 0 alpha at the entry bounds.
        startTransaction.setPosition(pipLeash, destinationBounds.left, destinationBounds.top)
                .setWindowCrop(pipLeash, destinationBounds.width(), destinationBounds.height())
                .setAlpha(pipLeash, 0f);

        PipAlphaAnimator animator = new PipAlphaAnimator(mContext, pipLeash, startTransaction,
                PipAlphaAnimator.FADE_IN);
        animator.setAnimationEndCallback(() -> {
            finishCallback.onTransitionFinished(null);
            // This should update the pip transition state accordingly after we stop playing.
            onClientDrawAtTransitionEnd();
        });

        animator.start();
        return true;
@@ -480,10 +483,10 @@ public class PipTransition extends PipTransitionController implements

    private boolean isLegacyEnter(@NonNull TransitionInfo info) {
        TransitionInfo.Change pipChange = getPipChange(info);
        // If the only change in the changes list is a TO_FRONT mode PiP task,
        // If the only change in the changes list is a opening type PiP task,
        // then this is legacy-enter PiP.
        return pipChange != null && pipChange.getMode() == TRANSIT_TO_FRONT
                && info.getChanges().size() == 1;
        return pipChange != null && info.getChanges().size() == 1
                && (pipChange.getMode() == TRANSIT_TO_FRONT || pipChange.getMode() == TRANSIT_OPEN);
    }

    private boolean isRemovePipTransition(@NonNull TransitionInfo info) {