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

Commit da8b27ce authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fixing some interaction issues with the PIP menu."

parents 9bab1c4d c75ffe8c
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -427,6 +427,7 @@
            android:supportsPictureInPicture="true"
            android:supportsPictureInPicture="true"
            android:stateNotNeeded="true"
            android:stateNotNeeded="true"
            android:taskAffinity=""
            android:taskAffinity=""
            android:launchMode="singleTop"
            androidprv:alwaysFocusable="true" />
            androidprv:alwaysFocusable="true" />


        <!-- platform logo easter egg activity -->
        <!-- platform logo easter egg activity -->
+3 −3
Original line number Original line Diff line number Diff line
@@ -19,7 +19,7 @@
    android:id="@+id/menu"
    android:id="@+id/menu"
    android:layout_width="match_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_height="match_parent"
    android:background="#33000000">
    android:background="#66000000">


    <LinearLayout
    <LinearLayout
        android:id="@+id/actions"
        android:id="@+id/actions"
@@ -45,7 +45,7 @@
            android:text="@string/pip_phone_dismiss"
            android:text="@string/pip_phone_dismiss"
            android:background="?android:selectableItemBackground" />
            android:background="?android:selectableItemBackground" />
        <TextView
        <TextView
            android:id="@+id/minimize"
            android:id="@+id/expand"
            android:layout_width="0dp"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_weight="1"
@@ -53,7 +53,7 @@
            android:textSize="12sp"
            android:textSize="12sp"
            android:textColor="#ffffffff"
            android:textColor="#ffffffff"
            android:fontFamily="sans-serif"
            android:fontFamily="sans-serif"
            android:text="@string/pip_phone_minimize"
            android:text="@string/pip_phone_expand"
            android:background="?android:selectableItemBackground" />
            android:background="?android:selectableItemBackground" />
    </LinearLayout>
    </LinearLayout>
</FrameLayout>
</FrameLayout>
+1 −1
Original line number Original line Diff line number Diff line
@@ -68,7 +68,7 @@
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowBackground">@drawable/forced_resizable_background</item>
        <item name="android:windowBackground">@null</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:statusBarColor">@color/transparent</item>
        <item name="android:statusBarColor">@color/transparent</item>
        <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item>
        <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item>
+143 −28
Original line number Original line Diff line number Diff line
@@ -16,13 +16,16 @@


package com.android.systemui.pip.phone;
package com.android.systemui.pip.phone;


import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.PendingIntent.CanceledException;
import android.app.RemoteAction;
import android.app.RemoteAction;
import android.content.Intent;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.content.pm.ParceledListSlice;
import android.graphics.PointF;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler;
import android.os.Message;
import android.os.Message;
@@ -30,11 +33,15 @@ import android.os.Messenger;
import android.os.RemoteException;
import android.os.RemoteException;
import android.util.Log;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.ImageView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.TextView;


import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.R;


import java.util.ArrayList;
import java.util.ArrayList;
@@ -47,28 +54,40 @@ public class PipMenuActivity extends Activity {


    private static final String TAG = "PipMenuActivity";
    private static final String TAG = "PipMenuActivity";


    public static final int MESSAGE_FINISH_SELF = 1;
    public static final int MESSAGE_SHOW_MENU = 1;
    public static final int MESSAGE_UPDATE_ACTIONS = 2;
    public static final int MESSAGE_HIDE_MENU = 2;
    public static final int MESSAGE_UPDATE_ACTIONS = 3;


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


    private List<RemoteAction> mActions = new ArrayList<>();
    private boolean mMenuVisible;
    private final List<RemoteAction> mActions = new ArrayList<>();
    private View mMenuContainer;
    private View mDismissButton;
    private View mDismissButton;
    private View mMinimizeButton;
    private View mExpandButton;


    private ObjectAnimator mMenuContainerAnimator;

    private PointF mDownPosition = new PointF();
    private PointF mDownDelta = new PointF();
    private ViewConfiguration mViewConfig;
    private Handler mHandler = new Handler();
    private Handler mHandler = new Handler();
    private Messenger mToControllerMessenger;
    private Messenger mToControllerMessenger;
    private Messenger mMessenger = new Messenger(new Handler() {
    private Messenger mMessenger = new Messenger(new Handler() {
        @Override
        @Override
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            switch (msg.what) {
                case MESSAGE_SHOW_MENU:
                    showMenu();
                    break;
                case MESSAGE_HIDE_MENU:
                    hideMenu();
                    break;
                case MESSAGE_UPDATE_ACTIONS:
                case MESSAGE_UPDATE_ACTIONS:
                    setActions(((ParceledListSlice) msg.obj).getList());
                    setActions(((ParceledListSlice) msg.obj).getList());
                    break;
                    break;
                case MESSAGE_FINISH_SELF:
                    finish();
                    break;
            }
            }
        }
        }
    });
    });
