Forwarding touch events from TouchInteractionService to Launcher

when launcher window is visible

Change-Id: I418994c2e2a5559c28c36875ac7aff589a15fac5
This commit is contained in:
Sunny Goyal 2017-11-20 18:00:42 -08:00
parent 635329a5ab
commit 0607cf03ea
2 changed files with 120 additions and 19 deletions

View File

@ -62,6 +62,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mSnapshotView = findViewById(R.id.snapshot);
mIconView = findViewById(R.id.icon);
}

View File

@ -15,8 +15,15 @@
*/
package com.android.quickstep;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityOptions;
import android.app.Service;
@ -29,6 +36,7 @@ import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
@ -37,9 +45,12 @@ import android.view.Choreographer;
import android.view.Display;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.util.TraceHelper;
@ -51,9 +62,12 @@ import com.android.systemui.shared.recents.model.RecentsTaskLoader;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.BackgroundExecutor;
import java.util.function.Consumer;
/**
* Service connected by system-UI for handling touch interaction.
*/
@TargetApi(Build.VERSION_CODES.O)
public class TouchInteractionService extends Service {
private static final String TAG = "TouchInteractionService";
@ -73,6 +87,10 @@ public class TouchInteractionService extends Service {
}
};
private final Consumer<MotionEvent> mOtherActivityTouchConsumer
= this::handleTouchDownOnOtherActivity;
private final Consumer<MotionEvent> mNoOpTouchConsumer = (ev) -> {};
private ActivityManagerWrapper mAM;
private RunningTaskInfo mRunningTask;
private Intent mHomeIntent;
@ -80,8 +98,6 @@ public class TouchInteractionService extends Service {
private MotionEventQueue mEventQueue;
private MainThreadExecutor mMainThreadExecutor;
private int mDisplayRotation;
private final Point mDisplaySize = new Point();
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
private int mActivePointerId = INVALID_POINTER_ID;
@ -90,6 +106,7 @@ public class TouchInteractionService extends Service {
private NavBarSwipeInteractionHandler mInteractionHandler;
private ISystemUiProxy mISystemUiProxy;
private Consumer<MotionEvent> mCurrentConsumer = mNoOpTouchConsumer;
@Override
public void onCreate() {
@ -127,25 +144,31 @@ public class TouchInteractionService extends Service {
}
private void handleMotionEvent(MotionEvent ev) {
if (ev.getActionMasked() != MotionEvent.ACTION_DOWN && mVelocityTracker == null) {
if (ev.getActionMasked() == ACTION_DOWN) {
mRunningTask = mAM.getRunningTask();
if (mRunningTask == null) {
mCurrentConsumer = mNoOpTouchConsumer;
} else if (mRunningTask.topActivity.equals(mLauncher)) {
mCurrentConsumer = getLauncherConsumer();
} else {
mCurrentConsumer = mOtherActivityTouchConsumer;
}
}
mCurrentConsumer.accept(ev);
}
private void handleTouchDownOnOtherActivity(MotionEvent ev) {
if (ev.getActionMasked() != ACTION_DOWN && mVelocityTracker == null) {
return;
}
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
case ACTION_DOWN: {
TraceHelper.beginSection("TouchInt");
mActivePointerId = ev.getPointerId(0);
mDownPos.set(ev.getX(), ev.getY());
mLastPos.set(mDownPos);
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
Display display = getSystemService(WindowManager.class).getDefaultDisplay();
display.getRealSize(mDisplaySize);
mDisplayRotation = display.getRotation();
mRunningTask = mAM.getRunningTask();
if (mRunningTask == null || mRunningTask.topActivity.equals(mLauncher)) {
// TODO: We could drive all-apps in this case. For now just ignore swipe.
break;
}
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
@ -159,7 +182,7 @@ public class TouchInteractionService extends Service {
}
break;
}
case MotionEvent.ACTION_POINTER_UP: {
case ACTION_POINTER_UP: {
int ptrIdx = ev.getActionIndex();
int ptrId = ev.getPointerId(ptrIdx);
if (ptrId == mActivePointerId) {
@ -173,7 +196,7 @@ public class TouchInteractionService extends Service {
}
break;
}
case MotionEvent.ACTION_MOVE: {
case ACTION_MOVE: {
int pointerIndex = ev.findPointerIndex(mActivePointerId);
if (pointerIndex == INVALID_POINTER_ID) {
break;
@ -192,17 +215,19 @@ public class TouchInteractionService extends Service {
}
break;
}
case MotionEvent.ACTION_CANCEL:
case ACTION_CANCEL:
// TODO: Should be different than ACTION_UP
case MotionEvent.ACTION_UP: {
case ACTION_UP: {
TraceHelper.endSection("TouchInt");
endInteraction();
mCurrentConsumer = mNoOpTouchConsumer;
break;
}
}
}
private void startTouchTracking() {
// Create the shared handler
final NavBarSwipeInteractionHandler handler =
@ -260,9 +285,12 @@ public class TouchInteractionService extends Service {
TraceHelper.beginSection("TaskSnapshot");
// TODO: We are using some hardcoded layers for now, to best approximate the activity layers
Point displaySize = new Point();
Display display = getSystemService(WindowManager.class).getDefaultDisplay();
display.getRealSize(displaySize);
try {
return mISystemUiProxy.screenshot(new Rect(), mDisplaySize.x, mDisplaySize.y, 0, 100000,
false, mDisplayRotation).toBitmap();
return mISystemUiProxy.screenshot(new Rect(), displaySize.x, displaySize.y, 0, 100000,
false, display.getRotation()).toBitmap();
} catch (RemoteException e) {
Log.e(TAG, "Error capturing snapshot", e);
return null;
@ -270,4 +298,76 @@ public class TouchInteractionService extends Service {
TraceHelper.endSection("TaskSnapshot");
}
}
private Consumer<MotionEvent> getLauncherConsumer() {
Launcher launcher = (Launcher) LauncherAppState.getInstance(this).getModel().getCallback();
if (launcher == null) {
return mNoOpTouchConsumer;
}
View target = launcher.getDragLayer();
if (!target.getWindowId().isFocused()) {
return mNoOpTouchConsumer;
}
return new LauncherTouchConsumer(target);
}
private class LauncherTouchConsumer implements Consumer<MotionEvent> {
private final View mTarget;
private final int[] mLocationOnScreen = new int[2];
private boolean mTrackingStarted = false;
LauncherTouchConsumer(View target) {
mTarget = target;
}
@Override
public void accept(MotionEvent ev) {
int action = ev.getActionMasked();
if (action == ACTION_DOWN) {
mTrackingStarted = false;
mDownPos.set(ev.getX(), ev.getY());
mTouchSlop = ViewConfiguration.get(mTarget.getContext()).getScaledTouchSlop();
} else if (!mTrackingStarted) {
switch (action) {
case ACTION_POINTER_UP:
case ACTION_POINTER_DOWN:
if (!mTrackingStarted) {
mCurrentConsumer = mNoOpTouchConsumer;
}
break;
case ACTION_MOVE: {
float displacement = ev.getY() - mDownPos.y;
if (Math.abs(displacement) >= mTouchSlop) {
mTrackingStarted = true;
mTarget.getLocationOnScreen(mLocationOnScreen);
// Send a down event only when mTouchSlop is crossed.
MotionEvent down = MotionEvent.obtain(ev);
down.setAction(ACTION_DOWN);
sendEvent(down);
down.recycle();
}
}
}
}
if (mTrackingStarted) {
sendEvent(ev);
}
if (action == ACTION_UP || action == ACTION_CANCEL) {
mCurrentConsumer = mNoOpTouchConsumer;
}
}
private void sendEvent(MotionEvent ev) {
ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
mTarget.dispatchTouchEvent(ev);
ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
}
}
}