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

am: 23c1105c1b

Change-Id: Id59c97b38e29cc4aa3d7abcca383a4ec0964379b
This commit is contained in:
Arthur Hung
2019-09-15 09:26:29 -07:00
committed by android-build-merger
5 changed files with 81 additions and 114 deletions

View File

@@ -16,6 +16,9 @@
package com.android.systemui.pip.phone; 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.ActivityManager;
import android.app.ActivityTaskManager; import android.app.ActivityTaskManager;
import android.app.IActivityManager; import android.app.IActivityManager;
@@ -182,7 +185,6 @@ public class PipManager implements BasePipManager {
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
mInputConsumerController = InputConsumerController.getPipInputConsumer(); mInputConsumerController = InputConsumerController.getPipInputConsumer();
mInputConsumerController.registerInputConsumer();
mMediaController = new PipMediaController(context, mActivityManager); mMediaController = new PipMediaController(context, mActivityManager);
mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController, mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController,
mInputConsumerController); mInputConsumerController);
@@ -190,6 +192,18 @@ public class PipManager implements BasePipManager {
mMenuController, mInputConsumerController); mMenuController, mInputConsumerController);
mAppOpsListener = new PipAppOpsListener(context, mActivityManager, mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
mTouchHandler.getMotionHelper()); 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();
}
} }
/** /**

View File

@@ -48,7 +48,6 @@ import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@@ -64,7 +63,6 @@ import android.util.Pair;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; 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.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityManager; 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_ACTIONS = 4;
public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5; public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5;
public static final int MESSAGE_ANIMATION_ENDED = 6; 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 INITIAL_DISMISS_DELAY = 3500;
private static final int POST_INTERACTION_DISMISS_DELAY = 2000; 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 Handler mHandler = new Handler();
private Messenger mToControllerMessenger; private Messenger mToControllerMessenger;
private Messenger mMessenger = new Messenger(new Handler() { private Messenger mMessenger = new Messenger(new Handler() {
@@ -170,6 +165,12 @@ public class PipMenuActivity extends Activity {
mAllowTouches = true; mAllowTouches = true;
break; 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) { protected void onCreate(@Nullable Bundle savedInstanceState) {
// Set the flags to allow us to watch for outside touches and also hide the menu and start // 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 // manipulating the PIP in the same touch gesture
mViewConfig = ViewConfiguration.get(this); getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
mTouchState = new PipTouchState(mViewConfig, mHandler, () -> {
if (mMenuState == MENU_STATE_CLOSE) {
showPipMenu();
} else {
expandPip();
}
});
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);
@@ -205,32 +198,6 @@ public class PipMenuActivity extends Activity {
mViewRoot.setBackground(mBackgroundDrawable); mViewRoot.setBackground(mBackgroundDrawable);
mMenuContainer = findViewById(R.id.menu_container); mMenuContainer = findViewById(R.id.menu_container);
mMenuContainer.setAlpha(0); 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 = findViewById(R.id.settings);
mSettingsButton.setAlpha(0); mSettingsButton.setAlpha(0);
mSettingsButton.setOnClickListener((v) -> { mSettingsButton.setOnClickListener((v) -> {
@@ -240,8 +207,11 @@ public class PipMenuActivity extends Activity {
}); });
mDismissButton = findViewById(R.id.dismiss); mDismissButton = findViewById(R.id.dismiss);
mDismissButton.setAlpha(0); mDismissButton.setAlpha(0);
mDismissButton.setOnClickListener((v) -> { mDismissButton.setOnClickListener(v -> dismissPip());
dismissPip(); findViewById(R.id.expand_button).setOnClickListener(v -> {
if (mMenuContainer.getAlpha() != 0) {
expandPip();
}
}); });
mActionsGroup = findViewById(R.id.actions_group); mActionsGroup = findViewById(R.id.actions_group);
mBetweenActionPaddingLand = getResources().getDimensionPixelSize( mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
@@ -301,27 +271,14 @@ public class PipMenuActivity extends Activity {
@Override @Override
public boolean dispatchTouchEvent(MotionEvent ev) { public boolean dispatchTouchEvent(MotionEvent ev) {
if (!mAllowTouches) { if (!mAllowTouches) {
return super.dispatchTouchEvent(ev); return false;
} }
// On the first action outside the window, hide the menu // On the first action outside the window, hide the menu
switch (ev.getAction()) { switch (ev.getAction()) {
case MotionEvent.ACTION_OUTSIDE: case MotionEvent.ACTION_OUTSIDE:
hideMenu(); hideMenu();
break; return true;
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 super.dispatchTouchEvent(ev); return super.dispatchTouchEvent(ev);
} }
@@ -384,7 +341,6 @@ public class PipMenuActivity extends Activity {
if (allowMenuTimeout) { if (allowMenuTimeout) {
repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY); repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
} }
notifyUnregisterInputConsumer();
} }
} }
@@ -509,11 +465,13 @@ public class PipMenuActivity extends Activity {
actionView.setContentDescription(action.getContentDescription()); actionView.setContentDescription(action.getContentDescription());
if (action.isEnabled()) { if (action.isEnabled()) {
actionView.setOnClickListener(v -> { actionView.setOnClickListener(v -> {
try { mHandler.post(() -> {
action.getActionIntent().send(); try {
} catch (CanceledException e) { action.getActionIntent().send();
Log.w(TAG, "Failed to send action", e); } catch (CanceledException e) {
} Log.w(TAG, "Failed to send action", e);
}
});
}); });
} }
actionView.setEnabled(action.isEnabled()); actionView.setEnabled(action.isEnabled());
@@ -557,18 +515,6 @@ public class PipMenuActivity extends Activity {
mBackgroundDrawable.setAlpha(alpha); 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) { private void notifyMenuStateChange(int menuState) {
mMenuState = menuState; mMenuState = menuState;
Message m = Message.obtain(); Message m = Message.obtain();
@@ -586,11 +532,6 @@ public class PipMenuActivity extends Activity {
}, false /* notifyMenuVisibility */, false /* isDismissing */); }, false /* notifyMenuVisibility */, false /* isDismissing */);
} }
private void minimizePip() {
sendEmptyMessage(PipMenuActivityController.MESSAGE_MINIMIZE_PIP,
"Could not notify controller to minimize PIP");
}
private void dismissPip() { private void dismissPip() {
// Do not notify menu visibility when hiding the menu, the controller will do this when it // Do not notify menu visibility when hiding the menu, the controller will do this when it
// handles the message // handles the message
@@ -600,12 +541,6 @@ public class PipMenuActivity extends Activity {
}, false /* notifyMenuVisibility */, true /* isDismissing */); }, 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() { private void showSettings() {
final Pair<ComponentName, Integer> topPipActivityInfo = final Pair<ComponentName, Integer> topPipActivityInfo =
PipUtils.getTopPinnedActivity(this, ActivityManager.getService()); PipUtils.getTopPinnedActivity(this, ActivityManager.getService());

View File

@@ -37,6 +37,7 @@ import android.os.RemoteException;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.Log; import android.util.Log;
import android.view.MotionEvent;
import com.android.systemui.pip.phone.PipMediaController.ActionListener; import com.android.systemui.pip.phone.PipMediaController.ActionListener;
import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InputConsumerController;
@@ -156,14 +157,6 @@ public class PipMenuActivityController {
mListeners.forEach(l -> l.onPipShowMenu()); mListeners.forEach(l -> l.onPipShowMenu());
break; break;
} }
case MESSAGE_REGISTER_INPUT_CONSUMER: {
mInputConsumerController.registerInputConsumer();
break;
}
case MESSAGE_UNREGISTER_INPUT_CONSUMER: {
mInputConsumerController.unregisterInputConsumer();
break;
}
case MESSAGE_UPDATE_ACTIVITY_CALLBACK: { case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
mToActivityMessenger = msg.replyTo; mToActivityMessenger = msg.replyTo;
setStartActivityRequested(false); setStartActivityRequested(false);
@@ -212,15 +205,12 @@ public class PipMenuActivityController {
} }
public void onActivityPinned() { public void onActivityPinned() {
if (mMenuState == MENU_STATE_NONE) { mInputConsumerController.registerInputConsumer();
// If the menu is not visible, then re-register the input consumer if it is not already
// registered
mInputConsumerController.registerInputConsumer();
}
} }
public void onActivityUnpinned() { public void onActivityUnpinned() {
hideMenu(); hideMenu();
mInputConsumerController.unregisterInputConsumer();
setStartActivityRequested(false); setStartActivityRequested(false);
} }
@@ -494,11 +484,7 @@ public class PipMenuActivityController {
Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState
+ " menuState=" + menuState + " resize=" + resize); + " menuState=" + menuState + " resize=" + resize);
} }
if (menuState == MENU_STATE_NONE) {
mInputConsumerController.registerInputConsumer();
} else {
mInputConsumerController.unregisterInputConsumer();
}
if (menuState != mMenuState) { if (menuState != mMenuState) {
mListeners.forEach(l -> l.onPipMenuStateChanged(menuState, resize)); mListeners.forEach(l -> l.onPipMenuStateChanged(menuState, resize));
if (menuState == MENU_STATE_FULL) { if (menuState == MENU_STATE_FULL) {
@@ -520,6 +506,22 @@ public class PipMenuActivityController {
mStartActivityRequestedTime = requested ? SystemClock.uptimeMillis() : 0; 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) { public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " "; final String innerPrefix = prefix + " ";
pw.println(prefix + TAG); pw.println(prefix + TAG);

View File

@@ -363,6 +363,8 @@ public class PipTouchHandler {
// Update the touch state // Update the touch state
mTouchState.onTouchEvent(ev); mTouchState.onTouchEvent(ev);
boolean shouldDeliverToMenu = mMenuState != MENU_STATE_NONE;
switch (ev.getAction()) { switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: { case MotionEvent.ACTION_DOWN: {
mMotionHelper.synchronizePinnedStackBounds(); mMotionHelper.synchronizePinnedStackBounds();
@@ -378,6 +380,8 @@ public class PipTouchHandler {
break; break;
} }
} }
shouldDeliverToMenu = !mTouchState.isDragging();
break; break;
} }
case MotionEvent.ACTION_UP: { case MotionEvent.ACTION_UP: {
@@ -394,6 +398,7 @@ public class PipTouchHandler {
// Fall through to clean up // Fall through to clean up
} }
case MotionEvent.ACTION_CANCEL: { case MotionEvent.ACTION_CANCEL: {
shouldDeliverToMenu = !mTouchState.startedDragging() && !mTouchState.isDragging();
mTouchState.reset(); mTouchState.reset();
break; break;
} }
@@ -425,7 +430,20 @@ public class PipTouchHandler {
break; 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 */, mMotionHelper.animateToClosestSnapTarget(mMovementBounds, null /* updateListener */,
null /* animatorListener */); null /* animatorListener */);
setMinimizedStateInternal(false); setMinimizedStateInternal(false);
} else if (mTouchState.isDoubleTap()) {
// Expand to fullscreen if this is a double tap
mMotionHelper.expandPip();
} else if (mMenuState != MENU_STATE_FULL) { } else if (mMenuState != MENU_STATE_FULL) {
if (mTouchState.isDoubleTap()) { if (!mTouchState.isWaitingForDoubleTap()) {
// Expand to fullscreen if this is a double tap
mMotionHelper.expandPip();
} else if (!mTouchState.isWaitingForDoubleTap()) {
// User has stalled long enough for this not to be a drag or a double tap, just // User has stalled long enough for this not to be a drag or a double tap, just
// expand the menu // expand the menu
mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
@@ -756,9 +774,6 @@ public class PipTouchHandler {
// next tap // next tap
mTouchState.scheduleDoubleTapTimeoutCallback(); mTouchState.scheduleDoubleTapTimeoutCallback();
} }
} else {
mMenuController.hideMenu();
mMotionHelper.expandPip();
} }
return true; return true;
} }

View File

@@ -106,6 +106,7 @@ public class PipTouchState {
mIsDoubleTap = !mPreviouslyDragging && mIsDoubleTap = !mPreviouslyDragging &&
(mDownTouchTime - mLastDownTouchTime) < DOUBLE_TAP_TIMEOUT; (mDownTouchTime - mLastDownTouchTime) < DOUBLE_TAP_TIMEOUT;
mIsWaitingForDoubleTap = false; mIsWaitingForDoubleTap = false;
mIsDragging = false;
mLastDownTouchTime = mDownTouchTime; mLastDownTouchTime = mDownTouchTime;
if (mDoubleTapTimeoutCallback != null) { if (mDoubleTapTimeoutCallback != null) {
mHandler.removeCallbacks(mDoubleTapTimeoutCallback); mHandler.removeCallbacks(mDoubleTapTimeoutCallback);