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

Commit 0818969c authored by Robert Horvath's avatar Robert Horvath Committed by Automerger Merge Worker
Browse files

Merge changes I49d32c18,I8e8736fc into tm-dev am: d338520c

parents 976817a2 d338520c
Loading
Loading
Loading
Loading
+21 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.dagger;

import android.content.Context;
import android.os.Handler;
import android.os.SystemClock;

import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
@@ -39,6 +40,7 @@ import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.PipTransitionState;
import com.android.wm.shell.pip.PipUiEventLogger;
import com.android.wm.shell.pip.tv.TvPipBoundsAlgorithm;
import com.android.wm.shell.pip.tv.TvPipBoundsController;
import com.android.wm.shell.pip.tv.TvPipBoundsState;
import com.android.wm.shell.pip.tv.TvPipController;
import com.android.wm.shell.pip.tv.TvPipMenuController;
@@ -64,6 +66,7 @@ public abstract class TvPipModule {
            Context context,
            TvPipBoundsState tvPipBoundsState,
            TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
            TvPipBoundsController tvPipBoundsController,
            PipAppOpsListener pipAppOpsListener,
            PipTaskOrganizer pipTaskOrganizer,
            TvPipMenuController tvPipMenuController,
@@ -74,13 +77,13 @@ public abstract class TvPipModule {
            PipParamsChangedForwarder pipParamsChangedForwarder,
            DisplayController displayController,
            WindowManagerShellWrapper windowManagerShellWrapper,
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellMainThread Handler mainHandler) {
            @ShellMainThread ShellExecutor mainExecutor) {
        return Optional.of(
                TvPipController.create(
                        context,
                        tvPipBoundsState,
                        tvPipBoundsAlgorithm,
                        tvPipBoundsController,
                        pipAppOpsListener,
                        pipTaskOrganizer,
                        pipTransitionController,
@@ -91,8 +94,22 @@ public abstract class TvPipModule {
                        pipParamsChangedForwarder,
                        displayController,
                        windowManagerShellWrapper,
                        mainExecutor,
                        mainHandler));
                        mainExecutor));
    }

    @WMSingleton
    @Provides
    static TvPipBoundsController provideTvPipBoundsController(
            Context context,
            @ShellMainThread Handler mainHandler,
            TvPipBoundsState tvPipBoundsState,
            TvPipBoundsAlgorithm tvPipBoundsAlgorithm) {
        return new TvPipBoundsController(
                context,
                SystemClock::uptimeMillis,
                mainHandler,
                tvPipBoundsState,
                tvPipBoundsAlgorithm);
    }

    @WMSingleton
+18 −12
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.SystemClock;
import android.util.ArraySet;
import android.util.Size;
import android.view.Gravity;
@@ -66,7 +65,7 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm {
            @NonNull PipSnapAlgorithm pipSnapAlgorithm) {
        super(context, tvPipBoundsState, pipSnapAlgorithm);
        this.mTvPipBoundsState = tvPipBoundsState;
        this.mKeepClearAlgorithm = new TvPipKeepClearAlgorithm(SystemClock::uptimeMillis);
        this.mKeepClearAlgorithm = new TvPipKeepClearAlgorithm();
        reloadResources(context);
    }

@@ -80,7 +79,6 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm {
                res.getDimensionPixelSize(R.dimen.pip_keep_clear_area_padding));
        mKeepClearAlgorithm.setMaxRestrictedDistanceFraction(
                res.getFraction(R.fraction.config_pipMaxRestrictedMoveDistance, 1, 1));
        mKeepClearAlgorithm.setStashDuration(res.getInteger(R.integer.config_pipStashDuration));
    }

    @Override
@@ -104,7 +102,7 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm {
            updateGravityOnExpandToggled(Gravity.NO_GRAVITY, true);
        }
        mTvPipBoundsState.setTvPipExpanded(isPipExpanded);
        return getTvPipBounds().getBounds();
        return adjustBoundsForTemporaryDecor(getTvPipPlacement().getBounds());
    }

    /** Returns the current bounds adjusted to the new aspect ratio, if valid. */
