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
This commit is contained in:
Winson Chung
2021-03-01 11:26:55 -08:00
parent af76755ff7
commit 527b6ce657
7 changed files with 94 additions and 70 deletions

View File

@@ -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<LegacySplitScreenController> mLegacySplitScreenOptional;
private final Optional<SplitScreenController> mSplitScreenOptional;
private final Optional<AppPairsController> mAppPairsOptional;
private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
private final FullscreenTaskListener mFullscreenTaskListener;
private final ShellExecutor mMainExecutor;
private final Transitions mTransitions;
@@ -56,6 +58,7 @@ public class ShellInitImpl {
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
Optional<StartingSurface> startingSurfaceOptional,
Optional<PipTouchHandler> 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<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
Optional<StartingSurface> startingSurfaceOptional,
Optional<PipTouchHandler> 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

View File

@@ -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);
}
/**

View File

@@ -102,7 +102,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
* PhysicsAnimator instance for animating {@link PipBoundsState#getMotionBoundsState()}
* using physics animations.
*/
private final PhysicsAnimator<Rect> mTemporaryBoundsPhysicsAnimator;
private PhysicsAnimator<Rect> mTemporaryBoundsPhysicsAnimator;
private MagnetizedObject<Rect> 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() {

View File

@@ -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(

View File

@@ -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<Consumer<Rect>> 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(

View File

@@ -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);

View File

@@ -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<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
Optional<StartingSurface> startingSurface,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
@ShellMainThread ShellExecutor mainExecutor) {
@@ -508,6 +512,7 @@ public abstract class WMShellBaseModule {
splitScreenOptional,
appPairsOptional,
startingSurface,
pipTouchHandlerOptional,
fullscreenTaskListener,
transitions,
mainExecutor);