From 527b6ce657dc8313dd95605f9384f6c47d2e32be Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 1 Mar 2021 11:26:55 -0800 Subject: [PATCH] Move PipTouchHandler initialization to shell main thread - We should separate the construction from the initialization and make sure everything is initialized in order on the shell main thread. Bug: 181262334 Test: atest PinnedStackTests Change-Id: I4f52864972146c7440794625e1de370ecea75006 --- .../com/android/wm/shell/ShellInitImpl.java | 11 +++ .../pip/phone/PipDismissTargetHandler.java | 95 +++++++++---------- .../wm/shell/pip/phone/PipMotionHelper.java | 21 ++-- .../pip/phone/PipResizeGestureHandler.java | 4 +- .../wm/shell/pip/phone/PipTouchHandler.java | 27 ++++-- .../shell/pip/phone/PipTouchHandlerTest.java | 1 + .../systemui/wmshell/WMShellBaseModule.java | 5 + 7 files changed, 94 insertions(+), 70 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java index cc353dc991e30..85bd24c1c2bff 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java @@ -24,6 +24,7 @@ import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; +import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.startingsurface.StartingSurface; import com.android.wm.shell.transition.Transitions; @@ -42,6 +43,7 @@ public class ShellInitImpl { private final Optional mLegacySplitScreenOptional; private final Optional mSplitScreenOptional; private final Optional mAppPairsOptional; + private final Optional mPipTouchHandlerOptional; private final FullscreenTaskListener mFullscreenTaskListener; private final ShellExecutor mMainExecutor; private final Transitions mTransitions; @@ -56,6 +58,7 @@ public class ShellInitImpl { Optional splitScreenOptional, Optional appPairsOptional, Optional startingSurfaceOptional, + Optional pipTouchHandlerOptional, FullscreenTaskListener fullscreenTaskListener, Transitions transitions, ShellExecutor mainExecutor) { @@ -66,6 +69,7 @@ public class ShellInitImpl { splitScreenOptional, appPairsOptional, startingSurfaceOptional, + pipTouchHandlerOptional, fullscreenTaskListener, transitions, mainExecutor).mImpl; @@ -78,6 +82,7 @@ public class ShellInitImpl { Optional splitScreenOptional, Optional appPairsOptional, Optional startingSurfaceOptional, + Optional pipTouchHandlerOptional, FullscreenTaskListener fullscreenTaskListener, Transitions transitions, ShellExecutor mainExecutor) { @@ -88,6 +93,7 @@ public class ShellInitImpl { mSplitScreenOptional = splitScreenOptional; mAppPairsOptional = appPairsOptional; mFullscreenTaskListener = fullscreenTaskListener; + mPipTouchHandlerOptional = pipTouchHandlerOptional; mTransitions = transitions; mMainExecutor = mainExecutor; mStartingSurfaceOptional = startingSurfaceOptional; @@ -112,6 +118,11 @@ public class ShellInitImpl { if (Transitions.ENABLE_SHELL_TRANSITIONS) { mTransitions.register(mShellTaskOrganizer); } + + // TODO(b/181599115): This should really be the pip controller, but until we can provide the + // controller instead of the feature interface, can just initialize the touch handler if + // needed + mPipTouchHandlerOptional.ifPresent((handler) -> handler.init()); } @ExternalThread diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java index d9a7bdb2eca62..9ee6a221c80ce 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java @@ -87,7 +87,7 @@ public class PipDismissTargetHandler { SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY); // Allow dragging the PIP to a location to close it - private final boolean mEnableDismissDragToEdge; + private boolean mEnableDismissDragToEdge; private int mDismissAreaHeight; @@ -104,67 +104,66 @@ public class PipDismissTargetHandler { mMotionHelper = motionHelper; mMainExecutor = mainExecutor; mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + } - Resources res = context.getResources(); + public void init() { + Resources res = mContext.getResources(); mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge); mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height); - mMainExecutor.execute(() -> { - mTargetView = new DismissCircleView(context); - mTargetViewContainer = new FrameLayout(context); - mTargetViewContainer.setBackgroundDrawable( - context.getDrawable(R.drawable.floating_dismiss_gradient_transition)); - mTargetViewContainer.setClipChildren(false); - mTargetViewContainer.addView(mTargetView); + mTargetView = new DismissCircleView(mContext); + mTargetViewContainer = new FrameLayout(mContext); + mTargetViewContainer.setBackgroundDrawable( + mContext.getDrawable(R.drawable.floating_dismiss_gradient_transition)); + mTargetViewContainer.setClipChildren(false); + mTargetViewContainer.addView(mTargetView); - mMagnetizedPip = mMotionHelper.getMagnetizedPip(); - mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0); - updateMagneticTargetSize(); + mMagnetizedPip = mMotionHelper.getMagnetizedPip(); + mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0); + updateMagneticTargetSize(); - mMagnetizedPip.setAnimateStuckToTarget( - (target, velX, velY, flung, after) -> { - if (mEnableDismissDragToEdge) { - mMotionHelper.animateIntoDismissTarget(target, velX, velY, flung, - after); - } - return Unit.INSTANCE; - }); - mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() { - @Override - public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) { - // Show the dismiss target, in case the initial touch event occurred within - // the magnetic field radius. + mMagnetizedPip.setAnimateStuckToTarget( + (target, velX, velY, flung, after) -> { if (mEnableDismissDragToEdge) { - showDismissTargetMaybe(); + mMotionHelper.animateIntoDismissTarget(target, velX, velY, flung, after); } + return Unit.INSTANCE; + }); + mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() { + @Override + public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) { + // Show the dismiss target, in case the initial touch event occurred within + // the magnetic field radius. + if (mEnableDismissDragToEdge) { + showDismissTargetMaybe(); } + } - @Override - public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target, - float velX, float velY, boolean wasFlungOut) { - if (wasFlungOut) { - mMotionHelper.flingToSnapTarget(velX, velY, null /* endAction */); - hideDismissTargetMaybe(); - } else { - mMotionHelper.setSpringingToTouch(true); - } + @Override + public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target, + float velX, float velY, boolean wasFlungOut) { + if (wasFlungOut) { + mMotionHelper.flingToSnapTarget(velX, velY, null /* endAction */); + hideDismissTargetMaybe(); + } else { + mMotionHelper.setSpringingToTouch(true); } + } - @Override - public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) { - mMainExecutor.executeDelayed(() -> { - mMotionHelper.notifyDismissalPending(); - mMotionHelper.animateDismiss(); - hideDismissTargetMaybe(); + @Override + public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) { + mMainExecutor.executeDelayed(() -> { + mMotionHelper.notifyDismissalPending(); + mMotionHelper.animateDismiss(); + hideDismissTargetMaybe(); - mPipUiEventLogger.log( - PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_DRAG_TO_REMOVE); - }, 0); - } - }); - - mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView); + mPipUiEventLogger.log( + PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_DRAG_TO_REMOVE); + }, 0); + } }); + + mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java index eae8945ce6be7..d742aa688fe76 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java @@ -102,7 +102,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, * PhysicsAnimator instance for animating {@link PipBoundsState#getMotionBoundsState()} * using physics animations. */ - private final PhysicsAnimator mTemporaryBoundsPhysicsAnimator; + private PhysicsAnimator mTemporaryBoundsPhysicsAnimator; private MagnetizedObject mMagnetizedPip; @@ -171,7 +171,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, public PipMotionHelper(Context context, @NonNull PipBoundsState pipBoundsState, PipTaskOrganizer pipTaskOrganizer, PhonePipMenuController menuController, PipSnapAlgorithm snapAlgorithm, PipTransitionController pipTransitionController, - FloatingContentCoordinator floatingContentCoordinator, ShellExecutor mainExecutor) { + FloatingContentCoordinator floatingContentCoordinator) { mContext = context; mPipTaskOrganizer = pipTaskOrganizer; mPipBoundsState = pipBoundsState; @@ -179,15 +179,6 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mSnapAlgorithm = snapAlgorithm; mFloatingContentCoordinator = floatingContentCoordinator; pipTransitionController.registerPipTransitionCallback(mPipTransitionCallback); - mTemporaryBoundsPhysicsAnimator = PhysicsAnimator.getInstance( - mPipBoundsState.getMotionBoundsState().getBoundsInMotion()); - - // Need to get the shell main thread sf vsync animation handler - mainExecutor.execute(() -> { - mTemporaryBoundsPhysicsAnimator.setCustomAnimationHandler( - mSfAnimationHandlerThreadLocal.get()); - }); - mResizePipUpdateListener = (target, values) -> { if (mPipBoundsState.getMotionBoundsState().isInMotion()) { mPipTaskOrganizer.scheduleUserResizePip(getBounds(), @@ -196,6 +187,14 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, }; } + public void init() { + // Note: Needs to get the shell main thread sf vsync animation handler + mTemporaryBoundsPhysicsAnimator = PhysicsAnimator.getInstance( + mPipBoundsState.getMotionBoundsState().getBoundsInMotion()); + mTemporaryBoundsPhysicsAnimator.setCustomAnimationHandler( + mSfAnimationHandlerThreadLocal.get()); + } + @NonNull @Override public Rect getFloatingBoundsOnScreen() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java index 78ee1868eee7a..31057f8d5fb85 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java @@ -132,8 +132,10 @@ public class PipResizeGestureHandler { mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable; mPhonePipMenuController = menuActivityController; mPipUiEventLogger = pipUiEventLogger; + } - context.getDisplay().getRealSize(mMaxSize); + public void init() { + mContext.getDisplay().getRealSize(mMaxSize); reloadResources(); mEnablePinchResize = DeviceConfig.getBoolean( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java index 5e23281b3438a..543ecfcf1a332 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java @@ -71,12 +71,13 @@ public class PipTouchHandler { private static final float DEFAULT_STASH_VELOCITY_THRESHOLD = 18000.f; // Allow PIP to resize to a slightly bigger state upon touch - private final boolean mEnableResize; + private boolean mEnableResize; private final Context mContext; private final PipBoundsAlgorithm mPipBoundsAlgorithm; private final @NonNull PipBoundsState mPipBoundsState; private final PipUiEventLogger mPipUiEventLogger; private final PipDismissTargetHandler mPipDismissTargetHandler; + private final ShellExecutor mMainExecutor; private PipResizeGestureHandler mPipResizeGestureHandler; private WeakReference> mPipExclusionBoundsChangeListener; @@ -166,16 +167,18 @@ public class PipTouchHandler { ShellExecutor mainExecutor) { // Initialize the Pip input consumer mContext = context; + mMainExecutor = mainExecutor; mAccessibilityManager = context.getSystemService(AccessibilityManager.class); mPipBoundsAlgorithm = pipBoundsAlgorithm; mPipBoundsState = pipBoundsState; mMenuController = menuController; mPipUiEventLogger = pipUiEventLogger; + mFloatingContentCoordinator = floatingContentCoordinator; mMenuController.addListener(new PipMenuListener()); mGesture = new DefaultPipTouchGesture(); mMotionHelper = new PipMotionHelper(mContext, pipBoundsState, pipTaskOrganizer, mMenuController, mPipBoundsAlgorithm.getSnapAlgorithm(), pipTransitionController, - floatingContentCoordinator, mainExecutor); + floatingContentCoordinator); mPipResizeGestureHandler = new PipResizeGestureHandler(context, pipBoundsAlgorithm, pipBoundsState, mMotionHelper, pipTaskOrganizer, this::getMovementBounds, @@ -199,22 +202,26 @@ public class PipTouchHandler { }, menuController::hideMenu, mainExecutor); - - Resources res = context.getResources(); - mEnableResize = res.getBoolean(R.bool.config_pipEnableResizeForMenu); - reloadResources(); - - mFloatingContentCoordinator = floatingContentCoordinator; mConnection = new PipAccessibilityInteractionConnection(mContext, pipBoundsState, mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(), this::onAccessibilityShowMenu, this::updateMovementBounds, mainExecutor); + } + + public void init() { + Resources res = mContext.getResources(); + mEnableResize = res.getBoolean(R.bool.config_pipEnableResizeForMenu); + reloadResources(); + + mMotionHelper.init(); + mPipResizeGestureHandler.init(); + mPipDismissTargetHandler.init(); mEnableStash = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, PIP_STASHING, /* defaultValue = */ true); DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, - mainExecutor, + mMainExecutor, properties -> { if (properties.getKeyset().contains(PIP_STASHING)) { mEnableStash = properties.getBoolean( @@ -226,7 +233,7 @@ public class PipTouchHandler { PIP_STASH_MINIMUM_VELOCITY_THRESHOLD, DEFAULT_STASH_VELOCITY_THRESHOLD); DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, - mainExecutor, + mMainExecutor, properties -> { if (properties.getKeyset().contains(PIP_STASH_MINIMUM_VELOCITY_THRESHOLD)) { mStashVelocityThreshold = properties.getFloat( diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java index 19930485047c8..75ea4ac942570 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java @@ -106,6 +106,7 @@ public class PipTouchHandlerTest extends ShellTestCase { mPipBoundsAlgorithm, mPipBoundsState, mPipTaskOrganizer, mMockPipTransitionController, mFloatingContentCoordinator, mPipUiEventLogger, mMainExecutor); + mPipTouchHandler.init(); mMotionHelper = Mockito.spy(mPipTouchHandler.getMotionHelper()); mPipResizeGestureHandler = Mockito.spy(mPipTouchHandler.getPipResizeGestureHandler()); mPipTouchHandler.setPipMotionHelper(mMotionHelper); diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index 8d3a0402f4c8e..78cd3a823aab1 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -375,6 +375,9 @@ public abstract class WMShellBaseModule { return new PipUiEventLogger(uiEventLogger, packageManager); } + @BindsOptionalOf + abstract PipTouchHandler optionalPipTouchHandler(); + // // Shell transitions // @@ -498,6 +501,7 @@ public abstract class WMShellBaseModule { Optional splitScreenOptional, Optional appPairsOptional, Optional startingSurface, + Optional pipTouchHandlerOptional, FullscreenTaskListener fullscreenTaskListener, Transitions transitions, @ShellMainThread ShellExecutor mainExecutor) { @@ -508,6 +512,7 @@ public abstract class WMShellBaseModule { splitScreenOptional, appPairsOptional, startingSurface, + pipTouchHandlerOptional, fullscreenTaskListener, transitions, mainExecutor);