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

Commit 4f35a88b authored by Naomi Musgrave's avatar Naomi Musgrave
Browse files

Add on-device logging for edge resizing

Bug: 335795282
Test: atest WMShellUnitTests:DragResizeWindowGeometryTests
Change-Id: I2eb0a9c6f01d9e0e7f640dec9f7af16cc46c1f4e
parent 1fc94796
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ public enum ShellProtoLogGroup implements IProtoLogGroup {
    WM_SHELL_SYSUI_EVENTS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
            Consts.TAG_WM_SHELL),
    WM_SHELL_DESKTOP_MODE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
            Consts.TAG_WM_SHELL),
            Consts.TAG_WM_DESKTOP_MODE),
    WM_SHELL_FLOATING_APPS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
            Consts.TAG_WM_SHELL),
    WM_SHELL_FOLDABLE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
@@ -120,6 +120,7 @@ public enum ShellProtoLogGroup implements IProtoLogGroup {
        private static final String TAG_WM_SHELL = "WindowManagerShell";
        private static final String TAG_WM_STARTING_WINDOW = "ShellStartingWindow";
        private static final String TAG_WM_SPLIT_SCREEN = "ShellSplitScreen";
        private static final String TAG_WM_DESKTOP_MODE = "ShellDesktopMode";

        private static final boolean ENABLE_DEBUG = true;
        private static final boolean ENABLE_LOG_TO_PROTO_DEBUG = true;
+9 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERL
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;

import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT;
@@ -53,6 +54,7 @@ import android.view.ViewConfiguration;
import android.view.WindowManagerGlobal;
import android.window.InputTransferToken;

import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;

@@ -398,12 +400,17 @@ class DragResizeInputListener implements AutoCloseable {
                        float rawX = e.getRawX(0);
                        float rawY = e.getRawY(0);
                        int ctrlType = mDragResizeWindowGeometry.calculateCtrlType(isTouch, x, y);
                        ProtoLog.d(WM_SHELL_DESKTOP_MODE,
                                "%s: Handling action down, update ctrlType to %d", TAG, ctrlType);
                        mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType,
                                rawX, rawY);
                        // Increase the input sink region to cover the whole screen; this is to
                        // prevent input and focus from going to other tasks during a drag resize.
                        updateInputSinkRegionForDrag(mDragStartTaskBounds);
                        result = true;
                    } else {
                        ProtoLog.d(WM_SHELL_DESKTOP_MODE,
                                "%s: Handling action down, but ignore event", TAG);
                    }
                    break;
                }
