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

Commit a4920a6e authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Fix freeform window cannot move up" into rvc-dev am: 34e727ec

Change-Id: I51214a577cd6dc206fdf06e2d5e21237daf8f230
parents 8fa26d5a 34e727ec
Loading
Loading
Loading
Loading
+42 −64
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;

import android.annotation.NonNull;
import android.app.IActivityTaskManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
@@ -48,7 +47,6 @@ import android.util.DisplayMetrics;
import android.util.Slog;
import android.view.BatchedInputEventReceiver;
import android.view.Choreographer;
import android.view.Display;
import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputDevice;
@@ -75,10 +73,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
    public static final int RESIZING_HINT_DURATION_MS = 0;

    private final WindowManagerService mService;
    private final IActivityTaskManager mActivityManager;
    private WindowPositionerEventReceiver mInputEventReceiver;
    private DisplayContent mDisplayContent;
    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
    private Rect mTmpRect = new Rect();
    private int mMinVisibleWidth;
    private int mMinVisibleHeight;
@@ -151,11 +147,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
                        if (!mTmpRect.equals(mWindowDragBounds)) {
                            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                                    "wm.TaskPositioner.resizeTask");
                            try {
                                mActivityManager.resizeTask(
                            mService.mAtmService.resizeTask(
                                    mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
                            } catch (RemoteException e) {
                            }
                            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                        }
                    } break;
