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

Commit 81f44313 authored by Ikram Gabiyev's avatar Ikram Gabiyev
Browse files

Allow drag flings in PiP2 via PipTransitionState

Use PipTransitionState as an "event hub" to allow
PiP drag and fling animations through PipMotionHelper.

Furthermore, adopt the Approach #2 described in go/pip2-transitions
to use transitions to update pinned task's bounds in Core instead
of using direct applyTransaction() calls.

Ensure, through state updates connected to transitions that interactions
are disallowed until all leash and WM state updates are complete;
this should ultimately avoid any flickers while interacting with PiP.

Bug: 332770512
Test: adb shell setprop wm_shell.pip2 1 \
       && adb shell am crash com.android.systemui
Test: swipe-up to enter PiP and drag PiP window
Change-Id: If71b47103295563e3d419427d7abbc5ae67829bc
parent 3717eb05
Loading
Loading
Loading
Loading
+10 −4
Original line number Original line Diff line number Diff line
@@ -132,6 +132,7 @@ public abstract class Pip2Module {
            PhonePipMenuController menuPhoneController,
            PhonePipMenuController menuPhoneController,
            PipBoundsAlgorithm pipBoundsAlgorithm,
            PipBoundsAlgorithm pipBoundsAlgorithm,
            @NonNull PipBoundsState pipBoundsState,
            @NonNull PipBoundsState pipBoundsState,
            @NonNull PipTransitionState pipTransitionState,
            @NonNull SizeSpecSource sizeSpecSource,
            @NonNull SizeSpecSource sizeSpecSource,
            PipMotionHelper pipMotionHelper,
            PipMotionHelper pipMotionHelper,
            FloatingContentCoordinator floatingContentCoordinator,
            FloatingContentCoordinator floatingContentCoordinator,
@@ -139,8 +140,9 @@ public abstract class Pip2Module {
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellMainThread ShellExecutor mainExecutor,
            Optional<PipPerfHintController> pipPerfHintControllerOptional) {
            Optional<PipPerfHintController> pipPerfHintControllerOptional) {
        return new PipTouchHandler(context, shellInit, menuPhoneController, pipBoundsAlgorithm,
        return new PipTouchHandler(context, shellInit, menuPhoneController, pipBoundsAlgorithm,
                pipBoundsState, sizeSpecSource, pipMotionHelper, floatingContentCoordinator,
                pipBoundsState, pipTransitionState, sizeSpecSource, pipMotionHelper,
                pipUiEventLogger, mainExecutor, pipPerfHintControllerOptional);
                floatingContentCoordinator, pipUiEventLogger, mainExecutor,
                pipPerfHintControllerOptional);
    }
    }


    @WMSingleton
    @WMSingleton
@@ -149,9 +151,13 @@ public abstract class Pip2Module {
            PipBoundsState pipBoundsState, PhonePipMenuController menuController,
            PipBoundsState pipBoundsState, PhonePipMenuController menuController,
            PipSnapAlgorithm pipSnapAlgorithm,
            PipSnapAlgorithm pipSnapAlgorithm,
            FloatingContentCoordinator floatingContentCoordinator,
            FloatingContentCoordinator floatingContentCoordinator,
            Optional<PipPerfHintController> pipPerfHintControllerOptional) {
            PipScheduler pipScheduler,
            Optional<PipPerfHintController> pipPerfHintControllerOptional,
            PipBoundsAlgorithm pipBoundsAlgorithm,
            PipTransitionState pipTransitionState) {
        return new PipMotionHelper(context, pipBoundsState, menuController, pipSnapAlgorithm,
        return new PipMotionHelper(context, pipBoundsState, menuController, pipSnapAlgorithm,
                floatingContentCoordinator, pipPerfHintControllerOptional);
                floatingContentCoordinator, pipScheduler, pipPerfHintControllerOptional,
                pipBoundsAlgorithm, pipTransitionState);
    }
    }


    @WMSingleton
    @WMSingleton