@@ -114,13 +112,27 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: getAdjustedDestinationBounds: %f", TAG, newAspectRatio);
        }
        return getTvPipBounds().getBounds();
        return adjustBoundsForTemporaryDecor(getTvPipPlacement().getBounds());
    }

    Rect adjustBoundsForTemporaryDecor(Rect bounds) {
        Rect boundsWithDecor = new Rect(bounds);
        Insets decorInset = mTvPipBoundsState.getPipMenuTemporaryDecorInsets();
        Insets pipDecorReverseInsets = Insets.subtract(Insets.NONE, decorInset);
        boundsWithDecor.inset(decorInset);
        Gravity.apply(mTvPipBoundsState.getTvPipGravity(),
                boundsWithDecor.width(), boundsWithDecor.height(), bounds, boundsWithDecor);

        // remove temporary decoration again
        boundsWithDecor.inset(pipDecorReverseInsets);
        return boundsWithDecor;
    }

    /**
     * Calculates the PiP bounds.
     */
    public Placement getTvPipBounds() {
    @NonNull
    public Placement getTvPipPlacement() {
        final Size pipSize = getPipSize();
        final Rect displayBounds = mTvPipBoundsState.getDisplayBounds();
        final Size screenSize = new Size(displayBounds.width(), displayBounds.height());
@@ -153,8 +165,6 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm {
        mKeepClearAlgorithm.setStashOffset(mTvPipBoundsState.getStashOffset());
        mKeepClearAlgorithm.setPipPermanentDecorInsets(
                mTvPipBoundsState.getPipMenuPermanentDecorInsets());
        mKeepClearAlgorithm.setPipTemporaryDecorInsets(
                mTvPipBoundsState.getPipMenuTemporaryDecorInsets());

        final Placement placement = mKeepClearAlgorithm.calculatePipPosition(
                pipSize,
@@ -407,8 +417,4 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm {
                    TAG, expandedSize.getWidth(), expandedSize.getHeight());
        }
    }

    void keepUnstashedForCurrentKeepClearAreas() {
        mKeepClearAlgorithm.keepUnstashedForCurrentKeepClearAreas();
    }
}
+253 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.wm.shell.pip.tv;

import static com.android.wm.shell.pip.PipBoundsState.STASH_TYPE_NONE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Handler;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R;
import com.android.wm.shell.pip.tv.TvPipKeepClearAlgorithm.Placement;
import com.android.wm.shell.protolog.ShellProtoLogGroup;

import java.util.Objects;
import java.util.function.Supplier;

/**
 * Controller managing the PiP's position.
 * Manages debouncing of PiP movements and scheduling of unstashing.
 */
public class TvPipBoundsController {
    private static final boolean DEBUG = false;
    private static final String TAG = "TvPipBoundsController";

    /**
     * Time the calculated PiP position needs to be stable before PiP is moved there,
     * to avoid erratic movement.
     * Some changes will cause the PiP to be repositioned immediately, such as changes to
     * unrestricted keep clear areas.
     */
    @VisibleForTesting
    static final long POSITION_DEBOUNCE_TIMEOUT_MILLIS = 300L;

    private final Context mContext;
    private final Supplier<Long> mClock;
    private final Handler mMainHandler;
    private final TvPipBoundsState mTvPipBoundsState;
    private final TvPipBoundsAlgorithm mTvPipBoundsAlgorithm;

    @Nullable
    private PipBoundsListener mListener;

    private int mResizeAnimationDuration;
    private int mStashDurationMs;
    private Rect mCurrentPlacementBounds;
    private Rect mPipTargetBounds;

    private final Runnable mApplyPendingPlacementRunnable = this::applyPendingPlacement;
    private boolean mPendingStash;
    private Placement mPendingPlacement;
    private int mPendingPlacementAnimationDuration;
    private Runnable mUnstashRunnable;

    public TvPipBoundsController(
            Context context,
            Supplier<Long> clock,
            Handler mainHandler,
            TvPipBoundsState tvPipBoundsState,
            TvPipBoundsAlgorithm tvPipBoundsAlgorithm) {
        mContext = context;
        mClock = clock;
        mMainHandler = mainHandler;
        mTvPipBoundsState = tvPipBoundsState;
        mTvPipBoundsAlgorithm = tvPipBoundsAlgorithm;

        loadConfigurations();
    }

    private void loadConfigurations() {
        final Resources res = mContext.getResources();
        mResizeAnimationDuration = res.getInteger(R.integer.config_pipResizeAnimationDuration);
        mStashDurationMs = res.getInteger(R.integer.config_pipStashDuration);
    }

    void setListener(PipBoundsListener listener) {
        mListener = listener;
    }

    /**
     * Update the PiP bounds based on the state of the PiP, decors, and keep clear areas.
     * Unless {@code immediate} is {@code true}, the PiP does not move immediately to avoid
     * keep clear areas, but waits for a new position to stay uncontested for
     * {@link #POSITION_DEBOUNCE_TIMEOUT_MILLIS} before moving to it.
     * Temporary decor changes are applied immediately.
     *
     * @param stayAtAnchorPosition If true, PiP will be placed at the anchor position
     * @param disallowStashing     If true, PiP will not be placed off-screen in a stashed position
     * @param animationDuration    Duration of the animation to the new position
     * @param immediate            If true, PiP will move immediately to avoid keep clear areas
     */
    @VisibleForTesting
    void recalculatePipBounds(boolean stayAtAnchorPosition, boolean disallowStashing,
            int animationDuration, boolean immediate) {
        final Placement placement = mTvPipBoundsAlgorithm.getTvPipPlacement();

        final int stashType = disallowStashing ? STASH_TYPE_NONE : placement.getStashType();
        mTvPipBoundsState.setStashed(stashType);
        if (stayAtAnchorPosition) {
            cancelScheduledPlacement();
            applyPlacementBounds(placement.getAnchorBounds(), animationDuration);
        } else if (disallowStashing) {
            cancelScheduledPlacement();
            applyPlacementBounds(placement.getUnstashedBounds(), animationDuration);
        } else if (immediate) {
            cancelScheduledPlacement();
            applyPlacementBounds(placement.getBounds(), animationDuration);
            scheduleUnstashIfNeeded(placement);
        } else {
            applyPlacementBounds(mCurrentPlacementBounds, animationDuration);
            schedulePinnedStackPlacement(placement, animationDuration);
        }
    }

    private void schedulePinnedStackPlacement(@NonNull final Placement placement,
            int animationDuration) {
        if (DEBUG) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: schedulePinnedStackPlacement() - pip bounds: %s",
                    TAG, placement.getBounds().toShortString());
        }

        if (mPendingPlacement != null && Objects.equals(mPendingPlacement.getBounds(),
                placement.getBounds())) {
            mPendingStash = mPendingStash || placement.getTriggerStash();
            return;
        }

        mPendingStash = placement.getStashType() != STASH_TYPE_NONE
                && (mPendingStash || placement.getTriggerStash());

        mMainHandler.removeCallbacks(mApplyPendingPlacementRunnable);
        mPendingPlacement = placement;
        mPendingPlacementAnimationDuration = animationDuration;
        mMainHandler.postAtTime(mApplyPendingPlacementRunnable,
                mClock.get() + POSITION_DEBOUNCE_TIMEOUT_MILLIS);
    }

    private void scheduleUnstashIfNeeded(final Placement placement) {
        if (mUnstashRunnable != null) {
            mMainHandler.removeCallbacks(mUnstashRunnable);
            mUnstashRunnable = null;
        }
        if (placement.getUnstashDestinationBounds() != null) {
            mUnstashRunnable = () -> {
                applyPlacementBounds(placement.getUnstashDestinationBounds(),
                        mResizeAnimationDuration);
                mUnstashRunnable = null;
            };
            mMainHandler.postAtTime(mUnstashRunnable, mClock.get() + mStashDurationMs);
        }
    }

    private void applyPendingPlacement() {
        if (DEBUG) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: applyPendingPlacement()", TAG);
        }
        if (mPendingPlacement != null) {
            if (mPendingStash) {
                mPendingStash = false;
                scheduleUnstashIfNeeded(mPendingPlacement);
            }

            if (mUnstashRunnable != null) {
                // currently stashed, use stashed pos
                applyPlacementBounds(mPendingPlacement.getBounds(),
                        mPendingPlacementAnimationDuration);
            } else {
                applyPlacementBounds(mPendingPlacement.getUnstashedBounds(),
                        mPendingPlacementAnimationDuration);
            }
        }

        mPendingPlacement = null;
    }

    void onPipDismissed() {
        mCurrentPlacementBounds = null;
        mPipTargetBounds = null;
        cancelScheduledPlacement();
    }

    private void cancelScheduledPlacement() {
        mMainHandler.removeCallbacks(mApplyPendingPlacementRunnable);
        mPendingPlacement = null;

        if (mUnstashRunnable != null) {
            mMainHandler.removeCallbacks(mUnstashRunnable);
            mUnstashRunnable = null;
        }
    }

    private void applyPlacementBounds(Rect bounds, int animationDuration) {
        if (bounds == null) {
            return;
        }

        mCurrentPlacementBounds = bounds;
        Rect adjustedBounds = mTvPipBoundsAlgorithm.adjustBoundsForTemporaryDecor(bounds);
        movePipTo(adjustedBounds, animationDuration);
    }

    /** Animates the PiP to the given bounds with the given animation duration. */
    private void movePipTo(Rect bounds, int animationDuration) {
        if (Objects.equals(mPipTargetBounds, bounds)) {
            return;
        }

        mPipTargetBounds = bounds;
        if (DEBUG) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: movePipTo() - new pip bounds: %s", TAG, bounds.toShortString());
        }

        if (mListener != null) {
            mListener.onPipTargetBoundsChange(bounds, animationDuration);
        }
    }

    /**
     * Interface being notified of changes to the PiP bounds as calculated by
     * @link TvPipBoundsController}.
     */
    public interface PipBoundsListener {
        /**
         * Called when the calculated PiP bounds are changing.
         *
         * @param newTargetBounds The new bounds of the PiP.
         * @param animationDuration The animation duration for the PiP movement.
         */
        void onPipTargetBoundsChange(Rect newTargetBounds, int animationDuration);
    }
}
+27 −63
Original line number Diff line number Diff line
@@ -25,12 +25,10 @@ import android.app.ActivityTaskManager;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.view.Gravity;