@@ -498,6 +505,8 @@ class DragResizeInputListener implements AutoCloseable {
            // where views in the task can receive input events because we can't set touch regions
            // of input sinks to have rounded corners.
            if (mLastCursorType != cursorType || cursorType != PointerIcon.TYPE_DEFAULT) {
                ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: update pointer icon from %d to %d",
                        TAG, mLastCursorType, cursorType);
                mInputManager.setPointerIcon(PointerIcon.getSystemIcon(mContext, cursorType),
                        displayId, deviceId, pointerId, mInputChannel.getToken());
                mLastCursorType = cursorType;
+124 −36
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@ import android.graphics.Region;
import android.util.Size;
import android.view.MotionEvent;

import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.wm.shell.R;

import java.util.Objects;
@@ -41,6 +44,11 @@ import java.util.Objects;
 * Geometry for a drag resize region for a particular window.
 */
final class DragResizeWindowGeometry {
    // TODO(b/337264971) clean up when no longer needed
    @VisibleForTesting static final boolean DEBUG = true;
    // The additional width to apply to edge resize bounds just for logging when a touch is
    // close.
    @VisibleForTesting static final int EDGE_DEBUG_BUFFER = 15;
    private final int mTaskCornerRadius;
    private final Size mTaskSize;
    // The size of the handle applied to the edges of the window, for the user to drag resize.
@@ -51,10 +59,9 @@ final class DragResizeWindowGeometry {
    // The task corners to permit drag resizing with a fine input, such as stylus or cursor.
    private final @NonNull TaskCorners mFineTaskCorners;
    // The bounds for each edge drag region, which can resize the task in one direction.
    private final @NonNull Rect mTopEdgeBounds;
    private final @NonNull Rect mLeftEdgeBounds;
    private final @NonNull Rect mRightEdgeBounds;
    private final @NonNull Rect mBottomEdgeBounds;
    private final @NonNull TaskEdges mTaskEdges;
    // Extra-large edge bounds for logging to help debug when an edge resize is ignored.
    private final @Nullable TaskEdges mDebugTaskEdges;

    DragResizeWindowGeometry(int taskCornerRadius, @NonNull Size taskSize,
            int resizeHandleThickness, int fineCornerSize, int largeCornerSize) {
@@ -66,26 +73,12 @@ final class DragResizeWindowGeometry {
        mFineTaskCorners = new TaskCorners(mTaskSize, fineCornerSize);

        // Save touch areas for each edge.
        mTopEdgeBounds = new Rect(
                -mResizeHandleThickness,
                -mResizeHandleThickness,
                mTaskSize.getWidth() + mResizeHandleThickness,
                0);
        mLeftEdgeBounds = new Rect(
                -mResizeHandleThickness,
                0,
                0,
                mTaskSize.getHeight());
        mRightEdgeBounds = new Rect(
                mTaskSize.getWidth(),
                0,
                mTaskSize.getWidth() + mResizeHandleThickness,
                mTaskSize.getHeight());
        mBottomEdgeBounds = new Rect(
                -mResizeHandleThickness,
                mTaskSize.getHeight(),
                mTaskSize.getWidth() + mResizeHandleThickness,
                mTaskSize.getHeight() + mResizeHandleThickness);
        mTaskEdges = new TaskEdges(mTaskSize, mResizeHandleThickness);
        if (DEBUG) {
            mDebugTaskEdges = new TaskEdges(mTaskSize, mResizeHandleThickness + EDGE_DEBUG_BUFFER);
        } else {
            mDebugTaskEdges = null;
        }
    }

    /**
@@ -127,10 +120,13 @@ final class DragResizeWindowGeometry {
     */
    void union(@NonNull Region region) {
        // Apply the edge resize regions.
        region.union(mTopEdgeBounds);
        region.union(mLeftEdgeBounds);
        region.union(mRightEdgeBounds);
        region.union(mBottomEdgeBounds);
        if (inDebugMode()) {
            // Use the larger edge sizes if we are debugging, to be able to log if we ignored a
            // touch due to the size of the edge region.
            mDebugTaskEdges.union(region);
        } else {
            mTaskEdges.union(region);
        }

        if (enableWindowingEdgeDragResize()) {
            // Apply the corners as well for the larger corners, to ensure we capture all possible
@@ -216,6 +212,10 @@ final class DragResizeWindowGeometry {

    @DragPositioningCallback.CtrlType
    private int calculateEdgeResizeCtrlType(float x, float y) {
        if (inDebugMode() && (mDebugTaskEdges.contains((int) x, (int) y)
                    && !mTaskEdges.contains((int) x, (int) y))) {
            return CTRL_TYPE_UNDEFINED;
        }
        int ctrlType = CTRL_TYPE_UNDEFINED;
        // mTaskCornerRadius is only used in comparing with corner regions. Comparisons with
        // sides will use the bounds specified in setGeometry and not go into task bounds.
@@ -306,10 +306,9 @@ final class DragResizeWindowGeometry {
                && this.mResizeHandleThickness == other.mResizeHandleThickness
                && this.mFineTaskCorners.equals(other.mFineTaskCorners)
                && this.mLargeTaskCorners.equals(other.mLargeTaskCorners)
                && this.mTopEdgeBounds.equals(other.mTopEdgeBounds)
                && this.mLeftEdgeBounds.equals(other.mLeftEdgeBounds)
                && this.mRightEdgeBounds.equals(other.mRightEdgeBounds)
                && this.mBottomEdgeBounds.equals(other.mBottomEdgeBounds);
                && (inDebugMode()
                        ? this.mDebugTaskEdges.equals(other.mDebugTaskEdges)
                        : this.mTaskEdges.equals(other.mTaskEdges));
    }

    @Override
@@ -320,10 +319,11 @@ final class DragResizeWindowGeometry {
                mResizeHandleThickness,
                mFineTaskCorners,
                mLargeTaskCorners,
                mTopEdgeBounds,
                mLeftEdgeBounds,
                mRightEdgeBounds,
                mBottomEdgeBounds);
                (inDebugMode() ? mDebugTaskEdges : mTaskEdges));
    }

    private boolean inDebugMode() {
        return DEBUG && mDebugTaskEdges != null;
    }

    /**
@@ -431,4 +431,92 @@ final class DragResizeWindowGeometry {
                    mRightBottomCornerBounds);
        }
    }

    /**
     * Representation of the drag resize regions at the edges of the window.
     */
    private static class TaskEdges {
        private final @NonNull Rect mTopEdgeBounds;
        private final @NonNull Rect mLeftEdgeBounds;
        private final @NonNull Rect mRightEdgeBounds;
        private final @NonNull Rect mBottomEdgeBounds;
        private final @NonNull Region mRegion;

        private TaskEdges(@NonNull Size taskSize, int resizeHandleThickness) {
            // Save touch areas for each edge.
            mTopEdgeBounds = new Rect(
                    -resizeHandleThickness,
                    -resizeHandleThickness,
                    taskSize.getWidth() + resizeHandleThickness,
                    0);
            mLeftEdgeBounds = new Rect(
                    -resizeHandleThickness,
                    0,
                    0,
                    taskSize.getHeight());
            mRightEdgeBounds = new Rect(
                    taskSize.getWidth(),
                    0,
                    taskSize.getWidth() + resizeHandleThickness,
                    taskSize.getHeight());
            mBottomEdgeBounds = new Rect(
                    -resizeHandleThickness,
                    taskSize.getHeight(),
                    taskSize.getWidth() + resizeHandleThickness,
                    taskSize.getHeight() + resizeHandleThickness);

            mRegion = new Region();
            mRegion.union(mTopEdgeBounds);
            mRegion.union(mLeftEdgeBounds);
            mRegion.union(mRightEdgeBounds);
            mRegion.union(mBottomEdgeBounds);
        }

        /**
         * Returns {@code true} if the edges contain the given point.
         */
        private boolean contains(int x, int y) {
            return mRegion.contains(x, y);
        }

        /**
         * Updates the region to include all four corners.
         */
        private void union(Region region) {
            region.union(mTopEdgeBounds);
            region.union(mLeftEdgeBounds);
            region.union(mRightEdgeBounds);
            region.union(mBottomEdgeBounds);
        }

        @Override
        public String toString() {
            return "TaskEdges for the"
                    + " top " + mTopEdgeBounds
                    + " left " + mLeftEdgeBounds
                    + " right " + mRightEdgeBounds
                    + " bottom " + mBottomEdgeBounds;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) return false;
            if (this == obj) return true;
            if (!(obj instanceof TaskEdges other)) return false;

            return this.mTopEdgeBounds.equals(other.mTopEdgeBounds)
                    && this.mLeftEdgeBounds.equals(other.mLeftEdgeBounds)
                    && this.mRightEdgeBounds.equals(other.mRightEdgeBounds)
                    && this.mBottomEdgeBounds.equals(other.mBottomEdgeBounds);
        }

        @Override
        public int hashCode() {
            return Objects.hash(
                    mTopEdgeBounds,
                    mLeftEdgeBounds,
                    mRightEdgeBounds,
                    mBottomEdgeBounds);
        }
    }
}
+23 −15
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ public class DragResizeWindowGeometryTests {
    private static final Size TASK_SIZE = new Size(500, 1000);
    private static final int TASK_CORNER_RADIUS = 10;
    private static final int EDGE_RESIZE_THICKNESS = 15;
    private static final int EDGE_RESIZE_DEBUG_THICKNESS = EDGE_RESIZE_THICKNESS
            + (DragResizeWindowGeometry.DEBUG ? DragResizeWindowGeometry.EDGE_DEBUG_BUFFER : 0);
    private static final int FINE_CORNER_SIZE = EDGE_RESIZE_THICKNESS * 2 + 10;
    private static final int LARGE_CORNER_SIZE = FINE_CORNER_SIZE + 10;
    private static final DragResizeWindowGeometry GEOMETRY = new DragResizeWindowGeometry(
@@ -90,13 +92,14 @@ public class DragResizeWindowGeometryTests {
                                EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, LARGE_CORNER_SIZE),
                        new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
                                EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, LARGE_CORNER_SIZE))
                .addEqualityGroup(
                .addEqualityGroup(new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
                                EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE, LARGE_CORNER_SIZE + 5),
                        new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
                                EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE,
                                LARGE_CORNER_SIZE + 5),
                                EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE, LARGE_CORNER_SIZE + 5))
                .addEqualityGroup(new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
                                EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE + 4, LARGE_CORNER_SIZE),
                        new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE,
                                EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE,
                                LARGE_CORNER_SIZE + 5))
                                EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE + 4, LARGE_CORNER_SIZE))
                .testEquals();
    }

