diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java index ec15dd16f46e9dc744a40ce24f03173c74b9a142..1982227032cfd90b19bf3cc7fb4093fe9ce1c995 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java @@ -27,7 +27,7 @@ import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ALL import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER; import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION; import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE; -import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS; +import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_MENU_WITH_DELAY; import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS; import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU; import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE; @@ -138,9 +138,9 @@ public class PipMenuActivity extends Activity { final Bundle data = (Bundle) msg.obj; showMenu(data.getInt(EXTRA_MENU_STATE), data.getParcelable(EXTRA_STACK_BOUNDS), - data.getParcelable(EXTRA_MOVEMENT_BOUNDS), data.getBoolean(EXTRA_ALLOW_TIMEOUT), - data.getBoolean(EXTRA_WILL_RESIZE_MENU)); + data.getBoolean(EXTRA_WILL_RESIZE_MENU), + data.getBoolean(EXTRA_SHOW_MENU_WITH_DELAY)); break; } case MESSAGE_POKE_MENU: @@ -177,12 +177,7 @@ public class PipMenuActivity extends Activity { private Messenger mToControllerMessenger; private Messenger mMessenger = new Messenger(mHandler); - private final Runnable mFinishRunnable = new Runnable() { - @Override - public void run() { - hideMenu(); - } - }; + private final Runnable mFinishRunnable = this::hideMenu; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -321,8 +316,8 @@ public class PipMenuActivity extends Activity { // Do nothing } - private void showMenu(int menuState, Rect stackBounds, Rect movementBounds, - boolean allowMenuTimeout, boolean resizeMenuOnShow) { + private void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout, + boolean resizeMenuOnShow, boolean withDelay) { mAllowMenuTimeout = allowMenuTimeout; if (mMenuState != menuState) { // Disallow touches if the menu needs to resize while showing, and we are transitioning @@ -335,7 +330,6 @@ public class PipMenuActivity extends Activity { if (mMenuContainerAnimator != null) { mMenuContainerAnimator.cancel(); } - notifyMenuStateChange(menuState, resizeMenuOnShow); mMenuContainerAnimator = new AnimatorSet(); ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA, mMenuContainer.getAlpha(), 1f); @@ -359,7 +353,13 @@ public class PipMenuActivity extends Activity { } }); } - mMenuContainerAnimator.start(); + if (withDelay) { + // starts the menu container animation after window expansion is completed + notifyMenuStateChange(menuState, resizeMenuOnShow, mMenuContainerAnimator::start); + } else { + notifyMenuStateChange(menuState, resizeMenuOnShow, null /* callback */); + mMenuContainerAnimator.start(); + } } else { // If we are already visible, then just start the delayed dismiss and unregister any // existing input consumers from the previous drag @@ -382,7 +382,7 @@ public class PipMenuActivity extends Activity { if (mMenuState != MENU_STATE_NONE) { cancelDelayedFinish(); if (notifyMenuVisibility) { - notifyMenuStateChange(MENU_STATE_NONE, mResize); + notifyMenuStateChange(MENU_STATE_NONE, mResize, null /* callback */); } mMenuContainerAnimator = new AnimatorSet(); ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA, @@ -434,10 +434,10 @@ public class PipMenuActivity extends Activity { final int menuState = intent.getIntExtra(EXTRA_MENU_STATE, MENU_STATE_NONE); if (menuState != MENU_STATE_NONE) { Rect stackBounds = intent.getParcelableExtra(EXTRA_STACK_BOUNDS); - Rect movementBounds = intent.getParcelableExtra(EXTRA_MOVEMENT_BOUNDS); boolean allowMenuTimeout = intent.getBooleanExtra(EXTRA_ALLOW_TIMEOUT, true); boolean willResizeMenu = intent.getBooleanExtra(EXTRA_WILL_RESIZE_MENU, false); - showMenu(menuState, stackBounds, movementBounds, allowMenuTimeout, willResizeMenu); + boolean withDelay = intent.getBooleanExtra(EXTRA_SHOW_MENU_WITH_DELAY, false); + showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay); } } @@ -540,13 +540,14 @@ public class PipMenuActivity extends Activity { mBackgroundDrawable.setAlpha(alpha); } - private void notifyMenuStateChange(int menuState, boolean resize) { + private void notifyMenuStateChange(int menuState, boolean resize, Runnable callback) { mMenuState = menuState; mResize = resize; Message m = Message.obtain(); m.what = PipMenuActivityController.MESSAGE_MENU_STATE_CHANGED; m.arg1 = menuState; m.arg2 = resize ? 1 : 0; + m.obj = callback; sendMessage(m, "Could not notify controller of PIP menu visibility"); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java index 61ed40d5d78283e867f4143c608d0cba61d63ffb..1608f833c16992cbc0d6427668b04fec269c75d4 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java @@ -60,11 +60,11 @@ public class PipMenuActivityController { public static final String EXTRA_CONTROLLER_MESSENGER = "messenger"; public static final String EXTRA_ACTIONS = "actions"; public static final String EXTRA_STACK_BOUNDS = "stack_bounds"; - public static final String EXTRA_MOVEMENT_BOUNDS = "movement_bounds"; public static final String EXTRA_ALLOW_TIMEOUT = "allow_timeout"; public static final String EXTRA_WILL_RESIZE_MENU = "resize_menu_on_show"; public static final String EXTRA_DISMISS_FRACTION = "dismiss_fraction"; public static final String EXTRA_MENU_STATE = "menu_state"; + public static final String EXTRA_SHOW_MENU_WITH_DELAY = "show_menu_with_delay"; public static final int MESSAGE_MENU_STATE_CHANGED = 100; public static final int MESSAGE_EXPAND_PIP = 101; @@ -89,7 +89,7 @@ public class PipMenuActivityController { * @param menuState the current state of the menu * @param resize whether or not to resize the PiP with the state change */ - void onPipMenuStateChanged(int menuState, boolean resize); + void onPipMenuStateChanged(int menuState, boolean resize, Runnable callback); /** * Called when the PIP requested to be expanded. @@ -130,7 +130,7 @@ public class PipMenuActivityController { case MESSAGE_MENU_STATE_CHANGED: { int menuState = msg.arg1; boolean resize = msg.arg2 != 0; - onMenuStateChanged(menuState, resize); + onMenuStateChanged(menuState, resize, (Runnable) msg.obj); break; } case MESSAGE_EXPAND_PIP: { @@ -155,7 +155,7 @@ public class PipMenuActivityController { // Mark the menu as invisible once the activity finishes as well if (mToActivityMessenger == null) { final boolean resize = msg.arg1 != 0; - onMenuStateChanged(MENU_STATE_NONE, resize); + onMenuStateChanged(MENU_STATE_NONE, resize, null /* callback */); } break; } @@ -247,21 +247,38 @@ public class PipMenuActivityController { // If we haven't requested the start activity, or if it previously took too long to // start, then start it startMenuActivity(MENU_STATE_NONE, null /* stackBounds */, - null /* movementBounds */, false /* allowMenuTimeout */, - false /* resizeMenuOnShow */); + false /* allowMenuTimeout */, false /* resizeMenuOnShow */, + false /* withDelay */); } } /** - * Shows the menu activity. + * Similar to {@link #showMenu(int, Rect, boolean, boolean)} but only show the menu upon + * PiP window transition is finished. */ - public void showMenu(int menuState, Rect stackBounds, Rect movementBounds, - boolean allowMenuTimeout, boolean willResizeMenu) { + public void showMenuWithDelay(int menuState, Rect stackBounds, boolean allowMenuTimeout, + boolean willResizeMenu) { + showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu, + true /* withDelay */); + } + + /** + * Shows the menu activity immediately. + */ + public void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout, + boolean willResizeMenu) { + showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu, + false /* withDelay */); + } + + private void showMenuInternal(int menuState, Rect stackBounds, boolean allowMenuTimeout, + boolean willResizeMenu, boolean withDelay) { if (DEBUG) { Log.d(TAG, "showMenu() state=" + menuState + " hasActivity=" + (mToActivityMessenger != null) + " allowMenuTimeout=" + allowMenuTimeout + " willResizeMenu=" + willResizeMenu + + " withDelay=" + withDelay + " callers=\n" + Debug.getCallers(5, " ")); } @@ -271,9 +288,9 @@ public class PipMenuActivityController { if (stackBounds != null) { data.putParcelable(EXTRA_STACK_BOUNDS, stackBounds); } - data.putParcelable(EXTRA_MOVEMENT_BOUNDS, movementBounds); data.putBoolean(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout); data.putBoolean(EXTRA_WILL_RESIZE_MENU, willResizeMenu); + data.putBoolean(EXTRA_SHOW_MENU_WITH_DELAY, withDelay); Message m = Message.obtain(); m.what = PipMenuActivity.MESSAGE_SHOW_MENU; m.obj = data; @@ -285,8 +302,7 @@ public class PipMenuActivityController { } else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) { // If we haven't requested the start activity, or if it previously took too long to // start, then start it - startMenuActivity(menuState, stackBounds, movementBounds, allowMenuTimeout, - willResizeMenu); + startMenuActivity(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay); } } @@ -364,7 +380,7 @@ public class PipMenuActivityController { * (ie. when manually expanding or dismissing). */ public void hideMenuWithoutResize() { - onMenuStateChanged(MENU_STATE_NONE, false /* resize */); + onMenuStateChanged(MENU_STATE_NONE, false /* resize */, null /* callback */); } /** @@ -388,8 +404,8 @@ public class PipMenuActivityController { /** * Starts the menu activity on the top task of the pinned stack. */ - private void startMenuActivity(int menuState, Rect stackBounds, Rect movementBounds, - boolean allowMenuTimeout, boolean willResizeMenu) { + private void startMenuActivity(int menuState, Rect stackBounds, boolean allowMenuTimeout, + boolean willResizeMenu, boolean withDelay) { try { StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); @@ -402,12 +418,10 @@ public class PipMenuActivityController { if (stackBounds != null) { intent.putExtra(EXTRA_STACK_BOUNDS, stackBounds); } - if (movementBounds != null) { - intent.putExtra(EXTRA_MOVEMENT_BOUNDS, movementBounds); - } intent.putExtra(EXTRA_MENU_STATE, menuState); intent.putExtra(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout); intent.putExtra(EXTRA_WILL_RESIZE_MENU, willResizeMenu); + intent.putExtra(EXTRA_SHOW_MENU_WITH_DELAY, withDelay); ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0); options.setLaunchTaskId( pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]); @@ -472,14 +486,14 @@ public class PipMenuActivityController { /** * Handles changes in menu visibility. */ - private void onMenuStateChanged(int menuState, boolean resize) { + private void onMenuStateChanged(int menuState, boolean resize, Runnable callback) { if (DEBUG) { Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState + " menuState=" + menuState + " resize=" + resize); } if (menuState != mMenuState) { - mListeners.forEach(l -> l.onPipMenuStateChanged(menuState, resize)); + mListeners.forEach(l -> l.onPipMenuStateChanged(menuState, resize, callback)); if (menuState == MENU_STATE_FULL) { // Once visible, start listening for media action changes. This call will trigger // the menu actions to be updated again. diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index b1e4d67585453a21203b58bed9a7f4f0c5735343..162cdbca335180f6baf3483c88a956ddc4a2f274 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.IActivityTaskManager; +import android.content.ComponentName; import android.content.Context; import android.graphics.Rect; import android.os.Debug; @@ -123,6 +124,29 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, */ private boolean mSpringingToTouch = false; + /** + * Gets set in {@link #animateToExpandedState(Rect, Rect, Rect, Runnable)}, this callback is + * used to show menu activity when the expand animation is completed. + */ + private Runnable mPostPipTransitionCallback; + + private final PipTaskOrganizer.PipTransitionCallback mPipTransitionCallback = + new PipTaskOrganizer.PipTransitionCallback() { + @Override + public void onPipTransitionStarted(ComponentName activity, int direction) {} + + @Override + public void onPipTransitionFinished(ComponentName activity, int direction) { + if (mPostPipTransitionCallback != null) { + mPostPipTransitionCallback.run(); + mPostPipTransitionCallback = null; + } + } + + @Override + public void onPipTransitionCanceled(ComponentName activity, int direction) {} + }; + public PipMotionHelper(Context context, IActivityTaskManager activityTaskManager, PipTaskOrganizer pipTaskOrganizer, PipMenuActivityController menuController, PipSnapAlgorithm snapAlgorithm, FlingAnimationUtils flingAnimationUtils, @@ -135,6 +159,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mFlingAnimationUtils = flingAnimationUtils; mFloatingContentCoordinator = floatingContentCoordinator; onConfigurationChanged(); + mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback); } @NonNull @@ -375,9 +400,10 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, * Animates the PiP to the expanded state to show the menu. */ float animateToExpandedState(Rect expandedBounds, Rect movementBounds, - Rect expandedMovementBounds) { + Rect expandedMovementBounds, Runnable callback) { float savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(mBounds), movementBounds); mSnapAlgorithm.applySnapFraction(expandedBounds, expandedMovementBounds, savedSnapFraction); + mPostPipTransitionCallback = callback; resizeAndAnimatePipUnchecked(expandedBounds, EXPAND_STACK_TO_MENU_DURATION); return savedSnapFraction; } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index f5c83c1fffd718431491f29229814243032cffe0..87f0a708b0629b6eaaf114cf00236d89633c7224 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -182,8 +182,8 @@ public class PipTouchHandler { */ private class PipMenuListener implements PipMenuActivityController.Listener { @Override - public void onPipMenuStateChanged(int menuState, boolean resize) { - setMenuState(menuState, resize); + public void onPipMenuStateChanged(int menuState, boolean resize, Runnable callback) { + setMenuState(menuState, resize, callback); } @Override @@ -204,7 +204,7 @@ public class PipTouchHandler { @Override public void onPipShowMenu() { mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), - mMovementBounds, true /* allowMenuTimeout */, willResizeMenu()); + true /* allowMenuTimeout */, willResizeMenu()); } } @@ -234,8 +234,8 @@ public class PipTouchHandler { new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper, deviceConfig, pipTaskOrganizer); mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler, - () -> mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), - mMovementBounds, true /* allowMenuTimeout */, willResizeMenu())); + () -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(), + true /* allowMenuTimeout */, willResizeMenu())); Resources res = context.getResources(); mExpandedShortestEdgeSize = res.getDimensionPixelSize( @@ -322,7 +322,7 @@ public class PipTouchHandler { // Only show the menu if the user isn't currently interacting with the PiP if (!mTouchState.isUserInteracting()) { mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), - mMovementBounds, false /* allowMenuTimeout */, willResizeMenu()); + false /* allowMenuTimeout */, willResizeMenu()); } } @@ -358,7 +358,7 @@ public class PipTouchHandler { if (mShowPipMenuOnAnimationEnd) { mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(), - mMovementBounds, true /* allowMenuTimeout */, false /* willResizeMenu */); + true /* allowMenuTimeout */, false /* willResizeMenu */); mShowPipMenuOnAnimationEnd = false; } } @@ -557,7 +557,7 @@ public class PipTouchHandler { private void onAccessibilityShowMenu() { mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), - mMovementBounds, true /* allowMenuTimeout */, willResizeMenu()); + true /* allowMenuTimeout */, willResizeMenu()); } private boolean handleTouchEvent(InputEvent inputEvent) { @@ -628,8 +628,7 @@ public class PipTouchHandler { // Let's not enable menu show/hide for a11y services. if (!mAccessibilityManager.isTouchExplorationEnabled()) { mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), - mMovementBounds, false /* allowMenuTimeout */, - false /* willResizeMenu */); + false /* allowMenuTimeout */, false /* willResizeMenu */); } case MotionEvent.ACTION_HOVER_MOVE: { if (!shouldDeliverToMenu && !mSendingHoverAccessibilityEvents) { @@ -713,7 +712,7 @@ public class PipTouchHandler { /** * Sets the menu visibility. */ - private void setMenuState(int menuState, boolean resize) { + private void setMenuState(int menuState, boolean resize, Runnable callback) { if (mMenuState == menuState && !resize) { return; } @@ -727,7 +726,7 @@ public class PipTouchHandler { mResizedBounds.set(mMotionHelper.getBounds()); Rect expandedBounds = new Rect(mExpandedBounds); mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds, - mMovementBounds, mExpandedMovementBounds); + mMovementBounds, mExpandedMovementBounds, callback); } } else if (menuState == MENU_STATE_NONE && mMenuState == MENU_STATE_FULL) { // Try and restore the PiP to the closest edge, using the saved snap fraction @@ -893,7 +892,7 @@ public class PipTouchHandler { // If the menu is still visible, then just poke the menu so that // it will timeout after the user stops touching it mMenuController.showMenu(mMenuState, mMotionHelper.getBounds(), - mMovementBounds, true /* allowMenuTimeout */, willResizeMenu()); + true /* allowMenuTimeout */, willResizeMenu()); } else { // If the menu is not visible, then we can still be showing the activity for the // dismiss overlay, so just finish it after the animation completes @@ -917,7 +916,7 @@ public class PipTouchHandler { // User has stalled long enough for this not to be a drag or a double tap, just // expand the menu mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), - mMovementBounds, true /* allowMenuTimeout */, willResizeMenu()); + true /* allowMenuTimeout */, willResizeMenu()); } else { // Next touch event _may_ be the second tap for the double-tap, schedule a // fallback runnable to trigger the menu if no touch event occurs before the