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

Commit 026873c5 authored by Arthur Hung's avatar Arthur Hung Committed by android-build-merger
Browse files

Merge "Fix touch goes to the window behide PiP" into qt-qpr1-dev

am: 23c1105c

Change-Id: Id59c97b38e29cc4aa3d7abcca383a4ec0964379b
parents 4b279cd1 23c1105c
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.systemui.pip.phone;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;

import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IActivityManager;
@@ -182,7 +185,6 @@ public class PipManager implements BasePipManager {
        ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);

        mInputConsumerController = InputConsumerController.getPipInputConsumer();
        mInputConsumerController.registerInputConsumer();
        mMediaController = new PipMediaController(context, mActivityManager);
        mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController,
                mInputConsumerController);
@@ -190,6 +192,18 @@ public class PipManager implements BasePipManager {
                mMenuController, mInputConsumerController);
        mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
                mTouchHandler.getMotionHelper());

        // If SystemUI restart, and it already existed a pinned stack,
        // register the pip input consumer to ensure touch can send to it.
        try {
            ActivityManager.StackInfo stackInfo = mActivityTaskManager.getStackInfo(
                    WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
            if (stackInfo != null) {
                mInputConsumerController.registerInputConsumer();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
+22 −87
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -64,7 +63,6 @@ import android.util.Pair;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityManager;
@@ -92,6 +90,7 @@ public class PipMenuActivity extends Activity {
    public static final int MESSAGE_UPDATE_ACTIONS = 4;
    public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5;
    public static final int MESSAGE_ANIMATION_ENDED = 6;
    public static final int MESSAGE_TOUCH_EVENT = 7;

    private static final int INITIAL_DISMISS_DELAY = 3500;
    private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
@@ -129,10 +128,6 @@ public class PipMenuActivity extends Activity {
                }
            };

    private PipTouchState mTouchState;
    private PointF mDownPosition = new PointF();
    private PointF mDownDelta = new PointF();
    private ViewConfiguration mViewConfig;
    private Handler mHandler = new Handler();
    private Messenger mToControllerMessenger;
    private Messenger mMessenger = new Messenger(new Handler() {
@@ -170,6 +165,12 @@ public class PipMenuActivity extends Activity {
                    mAllowTouches = true;
                    break;
                }

                case MESSAGE_TOUCH_EVENT: {
                    final MotionEvent ev = (MotionEvent) msg.obj;
                    dispatchTouchEvent(ev);
                    break;
                }
            }
        }
    });
@@ -185,15 +186,7 @@ public class PipMenuActivity extends Activity {
    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);
        mTouchState = new PipTouchState(mViewConfig, mHandler, () -> {
            if (mMenuState == MENU_STATE_CLOSE) {
                showPipMenu();
            } else {
                expandPip();
            }
        });
        getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_SLIPPERY);
        getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.pip_menu_activity);
