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

Commit da42f4aa authored by Mady Mellor's avatar Mady Mellor Committed by Android (Google) Code Review
Browse files

Merge "Enables drag to dismiss for PiP and adds a dark scrim when dismissing"

parents fe94c2c4 81d40610
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -321,7 +321,7 @@ public class PipSnapAlgorithm {
                stackBounds.top));
        boundsOut.set(stackBounds);
        if (mIsMinimized) {
            boundsOut.offsetTo(boundedLeft, boundsOut.top);
            boundsOut.offsetTo(boundedLeft, boundedTop);
            return;
        }

+47 −42
Original line number Diff line number Diff line
@@ -15,11 +15,15 @@
-->
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/menu"
    android:id="@+id/background"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#4D000000">
    <!-- The above background is only for the dismiss button ripple to show. -->
    android:layout_height="match_parent">

  <!-- Menu layout -->
  <FrameLayout
      android:id="@+id/menu_container"
      android:layout_width="match_parent"
      android:layout_height="match_parent">

      <ImageView
          android:id="@+id/dismiss"
@@ -62,3 +66,4 @@
              android:showDividers="middle" />
      </FrameLayout>
  </FrameLayout>
</FrameLayout>
+52 −7
Original line number Diff line number Diff line
@@ -20,10 +20,12 @@ import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ACT
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_MENU;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
@@ -35,6 +37,8 @@ import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Handler;
@@ -71,13 +75,19 @@ public class PipMenuActivity extends Activity {
    public static final int MESSAGE_POKE_MENU = 2;
    public static final int MESSAGE_HIDE_MENU = 3;
    public static final int MESSAGE_UPDATE_ACTIONS = 4;
    public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5;

    private static final long INITIAL_DISMISS_DELAY = 2000;
    private static final long POST_INTERACTION_DISMISS_DELAY = 1500;
    private static final long MENU_FADE_DURATION = 125;

    private static final float MENU_BACKGROUND_ALPHA = 0.3f;
    private static final float DISMISS_BACKGROUND_ALPHA = 0.8f;

    private boolean mMenuVisible;
    private final List<RemoteAction> mActions = new ArrayList<>();
    private View mViewRoot;
    private Drawable mBackgroundDrawable;
    private View mMenuContainer;
    private LinearLayout mActionsGroup;
    private View mDismissButton;
@@ -85,6 +95,14 @@ public class PipMenuActivity extends Activity {
    private int mBetweenActionPaddingLand;

    private ObjectAnimator mMenuContainerAnimator;
    private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener =
            new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    final float alpha = (float) animation.getAnimatedValue();
                    mBackgroundDrawable.setAlpha((int) (MENU_BACKGROUND_ALPHA*alpha*255));
                }
            };

    private PointF mDownPosition = new PointF();
    private PointF mDownDelta = new PointF();
@@ -109,6 +127,10 @@ public class PipMenuActivity extends Activity {
                    Pair<Rect, ParceledListSlice> data = (Pair<Rect, ParceledListSlice>) msg.obj;
                    setActions(data.first, data.second.getList());
                    break;
                case MESSAGE_UPDATE_DISMISS_FRACTION:
                    float fraction = (float) msg.obj;
                    updateDismissFraction(fraction);
                    break;
            }
        }
    });
@@ -130,7 +152,12 @@ public class PipMenuActivity extends Activity {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pip_menu_activity);

        mMenuContainer = findViewById(R.id.menu);
        mBackgroundDrawable = new ColorDrawable(Color.BLACK);
        mBackgroundDrawable.setAlpha(0);
        mViewRoot = findViewById(R.id.background);
        mViewRoot.setBackground(mBackgroundDrawable);
        mMenuContainer = findViewById(R.id.menu_container);
        mMenuContainer.setAlpha(0);
        mMenuContainer.setOnClickListener((v) -> {
            expandPip();
        });
