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

Commit 9366e263 authored by jorgegil@google.com's avatar jorgegil@google.com
Browse files

Add PipBoundsState to manage current pip bounds

This change adds a basic state class and migrates
mLastReportedBounds from PipTaskOrg into it. It'll
eventually become the holder of all bounds-related state
such as movements bounds, reentry bounds/fraction and
aspect ratio.

Bug: 169373982
Test: atest com.android.wm.shell.pip
Change-Id: I43c530f4f3ab192756964022417f39f3085e593e
parent d1fec2c7
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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;

import android.annotation.NonNull;
import android.graphics.Rect;

import java.io.PrintWriter;

/**
 * Singleton source of truth for the current state of PIP bounds.
 */
public final class PipBoundsState {
    private static final String TAG = PipBoundsState.class.getSimpleName();

    private final @NonNull Rect mBounds = new Rect();

    void setBounds(@NonNull Rect bounds) {
        mBounds.set(bounds);
    }

    @NonNull
    public Rect getBounds() {
        return new Rect(mBounds);
    }

    /**
     * Dumps internal state.
     */
    public void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + TAG);
        pw.println(innerPrefix + "mBounds=" + mBounds);
    }
}
+20 −23
Original line number Diff line number Diff line
@@ -134,11 +134,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,

    private final Handler mMainHandler;
    private final Handler mUpdateHandler;
    private final PipBoundsState mPipBoundsState;
    private final PipBoundsHandler mPipBoundsHandler;
    private final PipAnimationController mPipAnimationController;
    private final PipUiEventLogger mPipUiEventLoggerLogger;
    private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>();
    private final Rect mLastReportedBounds = new Rect();
    private final int mEnterExitAnimationDuration;
    private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
    private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
@@ -262,7 +262,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     */
    private boolean mShouldIgnoreEnteringPipTransition;

    public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler,
    public PipTaskOrganizer(Context context, @NonNull PipBoundsState pipBoundsState,
            @NonNull PipBoundsHandler boundsHandler,
            @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
            Optional<SplitScreen> splitScreenOptional,
            @NonNull DisplayController displayController,
@@ -270,6 +271,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            @NonNull ShellTaskOrganizer shellTaskOrganizer) {
        mMainHandler = new Handler(Looper.getMainLooper());
        mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
        mPipBoundsState = pipBoundsState;
        mPipBoundsHandler = boundsHandler;
        mEnterExitAnimationDuration = context.getResources()
                .getInteger(R.integer.config_pipResizeAnimationDuration);
@@ -292,17 +294,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        return mUpdateHandler;
    }

    public Rect getLastReportedBounds() {
        return new Rect(mLastReportedBounds);
    }

    public Rect getCurrentOrAnimatingBounds() {
        PipAnimationController.PipTransitionAnimator animator =
                mPipAnimationController.getCurrentAnimator();
        if (animator != null && animator.isRunning()) {
            return new Rect(animator.getDestinationBounds());
        }
        return getLastReportedBounds();
        return mPipBoundsState.getBounds();
    }

    public boolean isInPip() {
@@ -347,7 +345,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     * Expect {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)} afterwards.
     */
    public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
        mLastReportedBounds.set(destinationBounds);
        mPipBoundsState.setBounds(destinationBounds);
    }

    /**
@@ -394,7 +392,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            final SurfaceControl.Transaction tx =
                    mSurfaceControlTransactionFactory.getTransaction();
            mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds,
                    mLastReportedBounds);
                    mPipBoundsState.getBounds());
            tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
            // We set to fullscreen here for now, but later it will be set to UNDEFINED for
            // the proper windowing mode to take place. See #applyWindowingModeChangeOnExit.
@@ -408,9 +406,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                @Override
                public void onTransactionReady(int id, SurfaceControl.Transaction t) {
                    t.apply();
                    scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
                            getValidSourceHintRect(mTaskInfo, destinationBounds), direction,
                            animationDurationMs, null /* updateBoundsCallback */);
                    scheduleAnimateResizePip(mPipBoundsState.getBounds(),
                            destinationBounds, getValidSourceHintRect(mTaskInfo, destinationBounds),
                            direction, animationDurationMs, null /* updateBoundsCallback */);
                    mState = State.EXITING_PIP;
                }
            });