@@ -46,25 +44,24 @@ import com.android.wm.shell.pip.PinnedStackListenerForwarder;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipAppOpsListener;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.tv.TvPipKeepClearAlgorithm.Placement;
import com.android.wm.shell.protolog.ShellProtoLogGroup;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Manages the picture-in-picture (PIP) UI and states.
 */
public class TvPipController implements PipTransitionController.PipTransitionCallback,
        TvPipMenuController.Delegate, TvPipNotificationController.Delegate,
        DisplayController.OnDisplaysChangedListener {
        TvPipBoundsController.PipBoundsListener, TvPipMenuController.Delegate,
        TvPipNotificationController.Delegate, DisplayController.OnDisplaysChangedListener {
    private static final String TAG = "TvPipController";
    static final boolean DEBUG = false;

@@ -98,19 +95,18 @@ public class TvPipController implements PipTransitionController.PipTransitionCal

    private final TvPipBoundsState mTvPipBoundsState;
    private final TvPipBoundsAlgorithm mTvPipBoundsAlgorithm;
    private final TvPipBoundsController mTvPipBoundsController;
    private final PipAppOpsListener mAppOpsListener;
    private final PipTaskOrganizer mPipTaskOrganizer;
    private final PipMediaController mPipMediaController;
    private final TvPipNotificationController mPipNotificationController;
    private final TvPipMenuController mTvPipMenuController;
    private final ShellExecutor mMainExecutor;
    private final Handler mMainHandler;
    private final TvPipImpl mImpl = new TvPipImpl();

    private @State int mState = STATE_NO_PIP;
    private int mPreviousGravity = TvPipBoundsState.DEFAULT_TV_GRAVITY;
    private int mPinnedTaskId = NONEXISTENT_TASK_ID;
    private Runnable mUnstashRunnable;

    private RemoteAction mCloseAction;
    // How long the shell will wait for the app to close the PiP if a custom action is set.
@@ -123,6 +119,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
            Context context,
            TvPipBoundsState tvPipBoundsState,
            TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
            TvPipBoundsController tvPipBoundsController,
            PipAppOpsListener pipAppOpsListener,
            PipTaskOrganizer pipTaskOrganizer,
            PipTransitionController pipTransitionController,
@@ -133,12 +130,12 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
            PipParamsChangedForwarder pipParamsChangedForwarder,
            DisplayController displayController,
            WindowManagerShellWrapper wmShell,
            ShellExecutor mainExecutor,
            Handler mainHandler) {
            ShellExecutor mainExecutor) {
        return new TvPipController(
                context,
                tvPipBoundsState,
                tvPipBoundsAlgorithm,
                tvPipBoundsController,
                pipAppOpsListener,
                pipTaskOrganizer,
                pipTransitionController,
@@ -149,14 +146,14 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
                pipParamsChangedForwarder,
                displayController,
                wmShell,
                mainExecutor,
                mainHandler).mImpl;
                mainExecutor).mImpl;
    }

    private TvPipController(
            Context context,
            TvPipBoundsState tvPipBoundsState,
            TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
            TvPipBoundsController tvPipBoundsController,
            PipAppOpsListener pipAppOpsListener,
            PipTaskOrganizer pipTaskOrganizer,
            PipTransitionController pipTransitionController,
@@ -167,16 +164,16 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
            PipParamsChangedForwarder pipParamsChangedForwarder,
            DisplayController displayController,
            WindowManagerShellWrapper wmShell,
            ShellExecutor mainExecutor,
            Handler mainHandler) {
            ShellExecutor mainExecutor) {
        mContext = context;
        mMainExecutor = mainExecutor;
        mMainHandler = mainHandler;

        mTvPipBoundsState = tvPipBoundsState;
        mTvPipBoundsState.setDisplayId(context.getDisplayId());
        mTvPipBoundsState.setDisplayLayout(new DisplayLayout(context, context.getDisplay()));
        mTvPipBoundsAlgorithm = tvPipBoundsAlgorithm;
        mTvPipBoundsController = tvPipBoundsController;
        mTvPipBoundsController.setListener(this);

        mPipMediaController = pipMediaController;

@@ -227,7 +224,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
    /**
     * Starts the process if bringing up the Pip menu if by issuing a command to move Pip
     * task/window to the "Menu" position. We'll show the actual Menu UI (eg. actions) once the Pip
     * task/window is properly positioned in {@link #onPipTransitionFinished(ComponentName, int)}.
     * task/window is properly positioned in {@link #onPipTransitionFinished(int)}.
     */
    @Override
    public void showPictureInPictureMenu() {
@@ -256,7 +253,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
                    "%s: closeMenu(), state before=%s", TAG, stateToName(mState));
        }
        setState(STATE_PIP);
        mTvPipBoundsAlgorithm.keepUnstashedForCurrentKeepClearAreas();
        updatePinnedStackBounds();
    }