@@ -76,12 +95,17 @@ public class PipMenuActivity extends Activity {
    private final Runnable mFinishRunnable = new Runnable() {
    private final Runnable mFinishRunnable = new Runnable() {
        @Override
        @Override
        public void run() {
        public void run() {
            finish();
            hideMenu();
        }
        }
    };
    };


    @Override
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        // Set the flags to allow us to watch for outside touches and also hide the menu and start
        // manipulating the PIP in the same touch gesture
        mViewConfig = ViewConfiguration.get(this);
        getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_SLIPPERY);

        super.onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pip_menu_activity);
        setContentView(R.layout.pip_menu_activity);


@@ -94,44 +118,74 @@ public class PipMenuActivity extends Activity {
            setActions(actions.getList());
            setActions(actions.getList());
        }
        }


        findViewById(R.id.menu).setOnClickListener((v) -> {
        mMenuContainer = findViewById(R.id.menu);
        mMenuContainer.setOnClickListener((v) -> {
            expandPip();
            expandPip();
        });
        });
        mDismissButton = findViewById(R.id.dismiss);
        mDismissButton = findViewById(R.id.dismiss);
        mDismissButton.setOnClickListener((v) -> {
        mDismissButton.setOnClickListener((v) -> {
            dismissPip();
            dismissPip();
        });
        });
        mMinimizeButton = findViewById(R.id.minimize);
        mExpandButton = findViewById(R.id.expand);
        mMinimizeButton.setOnClickListener((v) -> {
        mExpandButton.setOnClickListener((v) -> {
            minimizePip();
            expandPip();
        });
        });

        notifyActivityCallback(mMessenger);
        showMenu();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        showMenu();
    }
    }


    @Override
    @Override
    protected void onStart() {
    protected void onStart() {
        super.onStart();
        super.onStart();
        notifyActivityVisibility(true);
        notifyMenuVisibility(true);
        repostDelayedFinish(INITIAL_DISMISS_DELAY);
        repostDelayedFinish(INITIAL_DISMISS_DELAY);
    }
    }


    @Override
    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
        if (!isInPictureInPictureMode) {
            finish();
        }
    }

    @Override
    @Override
    public void onUserInteraction() {
    public void onUserInteraction() {
        repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
        repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
    }
    }


    @Override
    @Override
    protected void onStop() {
    public boolean dispatchTouchEvent(MotionEvent ev) {
        super.onStop();
        // On the first action outside the window, hide the menu
        finish();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_OUTSIDE:
                hideMenu();
                break;
            case MotionEvent.ACTION_DOWN:
                mDownPosition.set(ev.getX(), ev.getY());
                break;
            case MotionEvent.ACTION_MOVE:
                mDownDelta.set(ev.getX() - mDownPosition.x, ev.getY() - mDownPosition.y);
                if (mDownDelta.length() > mViewConfig.getScaledTouchSlop() && mMenuVisible) {
                    hideMenu();
                    mMenuVisible = false;
                }
        }
        return super.dispatchTouchEvent(ev);
    }
    }


    @Override
    @Override
    public void finish() {
    public void finish() {
        View v = getWindow().getDecorView();
        notifyActivityCallback(null);
        v.removeCallbacks(mFinishRunnable);
        notifyActivityVisibility(false);
        super.finish();
        super.finish();
        overridePendingTransition(0, R.anim.forced_resizable_exit);
        // Hide without an animation (the menu should already be invisible at this point)
        overridePendingTransition(0, 0);
    }
    }


    @Override
    @Override
