From f38f5b0d963ea92eb8ec216c46576708c2d2f905 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Thu, 23 Dec 2021 00:21:26 -0800 Subject: [PATCH] Introduce SimpleBatchedInputEventReceiver Create a BatchedInputEventReceiver that makes it easier to return whether an event was handled. Bug: 162194035 Test: build Change-Id: I8d597189b786db6bb61f1d838a530cc573a42238 --- .../view/BatchedInputEventReceiver.java | 36 +++- .../com/android/server/wm/TaskPositioner.java | 183 ++++++++---------- 2 files changed, 120 insertions(+), 99 deletions(-) diff --git a/core/java/android/view/BatchedInputEventReceiver.java b/core/java/android/view/BatchedInputEventReceiver.java index 1ed12f74ba2c2..e679f2998ca1a 100644 --- a/core/java/android/view/BatchedInputEventReceiver.java +++ b/core/java/android/view/BatchedInputEventReceiver.java @@ -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); + } + } + } } diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index 364246e1134ee..348cfb62582eb 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -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);