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

Commit ac3bc3ad authored by Jorge Gil's avatar Jorge Gil
Browse files

Add logs for DesktopModeTouchEventListener

Flag: EXEMPT adding logs
Bug: 418225224
Test: m
Change-Id: I784b8842a31babdfb3247747d89f37781abb77ce
parent 426c0248
Loading
Loading
Loading
Loading
+180 −57
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.SparseArray;
import android.view.Choreographer;
@@ -1132,9 +1133,13 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
    public class DesktopModeTouchEventListener extends GestureDetector.SimpleOnGestureListener
            implements View.OnClickListener, View.OnTouchListener, View.OnLongClickListener,
            View.OnGenericMotionListener, DragDetector.MotionEventHandler {
        private static final String TAG = "DesktopModeTouchEventListener";
        private static final long APP_HANDLE_HOLD_TO_DRAG_DURATION_MS = 100;
        private static final long APP_HEADER_HOLD_TO_DRAG_DURATION_MS = 0;

        private static final boolean DEBUG_MOTION_EVENTS = SystemProperties.getBoolean(
                "persist.wm.debug.window_decoration_motion_events_debug", false);

        private final int mTaskId;
        private final WindowContainerToken mTaskToken;
        private final DragPositioningCallback mDragPositioningCallback;
@@ -1178,19 +1183,36 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            mGestureDetector = new GestureDetector(mContext, this);
        }

        @NonNull
        private String getResourceName(@Nullable View view) {
            if (view == null) return "null";
            final int id = view.getId();
            if (id == R.id.back_button) return "back_button";
            if (id == R.id.caption_handle) return "caption_handle";
            if (id == R.id.close_window) return "close_window";
            if (id == R.id.desktop_mode_caption) return "desktop_mode_caption";
            if (id == R.id.maximize_window) return "maximize_window";
            if (id == R.id.minimize_window) return "minimize_window";
            if (id == R.id.open_menu_button) return "open_menu_button";
            return "unknown";
        }

        @Override
        public void onClick(View v) {
            final String viewName = getResourceName(v);
            logD("onClick(%s)", viewName);
            if (mIsDragging) {
                logD("onClick(%s) while dragging in progress, ignoring", viewName);
                mIsDragging = false;
                return;
            }
            final WindowDecorationWrapper decoration = mWindowDecorByTaskId.get(mTaskId);
            if (decoration == null) {
                logD("onClick(%s) but decoration is null, ignoring", viewName);
                return;
            }
            final int id = v.getId();
            if (id == R.id.close_window) {
                ProtoLog.d(WM_SHELL_WINDOW_DECORATION, "onClick close_window: taskId=%d", mTaskId);
                if (isTaskInSplitScreen(mTaskId)) {
                    mSplitScreenController.moveTaskToFullscreen(getOtherSplitTask(mTaskId).taskId,
                            SplitScreenController.EXIT_REASON_DESKTOP_MODE);
@@ -1215,16 +1237,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    }
                }
            } else if (id == R.id.back_button) {
                ProtoLog.d(WM_SHELL_WINDOW_DECORATION, "onClick back_button: taskId=%d", mTaskId);
                mTaskOperations.injectBackKey(decoration.getTaskInfo().displayId);
            } else if (id == R.id.caption_handle || id == R.id.open_menu_button) {
                if (id == R.id.caption_handle) {
                    ProtoLog.d(WM_SHELL_WINDOW_DECORATION, "onClick caption_handle: taskId=%d",
                            mTaskId);
                } else {
                    ProtoLog.d(WM_SHELL_WINDOW_DECORATION, "onClick open_menu_button: taskId=%d",
                            mTaskId);
                }
                if (id == R.id.caption_handle && !decoration.getTaskInfo().isFreeform()) {
                    // Clicking the App Handle.
                    mDesktopModeUiEventLogger.log(decoration.getTaskInfo(),
@@ -1236,8 +1250,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    openHandleMenu(mTaskId);
                }
            } else if (id == R.id.maximize_window) {
                ProtoLog.d(WM_SHELL_WINDOW_DECORATION, "onClick maximize_window: taskId=%d",
                        mTaskId);
                // TODO(b/346441962): move click detection logic into the decor's
                //  {@link AppHeaderViewHolder}. Let it encapsulate the that and have it report
                //  back to the decoration using
@@ -1258,8 +1270,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                            getInputMethod(mMotionEvent));
                }
            } else if (id == R.id.minimize_window) {
                ProtoLog.d(WM_SHELL_WINDOW_DECORATION, "onClick minimize_window: taskId=%d",
                        mTaskId);
                if (DesktopExperienceFlags
                        .ENABLE_DESKTOP_APP_HEADER_STATE_CHANGE_ANNOUNCEMENTS.isTrue()) {
                    final int nextFocusedTaskId = mDesktopTasksController
@@ -1278,9 +1288,12 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
        @Override
        public boolean onTouch(View v, MotionEvent e) {
            mMotionEvent = e;
            final String viewName = getResourceName(v);
            debugLogD("onTouch(%s) action=%s", viewName, MotionEvent.actionToString(e.getAction()));
            final int id = v.getId();
            final WindowDecorationWrapper decoration = mWindowDecorByTaskId.get(mTaskId);
            if (decoration == null) {
                debugLogD("onTouch(%s) but decoration is null, ignoring", viewName);
                return false;
            }
            final ActivityManager.RunningTaskInfo taskInfo = decoration.getTaskInfo();
@@ -1289,14 +1302,18 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            // Disable long click during events from a non-touchscreen source
            mLongClickDisabled = !touchscreenSource && e.getActionMasked() != ACTION_UP
                    && e.getActionMasked() != ACTION_CANCEL;
            debugLogD("onTouch(%s) isTouchscreen=%b longClickDisabled=%b",
                    viewName, touchscreenSource, mLongClickDisabled);

            if (id != R.id.caption_handle && id != R.id.desktop_mode_caption
                    && id != R.id.open_menu_button && id != R.id.close_window
                    && id != R.id.maximize_window && id != R.id.minimize_window) {
                debugLogD("onTouch(%s) unsupported view, ignoring", viewName);
                return false;
            }
            if (MotionEventKt.isTouchpadGesture(e)) {
                // Touchpad finger gestures are ignored.
                debugLogD("onTouch(%s) but is touchpad gesture, ignoring", viewName);
                return false;
            }

@@ -1341,6 +1358,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            if (mIsCustomHeaderGesture || mIsResizeGesture) {
                // The event will be handled by the custom window below or pilfered by resize
                // handler.
                debugLogD("onTouch(%s) but mIsCustomHeaderGesture=%b mIsResizeGesture=%b, ignoring",
                        viewName, mIsCustomHeaderGesture, mIsResizeGesture);
                return false;
            }
            if (mInputManager != null
@@ -1365,21 +1384,30 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,

        @Override
        public boolean onLongClick(View v) {
            final String viewName = getResourceName(v);
            logD("onLongClick(%s)", viewName);
            final int id = v.getId();
            if (id == R.id.maximize_window && !mLongClickDisabled) {
            if (id != R.id.maximize_window) {
                logD("onLongClick(%s) but view is unsupported, ignoring", viewName);
                return false;
            }
            if (mLongClickDisabled) {
                logD("onLongClick(%s) but long click is disabled, ignoring", viewName);
                return false;
            }
            final WindowDecorationWrapper decoration = mWindowDecorByTaskId.get(mTaskId);
            if (decoration == null) {
                logD("onLongClick(%s) but decoration is null, ignoring", viewName);
                return false;
            }
            moveTaskToFront(decoration.getTaskInfo());
            if (decoration.getMaximizeMenuController() != null
                    && !decoration.getMaximizeMenuController().isMaximizeMenuActive()) {
                logD("onLongClick(%s) creating maximize menu", viewName);
                decoration.getMaximizeMenuController().createMaximizeMenu();
            }
            return true;
        }
            return false;
        }

        /**
         * TODO(b/346441962): move this hover detection logic into the decor's
@@ -1415,15 +1443,20 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,

        private void moveTaskToFront(RunningTaskInfo taskInfo) {
            if (!mFocusTransitionObserver.hasGlobalFocus(taskInfo)) {
                ProtoLog.d(WM_SHELL_DESKTOP_MODE,
                        "%s: task#%d in display#%d does not have global focus, moving to front "
                logD("moveTaskToFront display=%d "
                                + "globallyFocusedTaskId=%d globallyFocusedDisplayId=%d",
                        TAG, taskInfo.taskId, taskInfo.displayId,
                        taskInfo.displayId,
                        mFocusTransitionObserver.getGloballyFocusedTaskId(),
                        mFocusTransitionObserver.getGloballyFocusedDisplayId());
                mDesktopModeUiEventLogger.log(taskInfo,
                        DesktopUiEventEnum.DESKTOP_WINDOW_HEADER_TAP_TO_REFOCUS);
                mDesktopTasksController.moveTaskToFront(taskInfo);
            } else {
                debugLogD("moveTaskToFront already had global focus, skipping "
                        + " display=%d globallyFocusedTaskId=%d globallyFocusedDisplayId=%d",
                        taskInfo.displayId,
                        mFocusTransitionObserver.getGloballyFocusedTaskId(),
                        mFocusTransitionObserver.getGloballyFocusedDisplayId());
            }
        }

@@ -1433,8 +1466,12 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
         */
        @Override
        public boolean handleMotionEvent(@Nullable View v, MotionEvent e) {
            final String viewName = getResourceName(v);
            debugLogD("handleMotionEvent(%s) action=%s",
                    viewName, MotionEvent.actionToString(e.getAction()));
            final WindowDecorationWrapper decoration = mWindowDecorByTaskId.get(mTaskId);
            if (decoration == null) {
                debugLogD("handleMotionEvent(%s) but decoration is null, ignoring", viewName);
                return false;
            }
            final RunningTaskInfo taskInfo = decoration.getTaskInfo();
@@ -1449,10 +1486,17 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
        private boolean handleNonFreeformMotionEvent(WindowDecorationWrapper decoration,
                View v, MotionEvent e) {
            final int id = v.getId();
            if (id == R.id.caption_handle) {
            final String viewName = getResourceName(v);
            debugLogD("handleNonFreeformMotionEvent(%s)", viewName);
            if (id != R.id.caption_handle) {
                debugLogD("handleNonFreeformMotionEvent(%s) unsupported view, ignoring",
                        viewName);
                return false;
            }
            handleCaptionThroughStatusBar(e, decoration,
                    /* interruptDragCallback= */
                    () -> {
                        logD("handleNonFreeformMotionEvent(%s) drag interrupted", viewName);
                        mDragInterrupted = true;
                        setIsDragging(decoration, /* isDragging= */ false);
                    });
@@ -1460,6 +1504,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            updateDragStatus(decoration, e);
            final boolean upOrCancel = e.getActionMasked() == ACTION_UP
                    || e.getActionMasked() == ACTION_CANCEL;
            debugLogD("handleNonFreeformMotionEvent(%s) wasDragging=%b isDragging=%b upOrCancel=%b",
                    wasDragging, mIsDragging, upOrCancel);
            if (wasDragging && upOrCancel) {
                // When finishing a drag the event will be consumed, which means the pressed
                // state of the App Handle must be manually reset to scale its drawable back to
@@ -1470,8 +1516,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            // Only prevent onClick from receiving this event if it's a drag.
            return wasDragging;
        }
            return false;
        }

        private void setIsDragging(@Nullable WindowDecorationWrapper decor, boolean isDragging) {
            mIsDragging = isDragging;
@@ -1481,9 +1525,12 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,

        private boolean handleFreeformMotionEvent(WindowDecorationWrapper decoration,
                RunningTaskInfo taskInfo, View v, MotionEvent e) {
            final String viewName = getResourceName(v);
            debugLogD("handleFreeformMotionEvent(%s)", viewName);
            updateTouchStatus(e);
            final int id = v.getId();
            if (mGestureDetector.onTouchEvent(e)) {
                debugLogD("handleFreeformMotionEvent(%s) handled by gesture detector", viewName);
                return true;
            }
            final boolean touchingButton = (id == R.id.close_window || id == R.id.maximize_window
@@ -1502,6 +1549,20 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                        updateDragStatus(decoration, e);
                        mOnDragStartInitialBounds.set(initialBounds);
                        mCurrentBounds.set(initialBounds);
                        debugLogD("handleFreeformMotionEvent(%s) action=%s "
                                        + "dispatched |onDragPositioningStart| dragAllowed=%b "
                                        + "isDragging=%b mOnDragStartInitialBounds=%s "
                                        + "mCurrentBounds=%s touchingButton=%b",
                                viewName, MotionEvent.actionToString(e.getAction()), dragAllowed,
                                mIsDragging, mOnDragStartInitialBounds, mCurrentBounds,
                                touchingButton);
                    } else {
                        debugLogD("handleFreeformMotionEvent(%s) action=%s dragAllowed=%b "
                                        + "isDragging=%b mOnDragStartInitialBounds=%s "
                                        + "mCurrentBounds=%s touchingButton=%b",
                                viewName, MotionEvent.actionToString(e.getAction()), dragAllowed,
                                mIsDragging, mOnDragStartInitialBounds, mCurrentBounds,
                                touchingButton);
                    }
                    // Do not consume input event if a button is touched, otherwise it would
                    // prevent the button's ripple effect from showing.
@@ -1509,9 +1570,19 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                }
                case ACTION_MOVE: {
                    // If a decor's resize drag zone is active, don't also try to reposition it.
                    if (decoration.isHandlingDragResize()) break;
                    if (decoration.isHandlingDragResize()) {
                        debugLogD("handleFreeformMotionEvent(%s) action=%s "
                                        + "handling drag resize, ignore",
                                viewName, MotionEvent.actionToString(e.getAction()));
                        break;
                    }
                    // Dragging the header isn't allowed, so skip the positioning work.
                    if (!dragAllowed) break;
                    if (!dragAllowed) {
                        debugLogD("handleFreeformMotionEvent(%s) action=%s "
                                        + "drag is not allowed, ignore",
                                viewName, MotionEvent.actionToString(e.getAction()));
                        break;
                    }

                    if (e.findPointerIndex(mDragPointerId) == -1) {
                        mDragPointerId = e.getPointerId(0);
@@ -1532,11 +1603,24 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                            mCurrentBounds.set(mDragPositioningCallback.onDragPositioningMove(
                                    e.getDisplayId(),
                                    e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)));
                            debugLogD("handleFreeformMotionEvent(%s) action=%s "
                                            + "inDesktopModeDisplay=%b dispatched "
                                            + "|onDragPositioningMove| mCurrentBounds=%s",
                                    viewName, MotionEvent.actionToString(e.getAction()),
                                    inDesktopModeDisplay, mCurrentBounds);
                        } else {
                            debugLogD("handleFreeformMotionEvent(%s) action=%s "
                                            + "not a desktop mode display, ignore",
                                    viewName, MotionEvent.actionToString(e.getAction()));
                        }
                    } else {
                        mCurrentBounds.set(mDragPositioningCallback.onDragPositioningMove(
                                e.getDisplayId(),
                                e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)));
                        debugLogD("handleFreeformMotionEvent(%s) action=%s dispatched "
                                        + "|onDragPositioningMove| mCurrentBounds=%s",
                                viewName, MotionEvent.actionToString(e.getAction()),
                                mCurrentBounds);
                    }

                    mDesktopTasksController.onDragPositioningMove(taskInfo,
@@ -1545,6 +1629,11 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                            e.getRawX(dragPointerIdx),
                            e.getRawY(dragPointerIdx),
                            mCurrentBounds);
                    debugLogD("handleFreeformMotionEvent(%s) action=%s updated controller "
                                    + "mIsDragging=%b mCurrentBounds=%s "
                                    + "mOnDragStartInitialBounds=%s",
                            viewName, MotionEvent.actionToString(e.getAction()), mIsDragging,
                            mCurrentBounds, mOnDragStartInitialBounds);
                    //  Flip mIsDragging only if the bounds actually changed.
                    if (mIsDragging || !mCurrentBounds.equals(mOnDragStartInitialBounds)) {
                        updateDragStatus(decoration, e);
@@ -1555,6 +1644,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                case MotionEvent.ACTION_CANCEL: {
                    final boolean wasDragging = mIsDragging;
                    if (!wasDragging) {
                        debugLogD("handleFreeformMotionEvent(%s) action=%s "
                                        + "was not dragging, ignore",
                                viewName, MotionEvent.actionToString(e.getAction()));
                        return false;
                    }
                    mDesktopModeUiEventLogger.log(taskInfo,
@@ -1566,6 +1658,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    final Rect newTaskBounds = mDragPositioningCallback.onDragPositioningEnd(
                            e.getDisplayId(),
                            e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
                    debugLogD("handleFreeformMotionEvent(%s) action=%s dispatched "
                                    + "|onDragPositioningEnd| newTaskBounds=%s",
                            viewName, MotionEvent.actionToString(e.getAction()), newTaskBounds);

                    if (DesktopExperienceFlags
                            .ENABLE_BLOCK_NON_DESKTOP_DISPLAY_WINDOW_DRAG_BUGFIX.isTrue()) {
@@ -1576,19 +1671,32 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                        if (!mShellDesktopState
                                .isEligibleWindowDropTarget(e.getDisplayId())) {
                            newTaskBounds.set(mOnDragStartInitialBounds);
                            debugLogD("handleFreeformMotionEvent(%s) action=%s "
                                            + "pointer in non-desktop display(%d), "
                                            + "reverted to initial bounds=%s",
                                    viewName, MotionEvent.actionToString(e.getAction()),
                                    e.getDisplayId(), newTaskBounds);
                        }
                    }

                    // Tasks bounds haven't actually been updated (only its leash), so pass to
                    // DesktopTasksController to allow secondary transformations (i.e. snap resizing
                    // or transforming to fullscreen) before setting new task bounds.
                    final Rect validDragArea = decoration.calculateValidDragArea();
                    final boolean needDragIndicatorCleanup =
                            mDesktopTasksController.onDragPositioningEnd(
                                    taskInfo, decoration.getTaskSurface(), e.getDisplayId(),
                                    new PointF(e.getRawX(dragPointerIdx),
                                            e.getRawY(dragPointerIdx)),
                                    newTaskBounds, decoration.calculateValidDragArea(),
                                    new PointF(
                                            e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)),
                                    newTaskBounds, validDragArea,
                                    new Rect(mOnDragStartInitialBounds), e);
                    debugLogD("handleFreeformMotionEvent(%s) action=%s updated controller "
                                    + "newTaskBounds%s validDragArea=%s "
                                    + "mOnDragStartInitialBounds=%s touchingButton=%b "
                                    + "needDragIndicatorCleanup=%b",
                            viewName, MotionEvent.actionToString(e.getAction()), newTaskBounds,
                            validDragArea, mOnDragStartInitialBounds, touchingButton,
                            needDragIndicatorCleanup);
                    if (DesktopExperienceFlags.ENABLE_WINDOW_DROP_SMOOTH_TRANSITION.isTrue()) {
                        if (needDragIndicatorCleanup) {
                            mMultiDisplayDragMoveIndicatorController.onDragEnd(taskInfo.taskId,
@@ -1600,13 +1708,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                        // We need the input event to not be consumed here to end the ripple
                        // effect on the touched button. We will reset drag state in the ensuing
                        // onClick call that results.
                        debugLogD("handleFreeformMotionEvent(%s) action=%s "
                                        + "touching button, ignore",
                                viewName, MotionEvent.actionToString(e.getAction()));
                        return false;
                    } else {
                    }
                    updateDragStatus(decoration, e);
                    return true;
                }
            }
            }
            return true;
        }

@@ -1636,6 +1746,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    break;
                }
            }
            debugLogD("updateDragStatus action=%s updated mIsDragging=%b mDragInterrupted=%b",
                    MotionEvent.actionToString(e.getAction()), mIsDragging, mDragInterrupted);
        }

        private void updateTouchStatus(MotionEvent e) {
@@ -1678,6 +1790,17 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    getInputMethod(mMotionEvent));
            return true;
        }

        private void debugLogD(@NonNull String msg, @NonNull Object... args) {
            if (DEBUG_MOTION_EVENTS) {
                logD(msg, args);
            }
        }

        private void logD(@NonNull String msg, @NonNull Object... args) {
            ProtoLog.d(WM_SHELL_WINDOW_DECORATION, "%s: (taskId=%d) %s",
                    TAG, mTaskId, String.format(msg, args));
        }
    }

    // InputEventReceiver to listen for touch input outside of caption bounds