@@ -222,10 +249,10 @@ public class PipMenuActivity extends Activity {

    private void showMenu(Rect stackBounds, Rect movementBounds) {
        if (!mMenuVisible) {
            updateActionViews(stackBounds);
            if (mMenuContainerAnimator != null) {
                mMenuContainerAnimator.cancel();
            }

            notifyMenuVisibility(true);
            updateExpandButtonFromBounds(stackBounds, movementBounds);
            mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
@@ -238,6 +265,7 @@ public class PipMenuActivity extends Activity {
                    repostDelayedFinish(INITIAL_DISMISS_DELAY);
                }
            });
            mMenuContainerAnimator.addUpdateListener(mMenuBgUpdateListener);
            mMenuContainerAnimator.start();
        } else {
            repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
@@ -269,21 +297,25 @@ public class PipMenuActivity extends Activity {
                    }
                }
            });
            mMenuContainerAnimator.addUpdateListener(mMenuBgUpdateListener);
            mMenuContainerAnimator.start();
        }
    }

    private void updateFromIntent(Intent intent) {
        Rect stackBounds = Rect.unflattenFromString(intent.getStringExtra(EXTRA_STACK_BOUNDS));
        Rect movementBounds = Rect.unflattenFromString(intent.getStringExtra(
                EXTRA_MOVEMENT_BOUNDS));
        mToControllerMessenger = intent.getParcelableExtra(EXTRA_CONTROLLER_MESSENGER);
        ParceledListSlice actions = intent.getParcelableExtra(EXTRA_ACTIONS);
        if (actions != null) {
            setActions(stackBounds, actions.getList());
            mActions.clear();
            mActions.addAll(actions.getList());
        }
        if (intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) {
            Rect stackBounds = Rect.unflattenFromString(intent.getStringExtra(EXTRA_STACK_BOUNDS));
            Rect movementBounds = Rect.unflattenFromString(intent.getStringExtra(
                    EXTRA_MOVEMENT_BOUNDS));
            showMenu(stackBounds, movementBounds);
        }
    }

    private void updateExpandButtonFromBounds(Rect stackBounds, Rect movementBounds) {
        if (stackBounds == null) {
@@ -365,6 +397,19 @@ public class PipMenuActivity extends Activity {
        }
    }

    private void updateDismissFraction(float fraction) {
        int alpha;
        if (mMenuVisible) {
            mMenuContainer.setAlpha(1-fraction);
            final float interpolatedAlpha =
                    MENU_BACKGROUND_ALPHA * (1.0f - fraction) + DISMISS_BACKGROUND_ALPHA * fraction;
            alpha = (int) (interpolatedAlpha*255);
        } else {
            alpha = (int) (fraction*DISMISS_BACKGROUND_ALPHA*255);
        }
        mBackgroundDrawable.setAlpha(alpha);
    }

    private void notifyRegisterInputConsumer() {
        Message m = Message.obtain();
        m.what = PipMenuActivityController.MESSAGE_REGISTER_INPUT_CONSUMER;
+58 −23
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ import java.util.ArrayList;
import java.util.List;

/**
 * Manages the PiP menu activity.
 * Manages the PiP menu activity which can show menu options or a scrim.
 *
 * The current media session provides actions whenever there are no valid actions provided by the
 * current PiP activity. Otherwise, those actions always take precedence.
@@ -55,6 +55,7 @@ public class PipMenuActivityController {
    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_SHOW_MENU = "show_menu";

    public static final int MESSAGE_MENU_VISIBILITY_CHANGED = 100;
    public static final int MESSAGE_EXPAND_PIP = 101;
@@ -101,6 +102,7 @@ public class PipMenuActivityController {
    private ParceledListSlice mMediaActions;
    private boolean mMenuVisible;

    private boolean mStartActivityRequested;
    private Messenger mToActivityMessenger;
    private Messenger mMessenger = new Messenger(new Handler() {
        @Override
@@ -135,6 +137,7 @@ public class PipMenuActivityController {
                }
                case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
                    mToActivityMessenger = msg.replyTo;
                    mStartActivityRequested = false;
                    // Mark the menu as invisible once the activity finishes as well
                    if (mToActivityMessenger == null) {
                        onMenuVisibilityChanged(false, true /* resize */);
@@ -178,6 +181,25 @@ public class PipMenuActivityController {
        }
    }

    /**
     * Updates the appearance of the menu and scrim on top of the PiP while dismissing.
     */
    public void setDismissFraction(float fraction) {
        if (mToActivityMessenger != null) {
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_UPDATE_DISMISS_FRACTION;
            m.obj = fraction;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify menu to show", e);
            }
        } else if (!mStartActivityRequested) {
            startMenuActivity(null /* stackBounds */, null /* movementBounds */,
                    false /* showMenu */);
        }
    }

    /**
     * Shows the menu activity.
     */
@@ -191,28 +213,8 @@ public class PipMenuActivityController {
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify menu to show", e);
            }
        } else {
            // Start the menu activity on the top task of the pinned stack
            try {
                StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
                if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
                        pinnedStackInfo.taskIds.length > 0) {
                    Intent intent = new Intent(mContext, PipMenuActivity.class);
                    intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
                    intent.putExtra(EXTRA_ACTIONS, resolveMenuActions());
                    intent.putExtra(EXTRA_STACK_BOUNDS, stackBounds.flattenToString());
                    intent.putExtra(EXTRA_MOVEMENT_BOUNDS, movementBounds.flattenToString());
                    ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
                    options.setLaunchTaskId(
                            pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
                    options.setTaskOverlay(true, true /* canResume */);
                    mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
                } else {
                    Log.e(TAG, "No PIP tasks found");
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Error showing PIP menu activity", e);
            }
        } else if (!mStartActivityRequested) {
            startMenuActivity(stackBounds, movementBounds, true /* showMenu */);
        }
    }

