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

Commit 4dc41ab5 authored by Winson Chung's avatar Winson Chung
Browse files

Migrate to using DisplayLayout instead of DisplayInfo

- No need to keep two sources of truth, can just use display
  layout to  store/calcualte all the info we need
- Update the display layout on display configuration changed
  as well
- KI: When changing displays, the min size of the pip also
  changes so we will need to calculate that based on the
  smallest display size

Bug: 175644531
Test: atest PinnedStacktests
Test: atest WMShellUnitTests
Change-Id: I34614a8f739311c7b382b6848e4752fa68c91cfb
parent 7cb084a4
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@ import android.util.TypedValue;
import android.view.DisplayInfo;
import android.view.Gravity;

import com.android.wm.shell.common.DisplayLayout;

import java.io.PrintWriter;

/**
@@ -190,9 +192,9 @@ public class PipBoundsAlgorithm {
                size = adjustSizeToAspectRatio(overrideMinSize, aspectRatio);
            } else {
                // Calculate the default size using the display size and default min edge size.
                final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
                final DisplayLayout displayLayout = mPipBoundsState.getDisplayLayout();
                size = getSizeForAspectRatio(aspectRatio, mDefaultMinSize,
                        displayInfo.logicalWidth, displayInfo.logicalHeight);
                        displayLayout.width(), displayLayout.height());
            }
        }

@@ -232,7 +234,7 @@ public class PipBoundsAlgorithm {
        final Size defaultSize;
        final Rect insetBounds = new Rect();
        getInsetBounds(insetBounds);
        final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
        final DisplayLayout displayLayout = mPipBoundsState.getDisplayLayout();
        final Size overrideMinSize = mPipBoundsState.getOverrideMinSize();
        if (overrideMinSize != null) {
            // The override minimal size is set, use that as the default size making sure it's
@@ -241,7 +243,7 @@ public class PipBoundsAlgorithm {
        } else {
            // Calculate the default size using the display size and default min edge size.
            defaultSize = getSizeForAspectRatio(mDefaultAspectRatio,
                    mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight);
                    mDefaultMinSize, displayLayout.width(), displayLayout.height());
        }

        // Now that we have the default size, apply the snap fraction if valid or position the
@@ -264,12 +266,12 @@ public class PipBoundsAlgorithm {
     * Populates the bounds on the screen that the PIP can be visible in.
     */
    public void getInsetBounds(Rect outRect) {
        final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
        final DisplayLayout displayLayout = mPipBoundsState.getDisplayLayout();
        Rect insets = mPipBoundsState.getDisplayLayout().stableInsets();
        outRect.set(insets.left + mScreenEdgeInsets.x,
                insets.top + mScreenEdgeInsets.y,
                displayInfo.logicalWidth - insets.right - mScreenEdgeInsets.x,
                displayInfo.logicalHeight - insets.bottom - mScreenEdgeInsets.y);
                displayLayout.width() - insets.right - mScreenEdgeInsets.x,
                displayLayout.height() - insets.bottom - mScreenEdgeInsets.y);
    }

    /**
+10 −15
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Size;
import android.view.Display;
import android.view.DisplayInfo;

import com.android.internal.annotations.VisibleForTesting;
@@ -68,7 +69,7 @@ public final class PipBoundsState {
    private int mStashOffset;
    private @Nullable PipReentryState mPipReentryState;
    private @Nullable ComponentName mLastPipComponentName;
    private final @NonNull DisplayInfo mDisplayInfo = new DisplayInfo();
    private int mDisplayId = Display.DEFAULT_DISPLAY;
    private final @NonNull DisplayLayout mDisplayLayout = new DisplayLayout();
    /** The current minimum edge size of PIP. */
    private int mMinEdgeSize;