@@ -205,32 +198,6 @@ public class PipMenuActivity extends Activity {
        mViewRoot.setBackground(mBackgroundDrawable);
        mMenuContainer = findViewById(R.id.menu_container);
        mMenuContainer.setAlpha(0);
        mMenuContainer.setOnTouchListener((v, event) -> {
            mTouchState.onTouchEvent(event);
            switch (event.getAction()) {
                case MotionEvent.ACTION_UP:
                    if (mTouchState.isDoubleTap() || mMenuState == MENU_STATE_FULL) {
                        // Expand to fullscreen if this is a double tap or we are already expanded
                        expandPip();
                    } else if (!mTouchState.isWaitingForDoubleTap()) {
                        // User has stalled long enough for this not to be a drag or a double tap,
                        // just expand the menu if necessary
                        if (mMenuState == MENU_STATE_CLOSE) {
                            showPipMenu();
                        }
                    } 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
                        // next tap
                        mTouchState.scheduleDoubleTapTimeoutCallback();
                    }
                    // Fall through
                case MotionEvent.ACTION_CANCEL:
                    mTouchState.reset();
                    break;
            }
            return true;
        });
        mSettingsButton = findViewById(R.id.settings);
        mSettingsButton.setAlpha(0);
        mSettingsButton.setOnClickListener((v) -> {
@@ -240,8 +207,11 @@ public class PipMenuActivity extends Activity {
        });
        mDismissButton = findViewById(R.id.dismiss);
        mDismissButton.setAlpha(0);
        mDismissButton.setOnClickListener((v) -> {
            dismissPip();
        mDismissButton.setOnClickListener(v -> dismissPip());
        findViewById(R.id.expand_button).setOnClickListener(v -> {
            if (mMenuContainer.getAlpha() != 0) {
                expandPip();
            }
        });
        mActionsGroup = findViewById(R.id.actions_group);
        mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
@@ -301,27 +271,14 @@ public class PipMenuActivity extends Activity {
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (!mAllowTouches) {
            return super.dispatchTouchEvent(ev);
            return false;
        }

        // On the first action outside the window, hide the menu
        switch (ev.getAction()) {
            case MotionEvent.ACTION_OUTSIDE:
                hideMenu();
                break;
            case MotionEvent.ACTION_DOWN:
                mDownPosition.set(ev.getX(), ev.getY());
                mDownDelta.set(0f, 0f);
                break;
            case MotionEvent.ACTION_MOVE:
                mDownDelta.set(ev.getX() - mDownPosition.x, ev.getY() - mDownPosition.y);
                if (mDownDelta.length() > mViewConfig.getScaledTouchSlop()
                        && mMenuState != MENU_STATE_NONE) {
                    // Restore the input consumer and let that drive the movement of this menu
                    notifyRegisterInputConsumer();
                    cancelDelayedFinish();
                }
                break;
                return true;
        }
        return super.dispatchTouchEvent(ev);
    }
@@ -384,7 +341,6 @@ public class PipMenuActivity extends Activity {
            if (allowMenuTimeout) {
                repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
            }
            notifyUnregisterInputConsumer();
        }
    }

@@ -509,12 +465,14 @@ public class PipMenuActivity extends Activity {
                    actionView.setContentDescription(action.getContentDescription());
                    if (action.isEnabled()) {
                        actionView.setOnClickListener(v -> {
                            mHandler.post(() -> {
                                try {
                                    action.getActionIntent().send();
                                } catch (CanceledException e) {
                                    Log.w(TAG, "Failed to send action", e);
                                }
                            });
                        });
                    }
                    actionView.setEnabled(action.isEnabled());
                    actionView.setAlpha(action.isEnabled() ? 1f : DISABLED_ACTION_ALPHA);
@@ -557,18 +515,6 @@ public class PipMenuActivity extends Activity {
        mBackgroundDrawable.setAlpha(alpha);
    }

    private void notifyRegisterInputConsumer() {
        Message m = Message.obtain();
        m.what = PipMenuActivityController.MESSAGE_REGISTER_INPUT_CONSUMER;
        sendMessage(m, "Could not notify controller to register input consumer");
    }

    private void notifyUnregisterInputConsumer() {
        Message m = Message.obtain();
        m.what = PipMenuActivityController.MESSAGE_UNREGISTER_INPUT_CONSUMER;
        sendMessage(m, "Could not notify controller to unregister input consumer");
    }

    private void notifyMenuStateChange(int menuState) {
        mMenuState = menuState;
        Message m = Message.obtain();
@@ -586,11 +532,6 @@ public class PipMenuActivity extends Activity {
        }, false /* notifyMenuVisibility */, false /* isDismissing */);
    }

    private void minimizePip() {
        sendEmptyMessage(PipMenuActivityController.MESSAGE_MINIMIZE_PIP,
                "Could not notify controller to minimize PIP");
    }

    private void dismissPip() {
        // Do not notify menu visibility when hiding the menu, the controller will do this when it
        // handles the message
@@ -600,12 +541,6 @@ public class PipMenuActivity extends Activity {
        }, false /* notifyMenuVisibility */, true /* isDismissing */);
    }

    private void showPipMenu() {
        Message m = Message.obtain();
        m.what = PipMenuActivityController.MESSAGE_SHOW_MENU;
        sendMessage(m, "Could not notify controller to show PIP menu");
    }

    private void showSettings() {
        final Pair<ComponentName, Integer> topPipActivityInfo =
                PipUtils.getTopPinnedActivity(this, ActivityManager.getService());
+20 −18
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import android.view.MotionEvent;

import com.android.systemui.pip.phone.PipMediaController.ActionListener;
import com.android.systemui.shared.system.InputConsumerController;
@@ -156,14 +157,6 @@ public class PipMenuActivityController {
                    mListeners.forEach(l -> l.onPipShowMenu());
                    break;
                }
                case MESSAGE_REGISTER_INPUT_CONSUMER: {
                    mInputConsumerController.registerInputConsumer();
                    break;
                }
                case MESSAGE_UNREGISTER_INPUT_CONSUMER: {
                    mInputConsumerController.unregisterInputConsumer();
                    break;
                }
                case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
                    mToActivityMessenger = msg.replyTo;
                    setStartActivityRequested(false);
@@ -212,15 +205,12 @@ public class PipMenuActivityController {
    }

    public void onActivityPinned() {
        if (mMenuState == MENU_STATE_NONE) {
            // If the menu is not visible, then re-register the input consumer if it is not already
            // registered
        mInputConsumerController.registerInputConsumer();
    }
    }

    public void onActivityUnpinned() {
        hideMenu();
        mInputConsumerController.unregisterInputConsumer();
        setStartActivityRequested(false);
    }

@@ -494,11 +484,7 @@ public class PipMenuActivityController {
            Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState
                    + " menuState=" + menuState + " resize=" + resize);
        }
        if (menuState == MENU_STATE_NONE) {
            mInputConsumerController.registerInputConsumer();
        } else {
            mInputConsumerController.unregisterInputConsumer();
        }

        if (menuState != mMenuState) {
            mListeners.forEach(l -> l.onPipMenuStateChanged(menuState, resize));
            if (menuState == MENU_STATE_FULL) {
@@ -520,6 +506,22 @@ public class PipMenuActivityController {
        mStartActivityRequestedTime = requested ? SystemClock.uptimeMillis() : 0;
    }

    /**
     * Handles touch event sent from pip input consumer.
     */
    void handleTouchEvent(MotionEvent ev) {
        if (mToActivityMessenger != null) {
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_TOUCH_EVENT;
            m.obj = ev;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not dispatch touch event", e);
            }
        }
    }

    public void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + TAG);
+23 −8
Original line number Diff line number Diff line
@@ -363,6 +363,8 @@ public class PipTouchHandler {
        // Update the touch state
        mTouchState.onTouchEvent(ev);

        boolean shouldDeliverToMenu = mMenuState != MENU_STATE_NONE;

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                mMotionHelper.synchronizePinnedStackBounds();
@@ -378,6 +380,8 @@ public class PipTouchHandler {
                        break;
                    }
                }

                shouldDeliverToMenu = !mTouchState.isDragging();
                break;
            }
            case MotionEvent.ACTION_UP: {
@@ -394,6 +398,7 @@ public class PipTouchHandler {
                // Fall through to clean up
            }
            case MotionEvent.ACTION_CANCEL: {
                shouldDeliverToMenu = !mTouchState.startedDragging() && !mTouchState.isDragging();
                mTouchState.reset();
                break;
            }
@@ -425,7 +430,20 @@ public class PipTouchHandler {
                break;
            }
        }
        return mMenuState == MENU_STATE_NONE;

        // Deliver the event to PipMenuActivity to handle button click if the menu has shown.
        if (shouldDeliverToMenu) {
            final MotionEvent cloneEvent = MotionEvent.obtain(ev);
            // Send the cancel event and cancel menu timeout if it starts to drag.
            if (mTouchState.startedDragging()) {
                cloneEvent.setAction(MotionEvent.ACTION_CANCEL);
                mMenuController.pokeMenu();
            }

            mMenuController.handleTouchEvent(cloneEvent);
        }

        return true;
    }

    /**
@@ -741,11 +759,11 @@ public class PipTouchHandler {
                mMotionHelper.animateToClosestSnapTarget(mMovementBounds, null /* updateListener */,
                        null /* animatorListener */);
                setMinimizedStateInternal(false);
            } else if (mMenuState != MENU_STATE_FULL) {
                if (mTouchState.isDoubleTap()) {
            } else if (mTouchState.isDoubleTap()) {
                // Expand to fullscreen if this is a double tap
                mMotionHelper.expandPip();
                } else if (!mTouchState.isWaitingForDoubleTap()) {
            } else if (mMenuState != MENU_STATE_FULL) {
                if (!mTouchState.isWaitingForDoubleTap()) {
                    // 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(),
@@ -756,9 +774,6 @@ public class PipTouchHandler {
                    // next tap
                    mTouchState.scheduleDoubleTapTimeoutCallback();
                }
            } else {
                mMenuController.hideMenu();
                mMotionHelper.expandPip();
            }
            return true;
        }
+1 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ public class PipTouchState {
                mIsDoubleTap = !mPreviouslyDragging &&
                        (mDownTouchTime - mLastDownTouchTime) < DOUBLE_TAP_TIMEOUT;
                mIsWaitingForDoubleTap = false;
                mIsDragging = false;
                mLastDownTouchTime = mDownTouchTime;
                if (mDoubleTapTimeoutCallback != null) {
                    mHandler.removeCallbacks(mDoubleTapTimeoutCallback);