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

Commit 75646e90 authored by Hongwei Wang's avatar Hongwei Wang Committed by Android (Google) Code Review
Browse files

Merge "Use cached launcher shelf KCA before entering PiP" into main

parents e18b3ffa 273c5220
Loading
Loading
Loading
Loading
+61 −28
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.graphics.Rect;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Size;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
@@ -42,9 +43,7 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
@@ -69,26 +68,36 @@ public class PipBoundsState {
    @Retention(RetentionPolicy.SOURCE)
    public @interface StashType {}

    public static final int NAMED_KCA_LAUNCHER_SHELF = 0;
    public static final int NAMED_KCA_TABLETOP_MODE = 1;

    @IntDef(prefix = { "NAMED_KCA_" }, value = {
            NAMED_KCA_LAUNCHER_SHELF,
            NAMED_KCA_TABLETOP_MODE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface NamedKca {}

    private static final String TAG = PipBoundsState.class.getSimpleName();

    private final @NonNull Rect mBounds = new Rect();
    private final @NonNull Rect mMovementBounds = new Rect();
    private final @NonNull Rect mNormalBounds = new Rect();
    private final @NonNull Rect mExpandedBounds = new Rect();
    private final @NonNull Rect mNormalMovementBounds = new Rect();
    private final @NonNull Rect mExpandedMovementBounds = new Rect();
    private final @NonNull PipDisplayLayoutState mPipDisplayLayoutState;
    @NonNull private final Rect mBounds = new Rect();
    @NonNull private final Rect mMovementBounds = new Rect();
    @NonNull private final Rect mNormalBounds = new Rect();
    @NonNull private final Rect mExpandedBounds = new Rect();
    @NonNull private final Rect mNormalMovementBounds = new Rect();
    @NonNull private final Rect mExpandedMovementBounds = new Rect();
    @NonNull private final PipDisplayLayoutState mPipDisplayLayoutState;
    private final Point mMaxSize = new Point();
    private final Point mMinSize = new Point();
    private final @NonNull Context mContext;
    @NonNull private final Context mContext;
    private float mAspectRatio;
    private int mStashedState = STASH_TYPE_NONE;
    private int mStashOffset;
    private @Nullable PipReentryState mPipReentryState;
    @Nullable private PipReentryState mPipReentryState;
    private final LauncherState mLauncherState = new LauncherState();
    private final @NonNull SizeSpecSource mSizeSpecSource;
    private @Nullable ComponentName mLastPipComponentName;
    private final @NonNull MotionBoundsState mMotionBoundsState = new MotionBoundsState();
    @NonNull private final SizeSpecSource mSizeSpecSource;
    @Nullable private ComponentName mLastPipComponentName;
    @NonNull private final MotionBoundsState mMotionBoundsState = new MotionBoundsState();
    private boolean mIsImeShowing;
    private int mImeHeight;
    private boolean mIsShelfShowing;
@@ -120,12 +129,18 @@ public class PipBoundsState {
     * as unrestricted keep clear area. Values in this map would be appended to
     * {@link #getUnrestrictedKeepClearAreas()} and this is meant for internal usage only.
     */
    private final Map<String, Rect> mNamedUnrestrictedKeepClearAreas = new HashMap<>();
    private final SparseArray<Rect> mNamedUnrestrictedKeepClearAreas = new SparseArray<>();

    private @Nullable Runnable mOnMinimalSizeChangeCallback;
    private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback;
    private List<Consumer<Rect>> mOnPipExclusionBoundsChangeCallbacks = new ArrayList<>();
    private List<Consumer<Float>> mOnAspectRatioChangedCallbacks = new ArrayList<>();
    @Nullable private Runnable mOnMinimalSizeChangeCallback;
    @Nullable private TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback;
    private final List<Consumer<Rect>> mOnPipExclusionBoundsChangeCallbacks = new ArrayList<>();
    private final List<Consumer<Float>> mOnAspectRatioChangedCallbacks = new ArrayList<>();

    /**
     * This is used to set the launcher shelf height ahead of non-auto-enter-pip animation,
     * to avoid the race condition. See also {@link #NAMED_KCA_LAUNCHER_SHELF}.
     */
    public final Rect mCachedLauncherShelfHeightKeepClearArea = new Rect();

    // the size of the current bounds relative to the max size spec
    private float mBoundsScale;
@@ -430,16 +445,31 @@ public class PipBoundsState {
        mUnrestrictedKeepClearAreas.addAll(unrestrictedAreas);
    }

    /** Add a named unrestricted keep clear area. */
    public void addNamedUnrestrictedKeepClearArea(@NonNull String name, Rect unrestrictedArea) {
        mNamedUnrestrictedKeepClearAreas.put(name, unrestrictedArea);
    /** Set a named unrestricted keep clear area. */
    public void setNamedUnrestrictedKeepClearArea(
            @NamedKca int tag, @Nullable Rect unrestrictedArea) {
        if (unrestrictedArea == null) {
            mNamedUnrestrictedKeepClearAreas.remove(tag);
        } else {
            mNamedUnrestrictedKeepClearAreas.put(tag, unrestrictedArea);
            if (tag == NAMED_KCA_LAUNCHER_SHELF) {
                mCachedLauncherShelfHeightKeepClearArea.set(unrestrictedArea);
            }
        }

    /** Remove a named unrestricted keep clear area. */
    public void removeNamedUnrestrictedKeepClearArea(@NonNull String name) {
        mNamedUnrestrictedKeepClearAreas.remove(name);
    }

    /**
     * Forcefully set the keep-clear-area for launcher shelf height if applicable.
     * This is used for entering PiP in button navigation mode to make sure the destination bounds
     * calculation includes the shelf height, to avoid race conditions that such callback is sent
     * from Launcher after the entering animation is started.
     */
    public void mayUseCachedLauncherShelfHeight() {
        if (!mCachedLauncherShelfHeightKeepClearArea.isEmpty()) {
            setNamedUnrestrictedKeepClearArea(
                    NAMED_KCA_LAUNCHER_SHELF, mCachedLauncherShelfHeightKeepClearArea);
        }
    }

    /**
     * @return restricted keep clear areas.
@@ -454,9 +484,12 @@ public class PipBoundsState {
     */
    @NonNull
    public Set<Rect> getUnrestrictedKeepClearAreas() {
        if (mNamedUnrestrictedKeepClearAreas.isEmpty()) return mUnrestrictedKeepClearAreas;
        if (mNamedUnrestrictedKeepClearAreas.size() == 0) return mUnrestrictedKeepClearAreas;
        final Set<Rect> unrestrictedAreas = new ArraySet<>(mUnrestrictedKeepClearAreas);
        unrestrictedAreas.addAll(mNamedUnrestrictedKeepClearAreas.values());
        for (int i = 0; i < mNamedUnrestrictedKeepClearAreas.size(); i++) {
            final int key = mNamedUnrestrictedKeepClearAreas.keyAt(i);
            unrestrictedAreas.add(mNamedUnrestrictedKeepClearAreas.get(key));
        }
        return unrestrictedAreas;
    }

+3 −0
Original line number Diff line number Diff line
@@ -1020,6 +1020,9 @@ public class PipTransition extends PipTransitionController {
            mPipMenuController.attach(leash);
        }

        // Make sure we have the launcher shelf into destination bounds calculation
        // before the animator starts.
        mPipBoundsState.mayUseCachedLauncherShelfHeight();
        final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
        final Rect currentBounds = pipChange.getStartAbsBounds();

+16 −12
Original line number Diff line number Diff line
@@ -646,9 +646,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb
                });

        mTabletopModeController.registerOnTabletopModeChangedListener((isInTabletopMode) -> {
            final String tag = "tabletop-mode";
            if (!isInTabletopMode) {
                mPipBoundsState.removeNamedUnrestrictedKeepClearArea(tag);
                mPipBoundsState.setNamedUnrestrictedKeepClearArea(
                        PipBoundsState.NAMED_KCA_TABLETOP_MODE, null);
                return;
            }

@@ -657,12 +657,14 @@ public class PipController implements PipTransitionController.PipTransitionCallb
            if (mTabletopModeController.getPreferredHalfInTabletopMode()
                    == TabletopModeController.PREFERRED_TABLETOP_HALF_TOP) {
                // Prefer top, avoid the bottom half of the display.
                mPipBoundsState.addNamedUnrestrictedKeepClearArea(tag, new Rect(
                mPipBoundsState.setNamedUnrestrictedKeepClearArea(
                        PipBoundsState.NAMED_KCA_TABLETOP_MODE, new Rect(
                                displayBounds.left, displayBounds.centerY(),
                                displayBounds.right, displayBounds.bottom));
            } else {
                // Prefer bottom, avoid the top half of the display.
                mPipBoundsState.addNamedUnrestrictedKeepClearArea(tag, new Rect(
                mPipBoundsState.setNamedUnrestrictedKeepClearArea(
                        PipBoundsState.NAMED_KCA_TABLETOP_MODE, new Rect(
                                displayBounds.left, displayBounds.top,
                                displayBounds.right, displayBounds.centerY()));
            }
@@ -916,10 +918,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb
                    0, mPipBoundsState.getDisplayBounds().bottom - height,
                    mPipBoundsState.getDisplayBounds().right,
                    mPipBoundsState.getDisplayBounds().bottom);
            mPipBoundsState.addNamedUnrestrictedKeepClearArea(LAUNCHER_KEEP_CLEAR_AREA_TAG, rect);
            mPipBoundsState.setNamedUnrestrictedKeepClearArea(
                    PipBoundsState.NAMED_KCA_LAUNCHER_SHELF, rect);
            updatePipPositionForKeepClearAreas();
        } else {
            mPipBoundsState.removeNamedUnrestrictedKeepClearArea(LAUNCHER_KEEP_CLEAR_AREA_TAG);
            mPipBoundsState.setNamedUnrestrictedKeepClearArea(
                    PipBoundsState.NAMED_KCA_LAUNCHER_SHELF, null);
            // postpone moving in response to hide of Launcher in case there's another change
            mMainExecutor.removeCallbacks(mMovePipInResponseToKeepClearAreasChangeCallback);
            mMainExecutor.executeDelayed(
@@ -968,8 +972,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb
            int launcherRotation, Rect hotseatKeepClearArea) {
        // preemptively add the keep clear area for Hotseat, so that it is taken into account
        // when calculating the entry destination bounds of PiP window
        mPipBoundsState.addNamedUnrestrictedKeepClearArea(LAUNCHER_KEEP_CLEAR_AREA_TAG,
                hotseatKeepClearArea);
        mPipBoundsState.setNamedUnrestrictedKeepClearArea(
                PipBoundsState.NAMED_KCA_LAUNCHER_SHELF, hotseatKeepClearArea);
        onDisplayRotationChangedNotInPip(mContext, launcherRotation);
        // cache current min/max size
        Point minSize = mPipBoundsState.getMinSize();