@@ -238,26 +239,20 @@ public final class PipBoundsState {
        return mLastPipComponentName;
    }

    /** Get the current display info. */
    @NonNull
    public DisplayInfo getDisplayInfo() {
        return mDisplayInfo;
    }

    /** Update the display info. */
    public void setDisplayInfo(@NonNull DisplayInfo displayInfo) {
        mDisplayInfo.copyFrom(displayInfo);
    /** Get the current display id. */
    public int getDisplayId() {
        return mDisplayId;
    }

    /** Set the rotation of the display. */
    public void setDisplayRotation(int rotation) {
        mDisplayInfo.rotation = rotation;
    /** Set the current display id for the associated display layout. */
    public void setDisplayId(int displayId) {
        mDisplayId = displayId;
    }

    /** Returns the display's bounds. */
    @NonNull
    public Rect getDisplayBounds() {
        return new Rect(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
        return new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
    }

    /** Update the display layout. */
@@ -474,7 +469,7 @@ public final class PipBoundsState {
        pw.println(innerPrefix + "mExpandedMovementBounds=" + mExpandedMovementBounds);
        pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
        pw.println(innerPrefix + "mAspectRatio=" + mAspectRatio);
        pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo);
        pw.println(innerPrefix + "mDisplayId=" + mDisplayId);
        pw.println(innerPrefix + "mDisplayLayout=" + mDisplayLayout);
        pw.println(innerPrefix + "mStashedState=" + mStashedState);
        pw.println(innerPrefix + "mStashOffset=" + mStashOffset);
+7 −2
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.os.RemoteException;
import android.util.Log;
import android.util.Rational;
import android.util.Size;
import android.view.Display;
import android.view.SurfaceControl;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
@@ -324,7 +325,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        mPipUiEventLoggerLogger.log(
                PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_EXPAND_TO_FULLSCREEN);
        final boolean orientationDiffers = initialConfig.windowConfiguration.getRotation()
                != mPipBoundsState.getDisplayInfo().rotation;
                != mPipBoundsState.getDisplayLayout().rotation();
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final Rect destinationBounds = initialConfig.windowConfiguration.getBounds();
        final int direction = syncWithSplitScreenBounds(destinationBounds)
@@ -437,7 +438,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,

        // If the displayId of the task is different than what PipBoundsHandler has, then update
        // it. This is possible if we entered PiP on an external display.
        if (info.displayId != mPipBoundsState.getDisplayInfo().displayId
        if (info.displayId != mPipBoundsState.getDisplayId()
                && mOnDisplayIdChangeCallback != null) {
            mOnDisplayIdChangeCallback.accept(info.displayId);
        }
@@ -605,6 +606,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        mState = State.UNDEFINED;
        mPipUiEventLoggerLogger.setTaskInfo(null);
        mPipMenuController.detach();

        if (info.displayId != Display.DEFAULT_DISPLAY && mOnDisplayIdChangeCallback != null) {
            mOnDisplayIdChangeCallback.accept(Display.DEFAULT_DISPLAY);
        }
    }

    @Override
+61 −56
Original line number Diff line number Diff line
@@ -19,8 +19,6 @@ package com.android.wm.shell.pip.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;

import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
@@ -86,7 +84,6 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
    private PipTouchHandler mTouchHandler;
    protected final PipImpl mImpl = new PipImpl();

    private final DisplayInfo mTmpDisplayInfo = new DisplayInfo();
    private final Rect mTmpInsetBounds = new Rect();

    private boolean mIsInFixedRotation;
@@ -145,7 +142,7 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
        }
    };

    private final DisplayController.OnDisplaysChangedListener mFixedRotationListener =
    private final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
            new DisplayController.OnDisplaysChangedListener() {
                @Override
                public void onFixedRotationStarted(int displayId, int newRotation) {
@@ -159,8 +156,20 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {

                @Override
                public void onDisplayAdded(int displayId) {
                    mPipBoundsState.setDisplayLayout(
                            mDisplayController.getDisplayLayout(displayId));
                    if (displayId != mPipBoundsState.getDisplayId()) {
                        return;
                    }
                    onDisplayChanged(mDisplayController.getDisplayLayout(displayId),
                            false /* saveRestoreSnapFraction */);
                }

                @Override
                public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
                    if (displayId != mPipBoundsState.getDisplayId()) {
                        return;
                    }
                    onDisplayChanged(mDisplayController.getDisplayLayout(displayId),
                            true /* saveRestoreSnapFraction */);
                }
            };

@@ -261,12 +270,9 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
                INPUT_CONSUMER_PIP, mainExecutor);
        mPipTaskOrganizer.registerPipTransitionCallback(this);
        mPipTaskOrganizer.registerOnDisplayIdChangeCallback((int displayId) -> {
            final DisplayInfo newDisplayInfo = new DisplayInfo();
            displayController.getDisplay(displayId).getDisplayInfo(newDisplayInfo);
            mPipBoundsState.setDisplayInfo(newDisplayInfo);
            updateMovementBounds(null /* toBounds */, false /* fromRotation */,
                    false /* fromImeAdjustment */, false /* fromShelfAdjustment */,
                    null /* wct */);
            mPipBoundsState.setDisplayId(displayId);
            onDisplayChanged(displayController.getDisplayLayout(displayId),
                    false /* saveRestoreSnapFraction */);
        });
        mPipBoundsState.setOnMinimalSizeChangeCallback(
                () -> {
@@ -291,13 +297,12 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
            mPipInputConsumer.setRegistrationListener(mTouchHandler::onRegistrationChanged);
        }
        displayController.addDisplayChangingController(mRotationController);
        displayController.addDisplayWindowListener(mFixedRotationListener);
        displayController.addDisplayWindowListener(mDisplaysChangedListener);

        // Ensure that we have the display info in case we get calls to update the bounds before the
        // listener calls back
        final DisplayInfo displayInfo = new DisplayInfo();
        context.getDisplay().getDisplayInfo(displayInfo);
        mPipBoundsState.setDisplayInfo(displayInfo);
        mPipBoundsState.setDisplayId(context.getDisplayId());
        mPipBoundsState.setDisplayLayout(new DisplayLayout(context, context.getDisplay()));

        try {
            mWindowManagerShellWrapper.addPinnedStackListener(mPinnedStackListener);
@@ -363,11 +368,42 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
    }

    private void onOverlayChanged() {
        mPipBoundsState.setDisplayLayout(new DisplayLayout(mContext, mContext.getDisplay()));
        onDisplayChanged(new DisplayLayout(mContext, mContext.getDisplay()),
                false /* saveRestoreSnapFraction */);
    }

    private void onDisplayChanged(DisplayLayout layout, boolean saveRestoreSnapFraction) {
        Runnable updateDisplayLayout = () -> {
            mPipBoundsState.setDisplayLayout(layout);
            updateMovementBounds(null /* toBounds */,
                    false /* fromRotation */, false /* fromImeAdjustment */,
                    false /* fromShelfAdjustment */,
                    null /* windowContainerTransaction */);
        };

        if (saveRestoreSnapFraction) {
            // Calculate the snap fraction of the current stack along the old movement bounds
            final PipSnapAlgorithm pipSnapAlgorithm = mPipBoundsAlgorithm.getSnapAlgorithm();
            final Rect postChangeStackBounds = new Rect(mPipBoundsState.getBounds());
            final float snapFraction = pipSnapAlgorithm.getSnapFraction(postChangeStackBounds,
                    mPipBoundsAlgorithm.getMovementBounds(postChangeStackBounds),
                    mPipBoundsState.getStashedState());

            updateDisplayLayout.run();

            // Calculate the stack bounds in the new orientation based on same fraction along the
            // rotated movement bounds.
            final Rect postChangeMovementBounds = mPipBoundsAlgorithm.getMovementBounds(
                    postChangeStackBounds, false /* adjustForIme */);
            pipSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
                    snapFraction, mPipBoundsState.getStashedState(),
                    mPipBoundsState.getStashOffset(),
                    mPipBoundsState.getDisplayBounds());

            mTouchHandler.getMotionHelper().movePip(postChangeStackBounds);
        } else {
            updateDisplayLayout.run();
        }
    }

    private void registerSessionListenerForCurrentUser() {
@@ -500,7 +536,7 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
        // Populate inset / normal bounds and DisplayInfo from mPipBoundsHandler before
        // passing to mTouchHandler/mPipTaskOrganizer
        final Rect outBounds = new Rect(toBounds);
        mTmpDisplayInfo.copyFrom(mPipBoundsState.getDisplayInfo());
        final int rotation = mPipBoundsState.getDisplayLayout().rotation();

        mPipBoundsAlgorithm.getInsetBounds(mTmpInsetBounds);
        mPipBoundsState.setNormalBounds(mPipBoundsAlgorithm.getNormalBounds());
@@ -512,8 +548,7 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
        mPipTaskOrganizer.onMovementBoundsChanged(outBounds, fromRotation, fromImeAdjustment,
                fromShelfAdjustment, wct);
        mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mPipBoundsState.getNormalBounds(),
                outBounds, fromImeAdjustment, fromShelfAdjustment,
                mTmpDisplayInfo.rotation);
                outBounds, fromImeAdjustment, fromShelfAdjustment, rotation);
    }

    /**
@@ -525,13 +560,6 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
        // Update the display layout, note that we have to do this on every rotation even if we
        // aren't in PIP since we need to update the display layout to get the right resources
        mPipBoundsState.getDisplayLayout().rotateTo(context.getResources(), toRotation);

        // Populate the new {@link #mDisplayInfo}.
        // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation,
        // therefore, the width/height may require a swap first.
        // Moving forward, we should get the new dimensions after rotation from DisplayLayout.
        mPipBoundsState.setDisplayRotation(toRotation);
        updateDisplayInfoIfNeeded();
    }

    /**
@@ -543,9 +571,8 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
    private boolean onDisplayRotationChanged(Context context, Rect outBounds, Rect oldBounds,
            Rect outInsetBounds,
            int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) {
        // Bail early if the event is not sent to current {@link #mDisplayInfo}
        if ((displayId != mPipBoundsState.getDisplayInfo().displayId)
                || (fromRotation == toRotation)) {
        // Bail early if the event is not sent to current display
        if ((displayId != mPipBoundsState.getDisplayId()) || (fromRotation == toRotation)) {
            return false;
        }

@@ -570,13 +597,6 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
        // Update the display layout
        mPipBoundsState.getDisplayLayout().rotateTo(context.getResources(), toRotation);

        // Populate the new {@link #mDisplayInfo}.
        // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation,
        // therefore, the width/height may require a swap first.
        // Moving forward, we should get the new dimensions after rotation from DisplayLayout.
        mPipBoundsState.getDisplayInfo().rotation = toRotation;
        updateDisplayInfoIfNeeded();

        // Calculate the stack bounds in the new orientation based on same fraction along the
        // rotated movement bounds.
        final Rect postChangeMovementBounds = mPipBoundsAlgorithm.getMovementBounds(
@@ -591,21 +611,6 @@ public class PipController implements PipTaskOrganizer.PipTransitionCallback {
        return true;
    }

    private void updateDisplayInfoIfNeeded() {
        final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
        final boolean updateNeeded;
        if ((displayInfo.rotation == ROTATION_0) || (displayInfo.rotation == ROTATION_180)) {
            updateNeeded = (displayInfo.logicalWidth > displayInfo.logicalHeight);
        } else {
            updateNeeded = (displayInfo.logicalWidth < displayInfo.logicalHeight);
        }
        if (updateNeeded) {
            final int newLogicalHeight = displayInfo.logicalWidth;
            displayInfo.logicalWidth = displayInfo.logicalHeight;
            displayInfo.logicalHeight = newLogicalHeight;
        }
    }

    private void dump(PrintWriter pw) {
        final String innerPrefix = "  ";
        pw.println(TAG);
+3 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.view.DisplayInfo;

import com.android.wm.shell.R;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
@@ -138,7 +139,8 @@ public class TvPipController implements PipTaskOrganizer.PipTransitionCallback,
        mMainExecutor = mainExecutor;

        mPipBoundsState = pipBoundsState;
        mPipBoundsState.setDisplayInfo(getDisplayInfo());
        mPipBoundsState.setDisplayId(context.getDisplayId());
        mPipBoundsState.setDisplayLayout(new DisplayLayout(context, context.getDisplay()));
        mPipBoundsAlgorithm = pipBoundsAlgorithm;

        mPipMediaController = pipMediaController;
Loading