@@ -271,6 +273,39 @@ public class PipMenuActivityController {
        return mMediaActions;
    }

    /**
     * Starts the menu activity on the top task of the pinned stack.
     */
    private void startMenuActivity(Rect stackBounds, Rect movementBounds, boolean showMenu) {
        try {
            StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
            if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
                    pinnedStackInfo.taskIds.length > 0) {
                Intent intent = new Intent(mContext, PipMenuActivity.class);
                intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
                intent.putExtra(EXTRA_ACTIONS, resolveMenuActions());
                if (stackBounds != null) {
                    intent.putExtra(EXTRA_STACK_BOUNDS, stackBounds.flattenToString());
                }
                if (movementBounds != null) {
                    intent.putExtra(EXTRA_MOVEMENT_BOUNDS, movementBounds.flattenToString());
                }
                intent.putExtra(EXTRA_SHOW_MENU, showMenu);
                ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
                options.setLaunchTaskId(
                        pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
                options.setTaskOverlay(true, true /* canResume */);
                mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
                mStartActivityRequested = true;
            } else {
                Log.e(TAG, "No PIP tasks found");
            }
        } catch (RemoteException e) {
            mStartActivityRequested = false;
            Log.e(TAG, "Error showing PIP menu activity", e);
        }
    }

    /**
     * Updates the PiP menu activity with the best set of actions provided.
     */
+21 −7
Original line number Diff line number Diff line
@@ -65,9 +65,9 @@ public class PipMotionHelper {
    private static final int IME_SHIFT_DURATION = 300;

    // The fraction of the stack width that the user has to drag offscreen to minimize the PiP
    private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f;
    // The fraction of the stack height that the user has to drag offscreen to minimize the PiP
    private static final float DISMISS_OFFSCREEN_FRACTION = 0.35f;
    private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.3f;
    // The fraction of the stack height that the user has to drag offscreen to dismiss the PiP
    private static final float DISMISS_OFFSCREEN_FRACTION = 0.15f;

    private Context mContext;
    private IActivityManager mActivityManager;
@@ -234,12 +234,16 @@ public class PipMotionHelper {
    /**
     * Animates the PiP to the minimized state, slightly offscreen.
     */
    Rect animateToClosestMinimizedState(Rect movementBounds) {
    Rect animateToClosestMinimizedState(Rect movementBounds,
            AnimatorUpdateListener updateListener) {
        cancelAnimations();
        Rect toBounds = getClosestMinimizedBounds(mBounds, movementBounds);
        if (!mBounds.equals(toBounds)) {
            mBoundsAnimator = createAnimationToBounds(mBounds, toBounds,
                    MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, mUpdateBoundsListener);
            if (updateListener != null) {
                mBoundsAnimator.addUpdateListener(updateListener);
            }
            mBoundsAnimator.start();
        }
        return toBounds;
@@ -248,7 +252,8 @@ public class PipMotionHelper {
    /**
     * Flings the PiP to the closest snap target.
     */
    Rect flingToSnapTarget(float velocity, float velocityX, float velocityY, Rect movementBounds) {
    Rect flingToSnapTarget(float velocity, float velocityX, float velocityY, Rect movementBounds,
            AnimatorUpdateListener listener) {
        cancelAnimations();
        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds,
                velocityX, velocityY);
@@ -258,6 +263,9 @@ public class PipMotionHelper {
            mFlingAnimationUtils.apply(mBoundsAnimator, 0,
                    distanceBetweenRectOffsets(mBounds, toBounds),
                    velocity);
            if (listener != null) {
                mBoundsAnimator.addUpdateListener(listener);
            }
            mBoundsAnimator.start();
        }
        return toBounds;
@@ -266,12 +274,15 @@ public class PipMotionHelper {
    /**
     * Animates the PiP to the closest snap target.
     */
    Rect animateToClosestSnapTarget(Rect movementBounds) {
    Rect animateToClosestSnapTarget(Rect movementBounds, AnimatorUpdateListener listener) {
        cancelAnimations();
        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds);
        if (!mBounds.equals(toBounds)) {
            mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, SNAP_STACK_DURATION,
                    FAST_OUT_SLOW_IN, mUpdateBoundsListener);
            if (listener != null) {
                mBoundsAnimator.addUpdateListener(listener);
            }
            mBoundsAnimator.start();
        }
        return toBounds;
@@ -316,7 +327,7 @@ public class PipMotionHelper {
    /**
     * Animates the dismissal of the PiP off the edge of the screen.
     */
    Rect animateDragToEdgeDismiss(Rect pipBounds) {
    Rect animateDragToEdgeDismiss(Rect pipBounds, AnimatorUpdateListener listener) {
        cancelAnimations();
        Point displaySize = new Point();
        mContext.getDisplay().getRealSize(displaySize);
@@ -330,6 +341,9 @@ public class PipMotionHelper {
                dismissPip();
            }
        });
        if (listener != null) {
            mBoundsAnimator.addUpdateListener(listener);
        }
        mBoundsAnimator.start();
        return toBounds;
    }
Loading