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

Commit 34e727ec authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Fix freeform window cannot move up" into rvc-dev

parents fcf25e08 3ae6ebb9
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).