@@ -181,14 +174,12 @@ class TaskPositioner implements IBinder.DeathRecipient {
                        endDragLocked();
                        mTask.getDimBounds(mTmpRect);
                    }
                    try {
                    if (wasResizing && !mTmpRect.equals(mWindowDragBounds)) {
                        // We were using fullscreen surface during resizing. Request
                        // resizeTask() one last time to restore surface to window size.
                            mActivityManager.resizeTask(
                        mService.mAtmService.resizeTask(
                                mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
                    }
                    } catch(RemoteException e) {}

                    // Post back to WM to handle clean-ups. We still need the input
                    // event handler for the last finishInputEvent()!
@@ -203,15 +194,10 @@ class TaskPositioner implements IBinder.DeathRecipient {
        }
    }

    /** Use {@link #create(WindowManagerService)} instead. */
    @VisibleForTesting
    TaskPositioner(WindowManagerService service, IActivityTaskManager activityManager) {
        mService = service;
        mActivityManager = activityManager;
    }

    /** Use {@link #create(WindowManagerService)} instead **/
    TaskPositioner(WindowManagerService service) {
        this(service, service.mActivityTaskManager);
        mService = service;
    }

    @VisibleForTesting
@@ -224,8 +210,6 @@ class TaskPositioner implements IBinder.DeathRecipient {
     * @param win The window which will be dragged.
     */
    void register(DisplayContent displayContent, @NonNull WindowState win) {
        final Display display = displayContent.getDisplay();

        if (DEBUG_TASK_POSITIONING) {
            Slog.d(TAG, "Registering task positioner");
        }
@@ -236,7 +220,6 @@ class TaskPositioner implements IBinder.DeathRecipient {
        }

        mDisplayContent = displayContent;
        display.getMetrics(mDisplayMetrics);
        final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
        mServerChannel = channels[0];
        mClientChannel = channels[1];
@@ -251,7 +234,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
        mDragApplicationHandle.dispatchingTimeoutNanos =
                WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;

        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, display.getDisplayId());
        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle,
                displayContent.getDisplayId());
        mDragWindowHandle.name = TAG;
        mDragWindowHandle.token = mServerChannel.getToken();
        mDragWindowHandle.layoutParamsFlags = 0;
@@ -271,13 +255,13 @@ class TaskPositioner implements IBinder.DeathRecipient {
        // The drag window cannot receive new touches.
        mDragWindowHandle.touchableRegion.setEmpty();

        // The drag window covers the entire display
        mDragWindowHandle.frameLeft = 0;
        mDragWindowHandle.frameTop = 0;
        final Point p = new Point();
        display.getRealSize(p);
        mDragWindowHandle.frameRight = p.x;
        mDragWindowHandle.frameBottom = p.y;
        // The drag window covers the entire display.
        final Rect displayBounds = mTmpRect;
        displayContent.getBounds(mTmpRect);
        mDragWindowHandle.frameLeft = displayBounds.left;
        mDragWindowHandle.frameTop = displayBounds.top;
        mDragWindowHandle.frameRight = displayBounds.right;
        mDragWindowHandle.frameBottom = displayBounds.bottom;

        // Pause rotations before a drag.
        ProtoLog.d(WM_DEBUG_ORIENTATION, "Pausing rotation during re-position");
@@ -287,9 +271,10 @@ class TaskPositioner implements IBinder.DeathRecipient {
        mDisplayContent.getInputMonitor().updateInputWindowsImmediately();
        new SurfaceControl.Transaction().syncInputWindows().apply(true);

        mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
        mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
        display.getRealSize(mMaxVisibleSize);
        final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
        mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
        mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics);
        mMaxVisibleSize.set(displayBounds.width(), displayBounds.height());

        mDragEnded = false;

@@ -341,8 +326,11 @@ class TaskPositioner implements IBinder.DeathRecipient {
        mWindow = null;
    }

    void startDrag(boolean resize, boolean preserveOrientation, float startX,
            float startY) {
    /**
     * Starts moving or resizing the task. This method should be only called from
     * {@link TaskPositioningController#startPositioningLocked} or unit tests.
     */
    void startDrag(boolean resize, boolean preserveOrientation, float startX, float startY) {
        if (DEBUG_TASK_POSITIONING) {
            Slog.d(TAG, "startDrag: win=" + mWindow + ", resize=" + resize
                    + ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", "
@@ -351,12 +339,9 @@ class TaskPositioner implements IBinder.DeathRecipient {
        // Use the bounds of the task which accounts for
        // multiple app windows. Don't use any bounds from win itself as it
        // may not be the same size as the task.
        mTask.getBounds(mTmpRect);
        startDrag(resize, preserveOrientation, startX, startY, mTmpRect);
    }
        final Rect startBounds = mTmpRect;
        mTask.getBounds(startBounds);

    protected void startDrag(boolean resize, boolean preserveOrientation,
                   float startX, float startY, Rect startBounds) {
        mCtrlType = CTRL_NONE;
        mStartDragX = startX;
        mStartDragY = startY;
@@ -389,20 +374,13 @@ class TaskPositioner implements IBinder.DeathRecipient {
        // bounds yet. This will guarantee that the app starts the backdrop renderer before
        // configuration changes which could cause an activity restart.
        if (mResizing) {
            synchronized (mService.mGlobalLock) {
            notifyMoveLocked(startX, startY);
            }

            // Perform the resize on the WMS handler thread when we don't have the WMS lock held
            // to ensure that we don't deadlock WMS and AMS. Note that WindowPositionerEventReceiver
            // callbacks are delivered on the same handler so this initial resize is always
            // guaranteed to happen before subsequent drag resizes.
            // The WindowPositionerEventReceiver callbacks are delivered on the same handler so this
            // initial resize is always guaranteed to happen before subsequent drag resizes.
            mService.mH.post(() -> {
                try {
                    mActivityManager.resizeTask(
                mService.mAtmService.resizeTask(
                        mTask.mTaskId, startBounds, RESIZE_MODE_USER_FORCED);
                } catch (RemoteException e) {
                }
            });
        }

@@ -417,7 +395,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
    }

    /** Returns true if the move operation should be ended. */
    private boolean notifyMoveLocked(float x, float y) {
    @VisibleForTesting
    boolean notifyMoveLocked(float x, float y) {
        if (DEBUG_TASK_POSITIONING) {
            Slog.d(TAG, "notifyMoveLocked: {" + x + "," + y + "}");
        }
@@ -429,12 +408,11 @@ class TaskPositioner implements IBinder.DeathRecipient {
        }

        // This is a moving or scrolling operation.
        mTask.getStack().getDimBounds(mTmpRect);
        // If a target window is covered by system bar, there is no way to move it again by touch.
        // So we exclude them from stack bounds. and then it will be shown inside stable area.
        Rect stableBounds = new Rect();
        mDisplayContent.getStableRect(stableBounds);
        mTmpRect.intersect(stableBounds);
        // Only allow to move in stable area so the target window won't be covered by system bar.
        // Though {@link Task#resolveOverrideConfiguration} should also avoid the case.
        mDisplayContent.getStableRect(mTmpRect);
        // The task may be put in a limited display area.
        mTmpRect.intersect(mTask.getRootTask().getParent().getBounds());

        int nX = (int) x;
        int nY = (int) y;
+4 −0
Original line number Diff line number Diff line
@@ -234,6 +234,10 @@ class ActivityTestsBase extends SystemServiceTestsBase {
                mTask = new TaskBuilder(mService.mStackSupervisor)
                        .setComponent(mComponent)
                        .setStack(mStack).build();
            } else if (mTask == null && mStack != null && DisplayContent.alwaysCreateStack(
                    mStack.getWindowingMode(), mStack.getActivityType())) {
                // The stack can be the task root.
                mTask = mStack;
            }

            Intent intent = new Intent();
+31 −7
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;

import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
@@ -71,18 +70,21 @@ public class TaskPositionerTests extends WindowTestsBase {
    public void setUp() {
        TaskPositioner.setFactory(null);

        final Display display = mDisplayContent.getDisplay();
        final DisplayMetrics dm = new DisplayMetrics();
        display.getMetrics(dm);
        final DisplayMetrics dm = mDisplayContent.getDisplayMetrics();

        // This should be the same calculation as the TaskPositioner uses.
        mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
        mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
        removeGlobalMinSizeRestriction();

        WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "window");
        mPositioner = new TaskPositioner(mWm, mWm.mAtmService);

        final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
        final ActivityRecord activity = new ActivityTestsBase.ActivityBuilder(stack.mAtmService)
                .setStack(stack)
                // In real case, there is no additional level for freeform mode.
                .setCreateTask(false)
                .build();
        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "window");
        mPositioner = new TaskPositioner(mWm);
        mPositioner.register(mDisplayContent, win);

        win.getRootTask().setWindowingMode(WINDOWING_MODE_FREEFORM);
@@ -109,6 +111,28 @@ public class TaskPositionerTests extends WindowTestsBase {
        assertTrue(created[0]);
    }

    /** This tests that the window can move in all directions. */
    @Test
    public void testMoveWindow() {
        final Rect displayBounds = mDisplayContent.getBounds();
        final int windowSize = Math.min(displayBounds.width(), displayBounds.height()) / 2;
        final int left = displayBounds.centerX() - windowSize / 2;
        final int top = displayBounds.centerY() - windowSize / 2;
        final Rect r = new Rect(left, top, left + windowSize, top + windowSize);
        mPositioner.mTask.setBounds(r);
        mPositioner.startDrag(false /* resizing */, false /* preserveOrientation */, left, top);

        // Move upper left.
        mPositioner.notifyMoveLocked(left - MOUSE_DELTA_X, top - MOUSE_DELTA_Y);
        r.offset(-MOUSE_DELTA_X, -MOUSE_DELTA_Y);
        assertBoundsEquals(r, mPositioner.getWindowDragBounds());

        // Move bottom right.
        mPositioner.notifyMoveLocked(left, top);
        r.offset(MOUSE_DELTA_X, MOUSE_DELTA_Y);
        assertBoundsEquals(r, mPositioner.getWindowDragBounds());
    }

    /**
     * This tests that free resizing will allow to change the orientation as well
     * as does some basic tests (e.g. dragging in Y only will keep X stable).