+1 −1
Original line number Original line Diff line number Diff line
@@ -53,7 +53,7 @@ public class PipInputConsumer {
     * Listener interface for callers to learn when this class is registered or unregistered with
     * Listener interface for callers to learn when this class is registered or unregistered with
     * window manager
     * window manager
     */
     */
    private interface RegistrationListener {
    interface RegistrationListener {
        void onRegistrationChanged(boolean isRegistered);
        void onRegistrationChanged(boolean isRegistered);
    }
    }


+89 −33
Original line number Original line Diff line number Diff line
@@ -31,7 +31,9 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Debug;
import android.os.Debug;
import android.view.SurfaceControl;


import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R;
import com.android.wm.shell.R;
@@ -39,6 +41,7 @@ import com.android.wm.shell.animation.FloatProperties;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
import com.android.wm.shell.common.pip.PipAppOpsListener;
import com.android.wm.shell.common.pip.PipAppOpsListener;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipPerfHintController;
import com.android.wm.shell.common.pip.PipPerfHintController;
import com.android.wm.shell.common.pip.PipSnapAlgorithm;
import com.android.wm.shell.common.pip.PipSnapAlgorithm;
@@ -57,6 +60,7 @@ import java.util.function.Consumer;
public class PipMotionHelper implements PipAppOpsListener.Callback,
public class PipMotionHelper implements PipAppOpsListener.Callback,
        FloatingContentCoordinator.FloatingContent {
        FloatingContentCoordinator.FloatingContent {
    private static final String TAG = "PipMotionHelper";
    private static final String TAG = "PipMotionHelper";
    private static final String FLING_BOUNDS_CHANGE = "fling_bounds_change";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = false;


    private static final int SHRINK_STACK_FROM_MENU_DURATION = 250;
    private static final int SHRINK_STACK_FROM_MENU_DURATION = 250;
@@ -72,7 +76,9 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,


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

    private @NonNull PipBoundsAlgorithm mPipBoundsAlgorithm;
    private @NonNull PipScheduler mPipScheduler;
    private @NonNull PipTransitionState mPipTransitionState;
    private PhonePipMenuController mMenuController;
    private PhonePipMenuController mMenuController;
    private PipSnapAlgorithm mSnapAlgorithm;
    private PipSnapAlgorithm mSnapAlgorithm;


@@ -144,6 +150,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
     */
     */
    private boolean mDismissalPending = false;
    private boolean mDismissalPending = false;


    /**
     * Set to true if bounds change transition has been scheduled from PipMotionHelper.
     */
    private boolean mWaitingForBoundsChangeTransition = false;

    /**
    /**
     * Gets set in {@link #animateToExpandedState(Rect, Rect, Rect, Runnable)}, this callback is
     * Gets set in {@link #animateToExpandedState(Rect, Rect, Rect, Runnable)}, this callback is
     * used to show menu activity when the expand animation is completed.
     * used to show menu activity when the expand animation is completed.
@@ -152,22 +163,25 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,


    public PipMotionHelper(Context context, @NonNull PipBoundsState pipBoundsState,
    public PipMotionHelper(Context context, @NonNull PipBoundsState pipBoundsState,
            PhonePipMenuController menuController, PipSnapAlgorithm snapAlgorithm,
            PhonePipMenuController menuController, PipSnapAlgorithm snapAlgorithm,
            FloatingContentCoordinator floatingContentCoordinator,
            FloatingContentCoordinator floatingContentCoordinator, PipScheduler pipScheduler,
            Optional<PipPerfHintController> pipPerfHintControllerOptional) {
            Optional<PipPerfHintController> pipPerfHintControllerOptional,
            PipBoundsAlgorithm pipBoundsAlgorithm, PipTransitionState pipTransitionState) {
        mContext = context;
        mContext = context;
        mPipBoundsState = pipBoundsState;
        mPipBoundsState = pipBoundsState;
        mPipBoundsAlgorithm = pipBoundsAlgorithm;
        mPipScheduler = pipScheduler;
        mMenuController = menuController;
        mMenuController = menuController;
        mSnapAlgorithm = snapAlgorithm;
        mSnapAlgorithm = snapAlgorithm;
        mFloatingContentCoordinator = floatingContentCoordinator;
        mFloatingContentCoordinator = floatingContentCoordinator;
        mPipPerfHintController = pipPerfHintControllerOptional.orElse(null);
        mPipPerfHintController = pipPerfHintControllerOptional.orElse(null);
        mResizePipUpdateListener = (target, values) -> {
        mResizePipUpdateListener = (target, values) -> {
            if (mPipBoundsState.getMotionBoundsState().isInMotion()) {
            if (mPipBoundsState.getMotionBoundsState().isInMotion()) {
                /*
                mPipScheduler.scheduleUserResizePip(
                mPipTaskOrganizer.scheduleUserResizePip(getBounds(),
                        mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
                        mPipBoundsState.getMotionBoundsState().getBoundsInMotion(), null);
                 */
            }
            }
        };
        };
        mPipTransitionState = pipTransitionState;
        mPipTransitionState.addPipTransitionStateChangedListener(this::onPipTransitionStateChanged);
    }
    }


    void init() {
    void init() {
@@ -236,12 +250,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
                mPipBoundsState.setBounds(toBounds);
                mPipBoundsState.setBounds(toBounds);
            } else {
            } else {
                mPipBoundsState.getMotionBoundsState().setBoundsInMotion(toBounds);
                mPipBoundsState.getMotionBoundsState().setBoundsInMotion(toBounds);
                /*
                mPipScheduler.scheduleUserResizePip(toBounds);
                mPipTaskOrganizer.scheduleUserResizePip(getBounds(), toBounds,
                        (Rect newBounds) -> {
                                mMenuController.updateMenuLayout(newBounds);
                        });
                 */
            }
            }
        } else {
        } else {
            // If PIP is 'catching up' after being stuck in the dismiss target, update the animation
            // If PIP is 'catching up' after being stuck in the dismiss target, update the animation
@@ -552,11 +561,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
    /** Set new fling configs whose min/max values respect the given movement bounds. */
    /** Set new fling configs whose min/max values respect the given movement bounds. */
    private void rebuildFlingConfigs() {
    private void rebuildFlingConfigs() {
        mFlingConfigX = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION,
        mFlingConfigX = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION,
                mPipBoundsState.getMovementBounds().left,
                mPipBoundsAlgorithm.getMovementBounds(getBounds()).left,
                mPipBoundsState.getMovementBounds().right);
                mPipBoundsAlgorithm.getMovementBounds(getBounds()).right);
        mFlingConfigY = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION,
        mFlingConfigY = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION,
                mPipBoundsState.getMovementBounds().top,
                mPipBoundsAlgorithm.getMovementBounds(getBounds()).top,
                mPipBoundsState.getMovementBounds().bottom);
                mPipBoundsAlgorithm.getMovementBounds(getBounds()).bottom);
        final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets();
        final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets();
        mStashConfigX = new PhysicsAnimator.FlingConfig(
        mStashConfigX = new PhysicsAnimator.FlingConfig(
                DEFAULT_FRICTION,
                DEFAULT_FRICTION,
@@ -623,22 +632,15 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
    private void onBoundsPhysicsAnimationEnd() {
    private void onBoundsPhysicsAnimationEnd() {
        // The physics animation ended, though we may not necessarily be done animating, such as
        // The physics animation ended, though we may not necessarily be done animating, such as
        // when we're still dragging after moving out of the magnetic target.
        // when we're still dragging after moving out of the magnetic target.
        if (!mDismissalPending
        if (!mDismissalPending && !mSpringingToTouch && !mMagnetizedPip.getObjectStuckToTarget()) {
                && !mSpringingToTouch
                && !mMagnetizedPip.getObjectStuckToTarget()) {
            // All motion operations have actually finished.
            mPipBoundsState.setBounds(
                    mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
            mPipBoundsState.getMotionBoundsState().onAllAnimationsEnded();
            if (!mDismissalPending) {
            // do not schedule resize if PiP is dismissing, which may cause app re-open to
            // do not schedule resize if PiP is dismissing, which may cause app re-open to
            // mBounds instead of its normal bounds.
            // mBounds instead of its normal bounds.
                // mPipTaskOrganizer.scheduleFinishResizePip(getBounds());
            Bundle extra = new Bundle();
            }
            extra.putBoolean(FLING_BOUNDS_CHANGE, true);
            mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra);
            return;
        }
        }
        mPipBoundsState.getMotionBoundsState().onPhysicsAnimationEnded();
        settlePipBoundsAfterPhysicsAnimation(true /* animatingAfter */);
        mSpringingToTouch = false;
        mDismissalPending = false;
        cleanUpHighPerfSessionMaybe();
        cleanUpHighPerfSessionMaybe();
    }
    }


@@ -662,7 +664,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
                            + " callers=\n%s", TAG, toBounds, Debug.getCallers(5, "    "));
                            + " callers=\n%s", TAG, toBounds, Debug.getCallers(5, "    "));
        }
        }
        if (!toBounds.equals(getBounds())) {
        if (!toBounds.equals(getBounds())) {
            // mPipTaskOrganizer.scheduleResizePip(toBounds, mUpdateBoundsCallback);
            mPipScheduler.scheduleAnimateResizePip(toBounds);
        }
        }
    }
    }