@@ -441,7 +439,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,

        // removePipImmediately is expected when the following animation finishes.
        mUpdateHandler.post(() -> mPipAnimationController
                .getAnimator(mLeash, mLastReportedBounds, 1f, 0f)
                .getAnimator(mLeash, mPipBoundsState.getBounds(), 1f, 0f)
                .setTransitionDirection(TRANSITION_DIRECTION_REMOVE_STACK)
                .setPipAnimationCallback(mPipAnimationCallback)
                .setDuration(mEnterExitAnimationDuration)
@@ -480,7 +478,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        if (mShouldIgnoreEnteringPipTransition) {
            // Animation has been finished together with Recents, directly apply the sync
            // transaction to PiP here.
            applyEnterPipSyncTransaction(mLastReportedBounds, () -> {
            applyEnterPipSyncTransaction(mPipBoundsState.getBounds(), () -> {
                mState = State.ENTERED_PIP;
            });
            mShouldIgnoreEnteringPipTransition = false;
@@ -572,7 +570,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,

    private void sendOnPipTransitionStarted(
            @PipAnimationController.TransitionDirection int direction) {
        final Rect pipBounds = new Rect(mLastReportedBounds);
        final Rect pipBounds = mPipBoundsState.getBounds();
        runOnMainHandler(() -> {
            for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
@@ -701,7 +699,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        }
        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                info.topActivity, getAspectRatioOrDefault(newParams),
                mLastReportedBounds, getMinimalSize(info.topActivityInfo),
                mPipBoundsState.getBounds(), getMinimalSize(info.topActivityInfo),
                true /* userCurrentMinEdgeSize */);
        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
        scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration,
@@ -759,7 +757,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                    sendOnPipTransitionCancelled(direction);
                    sendOnPipTransitionFinished(direction);
                }
                mLastReportedBounds.set(destinationBoundsOut);
                mPipBoundsState.setBounds(destinationBoundsOut);

                // Create a reset surface transaction for the new bounds and update the window
                // container transaction
@@ -774,8 +772,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                        destinationBoundsOut.set(animator.getDestinationBounds());
                    }
                } else {
                    if (!mLastReportedBounds.isEmpty()) {
                        destinationBoundsOut.set(mLastReportedBounds);
                    if (!mPipBoundsState.getBounds().isEmpty()) {
                        destinationBoundsOut.set(mPipBoundsState.getBounds());
                    }
                }
            }
@@ -827,7 +825,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
            return;
        }
        scheduleAnimateResizePip(mLastReportedBounds, toBounds, null /* sourceHintRect */,
        scheduleAnimateResizePip(mPipBoundsState.getBounds(), toBounds, null /* sourceHintRect */,
                TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
    }

@@ -963,7 +961,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            Log.w(TAG, "Abort animation, invalid leash");
            return;
        }
        mLastReportedBounds.set(destinationBounds);
        mPipBoundsState.setBounds(destinationBounds);
        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
        mSurfaceTransactionHelper
                .crop(tx, mLeash, destinationBounds)
@@ -999,7 +997,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
                    + "directly");
        }
        mLastReportedBounds.set(destinationBounds);
        mPipBoundsState.setBounds(destinationBounds);
        if (direction == TRANSITION_DIRECTION_REMOVE_STACK) {
            removePipImmediately();
            return;
@@ -1141,7 +1139,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        pw.println(innerPrefix + "mState=" + mState);
        pw.println(innerPrefix + "mOneShotAnimationType=" + mOneShotAnimationType);
        pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams);
        pw.println(innerPrefix + "mLastReportedBounds=" + mLastReportedBounds);
        pw.println(innerPrefix + "mInitialState:");
        for (Map.Entry<IBinder, Configuration> e : mInitialState.entrySet()) {
            pw.println(innerPrefix + "  binder=" + e.getKey()
+8 −3
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.wm.shell.pip.phone;

import android.annotation.NonNull;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.Region;
@@ -28,6 +29,7 @@ import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;

import com.android.wm.shell.R;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;

@@ -50,6 +52,7 @@ public class PipAccessibilityInteractionConnection

    private Context mContext;
    private Handler mHandler;
    private final @NonNull PipBoundsState mPipBoundsState;
    private PipMotionHelper mMotionHelper;
    private PipTaskOrganizer mTaskOrganizer;
    private PipSnapAlgorithm mSnapAlgorithm;
@@ -62,12 +65,14 @@ public class PipAccessibilityInteractionConnection
    private final Rect mExpandedMovementBounds = new Rect();
    private Rect mTmpBounds = new Rect();

    public PipAccessibilityInteractionConnection(Context context, PipMotionHelper motionHelper,
    public PipAccessibilityInteractionConnection(Context context,
            @NonNull PipBoundsState pipBoundsState, PipMotionHelper motionHelper,
            PipTaskOrganizer taskOrganizer, PipSnapAlgorithm snapAlgorithm,
            AccessibilityCallbacks callbacks, Runnable updateMovementBoundCallback,
            Handler handler) {
        mContext = context;
        mHandler = handler;
        mPipBoundsState = pipBoundsState;
        mMotionHelper = motionHelper;
        mTaskOrganizer = taskOrganizer;
        mSnapAlgorithm = snapAlgorithm;
@@ -148,7 +153,7 @@ public class PipAccessibilityInteractionConnection

    private void setToExpandedBounds() {
        float savedSnapFraction = mSnapAlgorithm.getSnapFraction(
                new Rect(mTaskOrganizer.getLastReportedBounds()), mNormalMovementBounds);
                mPipBoundsState.getBounds(), mNormalMovementBounds);
        mSnapAlgorithm.applySnapFraction(mExpandedBounds, mExpandedMovementBounds,
                savedSnapFraction);
        mTaskOrganizer.scheduleFinishResizePip(mExpandedBounds, (Rect bounds) -> {
@@ -159,7 +164,7 @@ public class PipAccessibilityInteractionConnection

    private void setToNormalBounds() {
        float savedSnapFraction = mSnapAlgorithm.getSnapFraction(
                new Rect(mTaskOrganizer.getLastReportedBounds()), mExpandedMovementBounds);
                mPipBoundsState.getBounds(), mExpandedMovementBounds);
        mSnapAlgorithm.applySnapFraction(mNormalBounds, mNormalMovementBounds, savedSnapFraction);
        mTaskOrganizer.scheduleFinishResizePip(mNormalBounds, (Rect bounds) -> {
            mMotionHelper.synchronizePinnedStackBounds();
+10 −3
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;

import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.PictureInPictureParams;
@@ -44,6 +45,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipBoundsHandler;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipTaskOrganizer;

import java.io.PrintWriter;
@@ -65,6 +67,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
    private DisplayController mDisplayController;
    private PipAppOpsListener mAppOpsListener;
    private PipBoundsHandler mPipBoundsHandler;
    private @NonNull PipBoundsState mPipBoundsState;
    private PipMediaController mMediaController;
    private PipTouchHandler mTouchHandler;
    private Consumer<Boolean> mPinnedStackAnimationRecentsCallback;
@@ -97,7 +100,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
            // If the pip was in the offset zone earlier, adjust the new bounds to the bottom of the
            // movement bounds
            mTouchHandler.adjustBoundsForRotation(mTmpNormalBounds,
                    mPipTaskOrganizer.getLastReportedBounds(), mTmpInsetBounds);
                    mPipBoundsState.getBounds(), mTmpInsetBounds);

            // The bounds are being applied to a specific snap fraction, so reset any known offsets
            // for the previous orientation before updating the movement bounds.
@@ -196,6 +199,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
            DisplayController displayController,
            PipAppOpsListener pipAppOpsListener,
            PipBoundsHandler pipBoundsHandler,
            @NonNull PipBoundsState pipBoundsState,
            PipMediaController pipMediaController,
            PipMenuActivityController pipMenuActivityController,
            PipTaskOrganizer pipTaskOrganizer,
@@ -206,7 +210,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac

        if (PipUtils.hasSystemFeature(mContext)) {
            initController(context, displayController, pipAppOpsListener, pipBoundsHandler,
                    pipMediaController, pipMenuActivityController, pipTaskOrganizer,
                    pipBoundsState, pipMediaController, pipMenuActivityController, pipTaskOrganizer,
                    pipTouchHandler, windowManagerShellWrapper);
        } else {
            Log.w(TAG, "Device not support PIP feature");
@@ -217,6 +221,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
            DisplayController displayController,
            PipAppOpsListener pipAppOpsListener,
            PipBoundsHandler pipBoundsHandler,
            @NonNull PipBoundsState pipBoundsState,
            PipMediaController pipMediaController,
            PipMenuActivityController pipMenuActivityController,
            PipTaskOrganizer pipTaskOrganizer,
@@ -232,6 +237,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
        mWindowManagerShellWrapper = windowManagerShellWrapper;
        mDisplayController = displayController;
        mPipBoundsHandler = pipBoundsHandler;
        mPipBoundsState = pipBoundsState;
        mPipTaskOrganizer = pipTaskOrganizer;
        mPipTaskOrganizer.registerPipTransitionCallback(this);
        mMediaController = pipMediaController;
@@ -360,7 +366,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
        final boolean changed = mPipBoundsHandler.setShelfHeight(visible, shelfHeight);
        if (changed) {
            mTouchHandler.onShelfVisibilityChanged(visible, shelfHeight);
            updateMovementBounds(mPipTaskOrganizer.getLastReportedBounds(),
            updateMovementBounds(mPipBoundsState.getBounds(),
                    false /* fromRotation */, false /* fromImeAdjustment */,
                    true /* fromShelfAdjustment */, null /* windowContainerTransaction */);
        }
@@ -445,5 +451,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
        mTouchHandler.dump(pw, innerPrefix);
        mPipBoundsHandler.dump(pw, innerPrefix);
        mPipTaskOrganizer.dump(pw, innerPrefix);
        mPipBoundsState.dump(pw, innerPrefix);
    }
}
+7 −4
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import com.android.wm.shell.animation.FloatProperties;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;

@@ -66,6 +67,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,

    private final Context mContext;
    private final PipTaskOrganizer mPipTaskOrganizer;
    private final @NonNull PipBoundsState mPipBoundsState;

    private PipMenuActivityController mMenuController;
    private PipSnapAlgorithm mSnapAlgorithm;
@@ -178,11 +180,12 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
        public void onPipTransitionCanceled(ComponentName activity, int direction) {}
    };

    public PipMotionHelper(Context context, PipTaskOrganizer pipTaskOrganizer,
            PipMenuActivityController menuController, PipSnapAlgorithm snapAlgorithm,
            FloatingContentCoordinator floatingContentCoordinator) {
    public PipMotionHelper(Context context, @NonNull PipBoundsState pipBoundsState,
            PipTaskOrganizer pipTaskOrganizer, PipMenuActivityController menuController,
            PipSnapAlgorithm snapAlgorithm, FloatingContentCoordinator floatingContentCoordinator) {
        mContext = context;
        mPipTaskOrganizer = pipTaskOrganizer;
        mPipBoundsState = pipBoundsState;
        mMenuController = menuController;
        mSnapAlgorithm = snapAlgorithm;
        mFloatingContentCoordinator = floatingContentCoordinator;
@@ -220,7 +223,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
     */
    void synchronizePinnedStackBounds() {
        cancelAnimations();
        mBounds.set(mPipTaskOrganizer.getLastReportedBounds());
        mBounds.set(mPipBoundsState.getBounds());
        mTemporaryBounds.setEmpty();

        if (mPipTaskOrganizer.isInPip()) {
Loading