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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user