@@ -685,6 +687,60 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
        // setAnimatingToBounds(toBounds);
        // setAnimatingToBounds(toBounds);
    }
    }


    private void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState,
            @PipTransitionState.TransitionState int newState,
            @Nullable Bundle extra) {
        switch (newState) {
            case PipTransitionState.SCHEDULED_BOUNDS_CHANGE:
                if (!extra.getBoolean(FLING_BOUNDS_CHANGE)) break;

                // If touch is turned off and we are in a fling animation, schedule a transition.
                mWaitingForBoundsChangeTransition = true;
                mPipScheduler.scheduleAnimateResizePip(
                        mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
                break;
            case PipTransitionState.CHANGING_PIP_BOUNDS:
                if (!mWaitingForBoundsChangeTransition) break;

                // If bounds change transition was scheduled from this class, handle leash updates.
                mWaitingForBoundsChangeTransition = false;
                SurfaceControl.Transaction startTx = extra.getParcelable(
                        PipTransition.PIP_START_TX, SurfaceControl.Transaction.class);
                Rect destinationBounds = extra.getParcelable(
                        PipTransition.PIP_DESTINATION_BOUNDS, Rect.class);
                startTx.setPosition(mPipTransitionState.mPinnedTaskLeash,
                        destinationBounds.left, destinationBounds.top);
                startTx.apply();

                // All motion operations have actually finished, so make bounds cache updates.
                settlePipBoundsAfterPhysicsAnimation(false /* animatingAfter */);
                cleanUpHighPerfSessionMaybe();

                // Setting state to CHANGED_PIP_BOUNDS applies finishTx and notifies Core.
                mPipTransitionState.setState(PipTransitionState.CHANGED_PIP_BOUNDS);
                break;
            case PipTransitionState.EXITING_PIP:
                // We need to force finish any local animators if about to leave PiP, to avoid
                // breaking the state (e.g. leashes are cleaned up upon exit).
                if (!mPipBoundsState.getMotionBoundsState().isInMotion()) break;
                cancelPhysicsAnimation();
                settlePipBoundsAfterPhysicsAnimation(false /* animatingAfter */);
        }
    }

    private void settlePipBoundsAfterPhysicsAnimation(boolean animatingAfter) {
        if (!animatingAfter) {
            // The physics animation ended, though we may not necessarily be done animating, such as
            // when we're still dragging after moving out of the magnetic target. Only set the final
            // bounds state and clear motion bounds completely if the whole animation is over.
            mPipBoundsState.setBounds(mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
            mPipBoundsState.getMotionBoundsState().onAllAnimationsEnded();
        }
        mPipBoundsState.getMotionBoundsState().onPhysicsAnimationEnded();
        mSpringingToTouch = false;
        mDismissalPending = false;
    }

    /**
    /**
     * Returns a MagnetizedObject wrapper for PIP's animated bounds. This is provided to the
     * Returns a MagnetizedObject wrapper for PIP's animated bounds. This is provided to the
     * magnetic dismiss target so it can calculate PIP's size and position.
     * magnetic dismiss target so it can calculate PIP's size and position.
+19 −0
Original line number Original line Diff line number Diff line
@@ -25,16 +25,19 @@ import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.graphics.Rect;
import android.graphics.Rect;
import android.view.SurfaceControl;
import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransaction;


import androidx.annotation.IntDef;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.content.ContextCompat;


import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.protolog.ShellProtoLogGroup;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
@@ -156,4 +159,20 @@ public class PipScheduler {
        wct.setBounds(mPipTransitionState.mPipTaskToken, toBounds);
        wct.setBounds(mPipTransitionState.mPipTaskToken, toBounds);
        mPipTransitionController.startResizeTransition(wct);
        mPipTransitionController.startResizeTransition(wct);
    }
    }

    /**
     * Directly perform a scaled matrix transformation on the leash. This will not perform any
     * {@link WindowContainerTransaction}.
     */
    public void scheduleUserResizePip(Rect toBounds) {
        if (toBounds.isEmpty()) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Attempted to user resize PIP to empty bounds, aborting.", TAG);
            return;
        }
        SurfaceControl leash = mPipTransitionState.mPinnedTaskLeash;
        final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
        tx.setPosition(leash, toBounds.left, toBounds.top);
        tx.apply();
    }
}
}
+49 −12
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