@@ -139,6 +193,51 @@ public class PipMenuActivity extends Activity {
        // Do nothing
        // Do nothing
    }
    }


    private void showMenu() {
        if (!mMenuVisible) {
            if (mMenuContainerAnimator != null) {
                mMenuContainerAnimator.cancel();
            }

            notifyMenuVisibility(true);
            mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
                    mMenuContainer.getAlpha(), 1f);
            mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
            mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
            mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    repostDelayedFinish(INITIAL_DISMISS_DELAY);
                }
            });
            mMenuContainerAnimator.start();
        }
    }

    private void hideMenu() {
        hideMenu(null /* animationFinishedRunnable */);
    }

    private void hideMenu(final Runnable animationFinishedRunnable) {
        if (mMenuVisible) {
            cancelDelayedFinish();
            notifyMenuVisibility(false);
            mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
                    mMenuContainer.getAlpha(), 0f);
            mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
            mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
            mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    if (animationFinishedRunnable != null) {
                        animationFinishedRunnable.run();
                    }
                }
            });
            mMenuContainerAnimator.start();
        }
    }

    private void setActions(List<RemoteAction> actions) {
    private void setActions(List<RemoteAction> actions) {
        mActions.clear();
        mActions.clear();
        mActions.addAll(actions);
        mActions.addAll(actions);
@@ -173,17 +272,19 @@ public class PipMenuActivity extends Activity {
        }
        }
    }
    }


    private void notifyActivityVisibility(boolean visible) {
    private void notifyMenuVisibility(boolean visible) {
        mMenuVisible = visible;
        Message m = Message.obtain();
        Message m = Message.obtain();
        m.what = PipMenuActivityController.MESSAGE_ACTIVITY_VISIBILITY_CHANGED;
        m.what = PipMenuActivityController.MESSAGE_MENU_VISIBILITY_CHANGED;
        m.arg1 = visible ? 1 : 0;
        m.arg1 = visible ? 1 : 0;
        m.replyTo = visible ? mMessenger : null;
        sendMessage(m, "Could not notify controller of PIP menu visibility");
        sendMessage(m, "Could not notify controller of PIP menu visibility");
    }
    }


    private void expandPip() {
    private void expandPip() {
        hideMenu(() -> {
            sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP,
            sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP,
                    "Could not notify controller to expand PIP");
                    "Could not notify controller to expand PIP");
        });
    }
    }


    private void minimizePip() {
    private void minimizePip() {
@@ -192,8 +293,17 @@ public class PipMenuActivity extends Activity {
    }
    }


    private void dismissPip() {
    private void dismissPip() {
        hideMenu(() -> {
            sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP,
            sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP,
                    "Could not notify controller to dismiss PIP");
                    "Could not notify controller to dismiss PIP");
        });
    }

    private void notifyActivityCallback(Messenger callback) {
        Message m = Message.obtain();
        m.what = PipMenuActivityController.MESSAGE_UPDATE_ACTIVITY_CALLBACK;
        m.replyTo = callback;
        sendMessage(m, "Could not notify controller of activity finished");
    }
    }


    private void sendEmptyMessage(int what, String errorMsg) {
    private void sendEmptyMessage(int what, String errorMsg) {
@@ -210,6 +320,11 @@ public class PipMenuActivity extends Activity {
        }
        }
    }
    }


    private void cancelDelayedFinish() {
        View v = getWindow().getDecorView();
        v.removeCallbacks(mFinishRunnable);
    }

    private void repostDelayedFinish(long delay) {
    private void repostDelayedFinish(long delay) {
        View v = getWindow().getDecorView();
        View v = getWindow().getDecorView();
        v.removeCallbacks(mFinishRunnable);
        v.removeCallbacks(mFinishRunnable);
+40 −39
Original line number Original line Diff line number Diff line
@@ -25,10 +25,11 @@ public class PipMenuActivityController {
    public static final String EXTRA_CONTROLLER_MESSENGER = "messenger";
    public static final String EXTRA_CONTROLLER_MESSENGER = "messenger";
    public static final String EXTRA_ACTIONS = "actions";
    public static final String EXTRA_ACTIONS = "actions";


    public static final int MESSAGE_ACTIVITY_VISIBILITY_CHANGED = 100;
    public static final int MESSAGE_MENU_VISIBILITY_CHANGED = 100;
    public static final int MESSAGE_EXPAND_PIP = 101;
    public static final int MESSAGE_EXPAND_PIP = 101;
    public static final int MESSAGE_MINIMIZE_PIP = 102;
    public static final int MESSAGE_MINIMIZE_PIP = 102;
    public static final int MESSAGE_DISMISS_PIP = 103;
    public static final int MESSAGE_DISMISS_PIP = 103;
    public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104;


    /**
    /**
     * A listener interface to receive notification on changes in PIP.
     * A listener interface to receive notification on changes in PIP.
@@ -67,34 +68,25 @@ public class PipMenuActivityController {
        @Override
        @Override
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            switch (msg.what) {
                case MESSAGE_ACTIVITY_VISIBILITY_CHANGED: {
                case MESSAGE_MENU_VISIBILITY_CHANGED: {
                    boolean visible = msg.arg1 > 0;
                    boolean visible = msg.arg1 > 0;
                    int listenerCount = mListeners.size();
                    mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible));
                    for (int i = 0; i < listenerCount; i++) {
                        mListeners.get(i).onPipMenuVisibilityChanged(visible);
                    }
                    mToActivityMessenger = msg.replyTo;
                    break;
                    break;
                }
                }
                case MESSAGE_EXPAND_PIP: {
                case MESSAGE_EXPAND_PIP: {
                    int listenerCount = mListeners.size();
                    mListeners.forEach(l -> l.onPipExpand());
                    for (int i = 0; i < listenerCount; i++) {
                        mListeners.get(i).onPipExpand();
                    }
                    break;
                    break;
                }
                }
                case MESSAGE_MINIMIZE_PIP: {
                case MESSAGE_MINIMIZE_PIP: {
                    int listenerCount = mListeners.size();
                    mListeners.forEach(l -> l.onPipMinimize());
                    for (int i = 0; i < listenerCount; i++) {
                        mListeners.get(i).onPipMinimize();
                    }
                    break;
                    break;
                }
                }
                case MESSAGE_DISMISS_PIP: {
                case MESSAGE_DISMISS_PIP: {
                    int listenerCount = mListeners.size();
                    mListeners.forEach(l -> l.onPipDismiss());
                    for (int i = 0; i < listenerCount; i++) {
                    break;
                        mListeners.get(i).onPipDismiss();
                }
                }
                case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
                    mToActivityMessenger = msg.replyTo;
                    break;
                    break;
                }
                }
            }
            }
@@ -121,6 +113,15 @@ public class PipMenuActivityController {
     * Shows the menu activity.
     * Shows the menu activity.
     */
     */
    public void showMenu() {
    public void showMenu() {
        if (mToActivityMessenger != null) {
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_SHOW_MENU;
            try {
                mToActivityMessenger.send(m);
            } 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
            // Start the menu activity on the top task of the pinned stack
            try {
            try {
                StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
                StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
@@ -129,7 +130,7 @@ public class PipMenuActivityController {
                    Intent intent = new Intent(mContext, PipMenuActivity.class);
                    Intent intent = new Intent(mContext, PipMenuActivity.class);
                    intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
                    intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
                    intent.putExtra(EXTRA_ACTIONS, mActions);
                    intent.putExtra(EXTRA_ACTIONS, mActions);
                ActivityOptions options = ActivityOptions.makeBasic();
                    ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
                    options.setLaunchTaskId(
                    options.setLaunchTaskId(
                            pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
                            pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
                    options.setTaskOverlay(true);
                    options.setTaskOverlay(true);
@@ -141,6 +142,7 @@ public class PipMenuActivityController {
                Log.e(TAG, "Error showing PIP menu activity", e);
                Log.e(TAG, "Error showing PIP menu activity", e);
            }
            }
        }
        }
    }


    /**
    /**
     * Hides the menu activity.
     * Hides the menu activity.
@@ -148,13 +150,12 @@ public class PipMenuActivityController {
    public void hideMenu() {
    public void hideMenu() {
        if (mToActivityMessenger != null) {
        if (mToActivityMessenger != null) {
            Message m = Message.obtain();
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_FINISH_SELF;
            m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
            try {
            try {
                mToActivityMessenger.send(m);
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify menu activity to finish", e);
                Log.e(TAG, "Could not notify menu to hide", e);
            }
            }
            mToActivityMessenger = null;
        }
        }
    }
    }


Loading