Introduce SimpleBatchedInputEventReceiver

Create a BatchedInputEventReceiver that makes it easier to return
whether an event was handled.

Bug: 162194035
Test: build
Change-Id: I8d597189b786db6bb61f1d838a530cc573a42238
This commit is contained in:
Prabir Pradhan
2021-12-23 00:21:26 -08:00
parent 2888d6598f
commit f38f5b0d96
2 changed files with 120 additions and 99 deletions

View File

@@ -78,7 +78,7 @@ public class BatchedInputEventReceiver extends InputEventReceiver {
}
}
void doConsumeBatchedInput(long frameTimeNanos) {
protected void doConsumeBatchedInput(long frameTimeNanos) {
if (mBatchedInputScheduled) {
mBatchedInputScheduled = false;
if (consumeBatchedInputEvents(frameTimeNanos) && frameTimeNanos != -1) {
@@ -114,4 +114,38 @@ public class BatchedInputEventReceiver extends InputEventReceiver {
}
}
private final BatchedInputRunnable mBatchedInputRunnable = new BatchedInputRunnable();
/**
* A {@link BatchedInputEventReceiver} that reports events to an {@link InputEventListener}.
* @hide
*/
public static class SimpleBatchedInputEventReceiver extends BatchedInputEventReceiver {
/** @hide */
public interface InputEventListener {
/**
* Process the input event.
* @return handled
*/
boolean onInputEvent(InputEvent event);
}
protected InputEventListener mListener;
public SimpleBatchedInputEventReceiver(InputChannel inputChannel, Looper looper,
Choreographer choreographer, InputEventListener listener) {
super(inputChannel, looper, choreographer);
mListener = listener;
}
@Override
public void onInputEvent(InputEvent event) {
boolean handled = false;
try {
handled = mListener.onInputEvent(event);
} finally {
finishInputEvent(event, handled);
}
}
}
}

View File

@@ -40,18 +40,17 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.Trace;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.view.BatchedInputEventReceiver;
import android.view.Choreographer;
import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
import android.view.MotionEvent;
import android.view.WindowManager;
@@ -73,7 +72,7 @@ class TaskPositioner implements IBinder.DeathRecipient {
public static final int RESIZING_HINT_DURATION_MS = 0;
private final WindowManagerService mService;
private WindowPositionerEventReceiver mInputEventReceiver;
private InputEventReceiver mInputEventReceiver;
private DisplayContent mDisplayContent;
private Rect mTmpRect = new Rect();
private int mMinVisibleWidth;
@@ -100,105 +99,93 @@ class TaskPositioner implements IBinder.DeathRecipient {
InputApplicationHandle mDragApplicationHandle;
InputWindowHandle mDragWindowHandle;
private final class WindowPositionerEventReceiver extends BatchedInputEventReceiver {
public WindowPositionerEventReceiver(
InputChannel inputChannel, Looper looper, Choreographer choreographer) {
super(inputChannel, looper, choreographer);
}
@Override
public void onInputEvent(InputEvent event) {
boolean handled = false;
try {
// All returns need to be in the try block to make sure the finishInputEvent is
// called correctly.
if (!(event instanceof MotionEvent)
|| (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
return;
}
final MotionEvent motionEvent = (MotionEvent) event;
if (mDragEnded) {
// The drag has ended but the clean-up message has not been processed by
// window manager. Drop events that occur after this until window manager
// has a chance to clean-up the input handle.
handled = true;
return;
}
final float newX = motionEvent.getRawX();
final float newY = motionEvent.getRawY();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_DOWN @ {" + newX + ", " + newY + "}");
}
} break;
case MotionEvent.ACTION_MOVE: {
if (DEBUG_TASK_POSITIONING){
Slog.w(TAG, "ACTION_MOVE @ {" + newX + ", " + newY + "}");
}
synchronized (mService.mGlobalLock) {
mDragEnded = notifyMoveLocked(newX, newY);
mTask.getDimBounds(mTmpRect);
}
if (!mTmpRect.equals(mWindowDragBounds)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
"wm.TaskPositioner.resizeTask");
mService.mAtmService.resizeTask(
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
} break;
case MotionEvent.ACTION_UP: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_UP @ {" + newX + ", " + newY + "}");
}
mDragEnded = true;
} break;
case MotionEvent.ACTION_CANCEL: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_CANCEL @ {" + newX + ", " + newY + "}");
}
mDragEnded = true;
} break;
}
if (mDragEnded) {
final boolean wasResizing = mResizing;
synchronized (mService.mGlobalLock) {
endDragLocked();
mTask.getDimBounds(mTmpRect);
}
if (wasResizing && !mTmpRect.equals(mWindowDragBounds)) {
// We were using fullscreen surface during resizing. Request
// resizeTask() one last time to restore surface to window size.
mService.mAtmService.resizeTask(
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
}
// Post back to WM to handle clean-ups. We still need the input
// event handler for the last finishInputEvent()!
mService.mTaskPositioningController.finishTaskPositioning();
}
handled = true;
} catch (Exception e) {
Slog.e(TAG, "Exception caught by drag handleMotion", e);
} finally {
finishInputEvent(event, handled);
}
}
}
/** Use {@link #create(WindowManagerService)} instead. */
@VisibleForTesting
TaskPositioner(WindowManagerService service) {
mService = service;
}
private boolean onInputEvent(InputEvent event) {
// All returns need to be in the try block to make sure the finishInputEvent is
// called correctly.
if (!(event instanceof MotionEvent)
|| (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
return false;
}
final MotionEvent motionEvent = (MotionEvent) event;
if (mDragEnded) {
// The drag has ended but the clean-up message has not been processed by
// window manager. Drop events that occur after this until window manager
// has a chance to clean-up the input handle.
return true;
}
final float newX = motionEvent.getRawX();
final float newY = motionEvent.getRawY();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_DOWN @ {" + newX + ", " + newY + "}");
}
}
break;
case MotionEvent.ACTION_MOVE: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_MOVE @ {" + newX + ", " + newY + "}");
}
synchronized (mService.mGlobalLock) {
mDragEnded = notifyMoveLocked(newX, newY);
mTask.getDimBounds(mTmpRect);
}
if (!mTmpRect.equals(mWindowDragBounds)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
"wm.TaskPositioner.resizeTask");
mService.mAtmService.resizeTask(
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
}
break;
case MotionEvent.ACTION_UP: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_UP @ {" + newX + ", " + newY + "}");
}
mDragEnded = true;
}
break;
case MotionEvent.ACTION_CANCEL: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_CANCEL @ {" + newX + ", " + newY + "}");
}
mDragEnded = true;
}
break;
}
if (mDragEnded) {
final boolean wasResizing = mResizing;
synchronized (mService.mGlobalLock) {
endDragLocked();
mTask.getDimBounds(mTmpRect);
}
if (wasResizing && !mTmpRect.equals(mWindowDragBounds)) {
// We were using fullscreen surface during resizing. Request
// resizeTask() one last time to restore surface to window size.
mService.mAtmService.resizeTask(
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
}
// Post back to WM to handle clean-ups. We still need the input
// event handler for the last finishInputEvent()!
mService.mTaskPositioningController.finishTaskPositioning();
}
return true;
}
@VisibleForTesting
Rect getWindowDragBounds() {
return mWindowDragBounds;
@@ -221,9 +208,9 @@ class TaskPositioner implements IBinder.DeathRecipient {
mDisplayContent = displayContent;
mClientChannel = mService.mInputManager.createInputChannel(TAG);
mInputEventReceiver = new WindowPositionerEventReceiver(
mInputEventReceiver = new BatchedInputEventReceiver.SimpleBatchedInputEventReceiver(
mClientChannel, mService.mAnimationHandler.getLooper(),
mService.mAnimator.getChoreographer());
mService.mAnimator.getChoreographer(), this::onInputEvent);
mDragApplicationHandle = new InputApplicationHandle(new Binder(), TAG,
DEFAULT_DISPATCHING_TIMEOUT_MILLIS);