package com.android.wm.shell.pip2.phone;
package com.android.wm.shell.pip2.phone;


import static android.view.WindowManager.INPUT_CONSUMER_PIP;

import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASHING;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASHING;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASH_MINIMUM_VELOCITY_THRESHOLD;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASH_MINIMUM_VELOCITY_THRESHOLD;
import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_LEFT;
import static com.android.wm.shell.common.pip.PipBoundsState.STASH_TYPE_LEFT;
@@ -30,18 +32,19 @@ import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_PICTURE_
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.Bundle;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig;
import android.util.Size;
import android.util.Size;
import android.view.DisplayCutout;
import android.view.DisplayCutout;
import android.view.InputEvent;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewConfiguration;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -80,6 +83,7 @@ public class PipTouchHandler {
    private final Context mContext;
    private final Context mContext;
    private final PipBoundsAlgorithm mPipBoundsAlgorithm;
    private final PipBoundsAlgorithm mPipBoundsAlgorithm;
    @NonNull private final PipBoundsState mPipBoundsState;
    @NonNull private final PipBoundsState mPipBoundsState;
    @NonNull private final PipTransitionState mPipTransitionState;
    @NonNull private final SizeSpecSource mSizeSpecSource;
    @NonNull private final SizeSpecSource mSizeSpecSource;
    private final PipUiEventLogger mPipUiEventLogger;
    private final PipUiEventLogger mPipUiEventLogger;
    private final PipDismissTargetHandler mPipDismissTargetHandler;
    private final PipDismissTargetHandler mPipDismissTargetHandler;
@@ -125,6 +129,7 @@ public class PipTouchHandler {
    private final FloatingContentCoordinator mFloatingContentCoordinator;
    private final FloatingContentCoordinator mFloatingContentCoordinator;
    private PipMotionHelper mMotionHelper;
    private PipMotionHelper mMotionHelper;
    private PipTouchGesture mGesture;
    private PipTouchGesture mGesture;
    private PipInputConsumer mPipInputConsumer;


    // Temp vars
    // Temp vars
    private final Rect mTmpBounds = new Rect();
    private final Rect mTmpBounds = new Rect();
@@ -167,6 +172,7 @@ public class PipTouchHandler {
            PhonePipMenuController menuController,
            PhonePipMenuController menuController,
            PipBoundsAlgorithm pipBoundsAlgorithm,
            PipBoundsAlgorithm pipBoundsAlgorithm,
            @NonNull PipBoundsState pipBoundsState,
            @NonNull PipBoundsState pipBoundsState,
            @NonNull PipTransitionState pipTransitionState,
            @NonNull SizeSpecSource sizeSpecSource,
            @NonNull SizeSpecSource sizeSpecSource,
            PipMotionHelper pipMotionHelper,
            PipMotionHelper pipMotionHelper,
            FloatingContentCoordinator floatingContentCoordinator,
            FloatingContentCoordinator floatingContentCoordinator,
@@ -179,6 +185,9 @@ public class PipTouchHandler {
        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
        mPipBoundsAlgorithm = pipBoundsAlgorithm;
        mPipBoundsAlgorithm = pipBoundsAlgorithm;
        mPipBoundsState = pipBoundsState;
        mPipBoundsState = pipBoundsState;

        mPipTransitionState = pipTransitionState;
        mPipTransitionState.addPipTransitionStateChangedListener(this::onPipTransitionStateChanged);
        mSizeSpecSource = sizeSpecSource;
        mSizeSpecSource = sizeSpecSource;
        mMenuController = menuController;
        mMenuController = menuController;
        mPipUiEventLogger = pipUiEventLogger;
        mPipUiEventLogger = pipUiEventLogger;
@@ -227,6 +236,11 @@ public class PipTouchHandler {
        mPipResizeGestureHandler.init();
        mPipResizeGestureHandler.init();
        mPipDismissTargetHandler.init();
        mPipDismissTargetHandler.init();


        mPipInputConsumer = new PipInputConsumer(WindowManagerGlobal.getWindowManagerService(),
                INPUT_CONSUMER_PIP, mMainExecutor);
        mPipInputConsumer.setInputListener(this::handleTouchEvent);
        mPipInputConsumer.setRegistrationListener(this::onRegistrationChanged);

        mEnableStash = DeviceConfig.getBoolean(
        mEnableStash = DeviceConfig.getBoolean(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                DeviceConfig.NAMESPACE_SYSTEMUI,
                PIP_STASHING,
                PIP_STASHING,
@@ -294,19 +308,17 @@ public class PipTouchHandler {


    void onActivityPinned() {
    void onActivityPinned() {
        mPipDismissTargetHandler.createOrUpdateDismissTarget();
        mPipDismissTargetHandler.createOrUpdateDismissTarget();

        mPipResizeGestureHandler.onActivityPinned();
        mPipResizeGestureHandler.onActivityPinned();
        mFloatingContentCoordinator.onContentAdded(mMotionHelper);
        mFloatingContentCoordinator.onContentAdded(mMotionHelper);
        mPipInputConsumer.registerInputConsumer();
    }
    }


    void onActivityUnpinned(ComponentName topPipActivity) {
    void onActivityUnpinned() {
        if (topPipActivity == null) {
        // Clean up state after the last PiP activity is removed
        // Clean up state after the last PiP activity is removed
        mPipDismissTargetHandler.cleanUpDismissTarget();
        mPipDismissTargetHandler.cleanUpDismissTarget();

        mFloatingContentCoordinator.onContentRemoved(mMotionHelper);
        mFloatingContentCoordinator.onContentRemoved(mMotionHelper);
        }
        mPipResizeGestureHandler.onActivityUnpinned();
        mPipResizeGestureHandler.onActivityUnpinned();
        mPipInputConsumer.unregisterInputConsumer();
    }
    }


    void onPinnedStackAnimationEnded(
    void onPinnedStackAnimationEnded(
@@ -512,6 +524,7 @@ public class PipTouchHandler {
            return true;
            return true;
        }
        }


        /*
        if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting())
        if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting())
                && mPipDismissTargetHandler.maybeConsumeMotionEvent(ev)) {
                && mPipDismissTargetHandler.maybeConsumeMotionEvent(ev)) {
            // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
            // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
@@ -528,11 +541,13 @@ public class PipTouchHandler {
            return true;
            return true;
        }
        }


        if (!mTouchState.isUserInteracting()) {
        // Ignore the motion event When the entry animation is waiting to be started
        if (!mTouchState.isUserInteracting() && mPipTaskOrganizer.isEntryScheduled()) {
            ProtoLog.wtf(WM_SHELL_PICTURE_IN_PICTURE,
            ProtoLog.wtf(WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Waiting to start the entry animation, skip the motion event.", TAG);
                    "%s: Waiting to start the entry animation, skip the motion event.", TAG);
            return true;
            return true;
        }
        }
         */


        // Update the touch state
        // Update the touch state
        mTouchState.onTouchEvent(ev);
        mTouchState.onTouchEvent(ev);
@@ -808,7 +823,7 @@ public class PipTouchHandler {
            mMovementWithinDismiss = touchState.getDownTouchPosition().y
            mMovementWithinDismiss = touchState.getDownTouchPosition().y
                    >= mPipBoundsState.getMovementBounds().bottom;
                    >= mPipBoundsState.getMovementBounds().bottom;
            mMotionHelper.setSpringingToTouch(false);
            mMotionHelper.setSpringingToTouch(false);
            // mPipDismissTargetHandler.setTaskLeash(mPipTaskOrganizer.getSurfaceControl());
            mPipDismissTargetHandler.setTaskLeash(mPipTransitionState.mPinnedTaskLeash);


            // If the menu is still visible then just poke the menu
            // If the menu is still visible then just poke the menu
            // so that it will timeout after the user stops touching it
            // so that it will timeout after the user stops touching it
@@ -880,7 +895,8 @@ public class PipTouchHandler {
                // Reset the touch state on up before the fling settles
                // Reset the touch state on up before the fling settles
                mTouchState.reset();
                mTouchState.reset();
                if (mEnableStash && shouldStash(vel, getPossiblyMotionBounds())) {
                if (mEnableStash && shouldStash(vel, getPossiblyMotionBounds())) {
                    mMotionHelper.stashToEdge(vel.x, vel.y, this::stashEndAction /* endAction */);
                    // mMotionHelper.stashToEdge(vel.x, vel.y,
                    //      this::stashEndAction /* endAction */);
                } else {
                } else {
                    if (mPipBoundsState.isStashed()) {
                    if (mPipBoundsState.isStashed()) {
                        // Reset stashed state if previously stashed
                        // Reset stashed state if previously stashed
@@ -1059,6 +1075,27 @@ public class PipTouchHandler {
        mPipResizeGestureHandler.setOhmOffset(offset);
        mPipResizeGestureHandler.setOhmOffset(offset);
    }
    }


    private void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState,
            @PipTransitionState.TransitionState int newState,
            @Nullable Bundle extra) {
        switch (newState) {
            case PipTransitionState.ENTERED_PIP:
                onActivityPinned();
                mTouchState.setAllowInputEvents(true);
                break;
            case PipTransitionState.EXITED_PIP:
                mTouchState.setAllowInputEvents(false);
                onActivityUnpinned();
                break;
            case PipTransitionState.SCHEDULED_BOUNDS_CHANGE:
                mTouchState.setAllowInputEvents(false);
                break;
            case PipTransitionState.CHANGED_PIP_BOUNDS:
                mTouchState.setAllowInputEvents(true);
                break;
        }
    }

    /**
    /**
     * Dumps the {@link PipTouchHandler} state.
     * Dumps the {@link PipTouchHandler} state.
     */
     */
Loading