@@ -331,68 +327,35 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
    public void onKeepClearAreasChanged(int displayId, Set<Rect> restricted,
            Set<Rect> unrestricted) {
        if (mTvPipBoundsState.getDisplayId() == displayId) {
            boolean unrestrictedAreasChanged = !Objects.equals(unrestricted,
                    mTvPipBoundsState.getUnrestrictedKeepClearAreas());
            mTvPipBoundsState.setKeepClearAreas(restricted, unrestricted);
            updatePinnedStackBounds();
            updatePinnedStackBounds(mResizeAnimationDuration, unrestrictedAreasChanged);
        }
    }

    private void updatePinnedStackBounds() {
        updatePinnedStackBounds(mResizeAnimationDuration);
        updatePinnedStackBounds(mResizeAnimationDuration, true);
    }

    /**
     * Update the PiP bounds based on the state of the PiP and keep clear areas.
     * Animates to the current PiP bounds, and schedules unstashing the PiP if necessary.
     */
    private void updatePinnedStackBounds(int animationDuration) {
    private void updatePinnedStackBounds(int animationDuration, boolean immediate) {
        if (mState == STATE_NO_PIP) {
            return;
        }

        final boolean stayAtAnchorPosition = mTvPipMenuController.isInMoveMode();
        final boolean disallowStashing = mState == STATE_PIP_MENU || stayAtAnchorPosition;
        final Placement placement = mTvPipBoundsAlgorithm.getTvPipBounds();

        int stashType =
                disallowStashing ? PipBoundsState.STASH_TYPE_NONE : placement.getStashType();
        mTvPipBoundsState.setStashed(stashType);

        if (stayAtAnchorPosition) {
            movePinnedStackTo(placement.getAnchorBounds());
        } else if (disallowStashing) {
            movePinnedStackTo(placement.getUnstashedBounds());
        } else {
            movePinnedStackTo(placement.getBounds());
        }

        if (mUnstashRunnable != null) {
            mMainHandler.removeCallbacks(mUnstashRunnable);
            mUnstashRunnable = null;
        }
        if (!disallowStashing && placement.getUnstashDestinationBounds() != null) {
            mUnstashRunnable = () -> {
                movePinnedStackTo(placement.getUnstashDestinationBounds(), animationDuration);
            };
            mMainHandler.postAtTime(mUnstashRunnable, placement.getUnstashTime());
        }
        mTvPipBoundsController.recalculatePipBounds(stayAtAnchorPosition, disallowStashing,
                animationDuration, immediate);
    }

    /** Animates the PiP to the given bounds. */
    private void movePinnedStackTo(Rect bounds) {
        movePinnedStackTo(bounds, mResizeAnimationDuration);
    }

    /** Animates the PiP to the given bounds with the given animation duration. */
    private void movePinnedStackTo(Rect bounds, int animationDuration) {
        if (DEBUG) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: movePinnedStack() - new pip bounds: %s", TAG, bounds.toShortString());
        }
        mPipTaskOrganizer.scheduleAnimateResizePip(bounds,
                animationDuration, rect -> {
                    mTvPipMenuController.updateExpansionState();
                });
        mTvPipMenuController.onPipTransitionStarted(bounds);
    @Override
    public void onPipTargetBoundsChange(Rect newTargetBounds, int animationDuration) {
        mPipTaskOrganizer.scheduleAnimateResizePip(newTargetBounds,
                animationDuration, rect -> mTvPipMenuController.updateExpansionState());
        mTvPipMenuController.onPipTransitionStarted(newTargetBounds);
    }

    /**
@@ -431,7 +394,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal

    @Override
    public void closeEduText() {
        updatePinnedStackBounds(mEduTextWindowExitAnimationDurationMs);
        updatePinnedStackBounds(mEduTextWindowExitAnimationDurationMs, false);
    }

    private void registerSessionListenerForCurrentUser() {
@@ -473,6 +436,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
        mPipNotificationController.dismiss();
        mTvPipMenuController.closeMenu();
        mTvPipBoundsState.resetTvPipState();
        mTvPipBoundsController.onPipDismissed();
        setState(STATE_NO_PIP);
        mPinnedTaskId = NONEXISTENT_TASK_ID;
    }
+12 −66

File changed.

Preview size limit exceeded, changes collapsed.

Loading