@@ -122,21 +125,21 @@ public class DragResizeWindowGeometryTests {
    private static void verifyHorizontalEdge(@NonNull Region region, @NonNull Point point) {
        assertThat(region.contains(point.x, point.y)).isTrue();
        // Horizontally along the edge is still contained.
        assertThat(region.contains(point.x + EDGE_RESIZE_THICKNESS, point.y)).isTrue();
        assertThat(region.contains(point.x - EDGE_RESIZE_THICKNESS, point.y)).isTrue();
        assertThat(region.contains(point.x + EDGE_RESIZE_DEBUG_THICKNESS, point.y)).isTrue();
        assertThat(region.contains(point.x - EDGE_RESIZE_DEBUG_THICKNESS, point.y)).isTrue();
        // Vertically along the edge is not contained.
        assertThat(region.contains(point.x, point.y - EDGE_RESIZE_THICKNESS)).isFalse();
        assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS)).isFalse();
        assertThat(region.contains(point.x, point.y - EDGE_RESIZE_DEBUG_THICKNESS)).isFalse();
        assertThat(region.contains(point.x, point.y + EDGE_RESIZE_DEBUG_THICKNESS)).isFalse();
    }

    private static void verifyVerticalEdge(@NonNull Region region, @NonNull Point point) {
        assertThat(region.contains(point.x, point.y)).isTrue();
        // Horizontally along the edge is not contained.
        assertThat(region.contains(point.x + EDGE_RESIZE_THICKNESS, point.y)).isFalse();
        assertThat(region.contains(point.x - EDGE_RESIZE_THICKNESS, point.y)).isFalse();
        assertThat(region.contains(point.x + EDGE_RESIZE_DEBUG_THICKNESS, point.y)).isFalse();
        assertThat(region.contains(point.x - EDGE_RESIZE_DEBUG_THICKNESS, point.y)).isFalse();
        // Vertically along the edge is contained.
        assertThat(region.contains(point.x, point.y - EDGE_RESIZE_THICKNESS)).isTrue();
        assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS)).isTrue();
        assertThat(region.contains(point.x, point.y - EDGE_RESIZE_DEBUG_THICKNESS)).isTrue();
        assertThat(region.contains(point.x, point.y + EDGE_RESIZE_DEBUG_THICKNESS)).isTrue();
    }

    /**
@@ -148,7 +151,10 @@ public class DragResizeWindowGeometryTests {
    public void testRegionUnion_edgeDragResizeEnabled_containsLargeCorners() {
        Region region = new Region();
        GEOMETRY.union(region);
        final int cornerRadius = LARGE_CORNER_SIZE / 2;
        // Make sure we're choosing a point outside of any debug region buffer.
        final int cornerRadius = DragResizeWindowGeometry.DEBUG
                ? Math.max(LARGE_CORNER_SIZE / 2, EDGE_RESIZE_DEBUG_THICKNESS)
                : LARGE_CORNER_SIZE / 2;

        new TestPoints(TASK_SIZE, cornerRadius).validateRegion(region);
    }
@@ -162,7 +168,9 @@ public class DragResizeWindowGeometryTests {
    public void testRegionUnion_edgeDragResizeDisabled_containsFineCorners() {
        Region region = new Region();
        GEOMETRY.union(region);
        final int cornerRadius = FINE_CORNER_SIZE / 2;
        final int cornerRadius = DragResizeWindowGeometry.DEBUG
                ? Math.max(LARGE_CORNER_SIZE / 2, EDGE_RESIZE_DEBUG_THICKNESS)
                : LARGE_CORNER_SIZE / 2;

        new TestPoints(TASK_SIZE, cornerRadius).validateRegion(region);
    }