Merge "Fix freeform window cannot move up" into rvc-dev am: 34e727ec7f
Change-Id: Icee1f258c817a68155ec41f50d56936ed7f84ad8
This commit is contained in:
@@ -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 static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.app.IActivityTaskManager;
|
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
@@ -48,7 +47,6 @@ import android.util.DisplayMetrics;
|
|||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.BatchedInputEventReceiver;
|
import android.view.BatchedInputEventReceiver;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
import android.view.Display;
|
|
||||||
import android.view.InputApplicationHandle;
|
import android.view.InputApplicationHandle;
|
||||||
import android.view.InputChannel;
|
import android.view.InputChannel;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
@@ -75,10 +73,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
public static final int RESIZING_HINT_DURATION_MS = 0;
|
public static final int RESIZING_HINT_DURATION_MS = 0;
|
||||||
|
|
||||||
private final WindowManagerService mService;
|
private final WindowManagerService mService;
|
||||||
private final IActivityTaskManager mActivityManager;
|
|
||||||
private WindowPositionerEventReceiver mInputEventReceiver;
|
private WindowPositionerEventReceiver mInputEventReceiver;
|
||||||
private DisplayContent mDisplayContent;
|
private DisplayContent mDisplayContent;
|
||||||
private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
|
|
||||||
private Rect mTmpRect = new Rect();
|
private Rect mTmpRect = new Rect();
|
||||||
private int mMinVisibleWidth;
|
private int mMinVisibleWidth;
|
||||||
private int mMinVisibleHeight;
|
private int mMinVisibleHeight;
|
||||||
@@ -151,11 +147,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
if (!mTmpRect.equals(mWindowDragBounds)) {
|
if (!mTmpRect.equals(mWindowDragBounds)) {
|
||||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
|
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
|
||||||
"wm.TaskPositioner.resizeTask");
|
"wm.TaskPositioner.resizeTask");
|
||||||
try {
|
mService.mAtmService.resizeTask(
|
||||||
mActivityManager.resizeTask(
|
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
|
||||||
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
}
|
|
||||||
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
|
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -181,14 +174,12 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
endDragLocked();
|
endDragLocked();
|
||||||
mTask.getDimBounds(mTmpRect);
|
mTask.getDimBounds(mTmpRect);
|
||||||
}
|
}
|
||||||
try {
|
if (wasResizing && !mTmpRect.equals(mWindowDragBounds)) {
|
||||||
if (wasResizing && !mTmpRect.equals(mWindowDragBounds)) {
|
// We were using fullscreen surface during resizing. Request
|
||||||
// We were using fullscreen surface during resizing. Request
|
// resizeTask() one last time to restore surface to window size.
|
||||||
// resizeTask() one last time to restore surface to window size.
|
mService.mAtmService.resizeTask(
|
||||||
mActivityManager.resizeTask(
|
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
|
||||||
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
|
}
|
||||||
}
|
|
||||||
} catch(RemoteException e) {}
|
|
||||||
|
|
||||||
// Post back to WM to handle clean-ups. We still need the input
|
// Post back to WM to handle clean-ups. We still need the input
|
||||||
// event handler for the last finishInputEvent()!
|
// event handler for the last finishInputEvent()!
|
||||||
@@ -203,15 +194,10 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Use {@link #create(WindowManagerService)} instead. */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
TaskPositioner(WindowManagerService service, IActivityTaskManager activityManager) {
|
|
||||||
mService = service;
|
|
||||||
mActivityManager = activityManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Use {@link #create(WindowManagerService)} instead **/
|
|
||||||
TaskPositioner(WindowManagerService service) {
|
TaskPositioner(WindowManagerService service) {
|
||||||
this(service, service.mActivityTaskManager);
|
mService = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -224,8 +210,6 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
* @param win The window which will be dragged.
|
* @param win The window which will be dragged.
|
||||||
*/
|
*/
|
||||||
void register(DisplayContent displayContent, @NonNull WindowState win) {
|
void register(DisplayContent displayContent, @NonNull WindowState win) {
|
||||||
final Display display = displayContent.getDisplay();
|
|
||||||
|
|
||||||
if (DEBUG_TASK_POSITIONING) {
|
if (DEBUG_TASK_POSITIONING) {
|
||||||
Slog.d(TAG, "Registering task positioner");
|
Slog.d(TAG, "Registering task positioner");
|
||||||
}
|
}
|
||||||
@@ -236,7 +220,6 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mDisplayContent = displayContent;
|
mDisplayContent = displayContent;
|
||||||
display.getMetrics(mDisplayMetrics);
|
|
||||||
final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
|
final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
|
||||||
mServerChannel = channels[0];
|
mServerChannel = channels[0];
|
||||||
mClientChannel = channels[1];
|
mClientChannel = channels[1];
|
||||||
@@ -251,7 +234,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
mDragApplicationHandle.dispatchingTimeoutNanos =
|
mDragApplicationHandle.dispatchingTimeoutNanos =
|
||||||
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
|
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
|
||||||
|
|
||||||
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, display.getDisplayId());
|
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle,
|
||||||
|
displayContent.getDisplayId());
|
||||||
mDragWindowHandle.name = TAG;
|
mDragWindowHandle.name = TAG;
|
||||||
mDragWindowHandle.token = mServerChannel.getToken();
|
mDragWindowHandle.token = mServerChannel.getToken();
|
||||||
mDragWindowHandle.layoutParamsFlags = 0;
|
mDragWindowHandle.layoutParamsFlags = 0;
|
||||||
@@ -271,13 +255,13 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
// The drag window cannot receive new touches.
|
// The drag window cannot receive new touches.
|
||||||
mDragWindowHandle.touchableRegion.setEmpty();
|
mDragWindowHandle.touchableRegion.setEmpty();
|
||||||
|
|
||||||
// The drag window covers the entire display
|
// The drag window covers the entire display.
|
||||||
mDragWindowHandle.frameLeft = 0;
|
final Rect displayBounds = mTmpRect;
|
||||||
mDragWindowHandle.frameTop = 0;
|
displayContent.getBounds(mTmpRect);
|
||||||
final Point p = new Point();
|
mDragWindowHandle.frameLeft = displayBounds.left;
|
||||||
display.getRealSize(p);
|
mDragWindowHandle.frameTop = displayBounds.top;
|
||||||
mDragWindowHandle.frameRight = p.x;
|
mDragWindowHandle.frameRight = displayBounds.right;
|
||||||
mDragWindowHandle.frameBottom = p.y;
|
mDragWindowHandle.frameBottom = displayBounds.bottom;
|
||||||
|
|
||||||
// Pause rotations before a drag.
|
// Pause rotations before a drag.
|
||||||
ProtoLog.d(WM_DEBUG_ORIENTATION, "Pausing rotation during re-position");
|
ProtoLog.d(WM_DEBUG_ORIENTATION, "Pausing rotation during re-position");
|
||||||
@@ -287,9 +271,10 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
mDisplayContent.getInputMonitor().updateInputWindowsImmediately();
|
mDisplayContent.getInputMonitor().updateInputWindowsImmediately();
|
||||||
new SurfaceControl.Transaction().syncInputWindows().apply(true);
|
new SurfaceControl.Transaction().syncInputWindows().apply(true);
|
||||||
|
|
||||||
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
|
final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
|
||||||
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
|
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
|
||||||
display.getRealSize(mMaxVisibleSize);
|
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics);
|
||||||
|
mMaxVisibleSize.set(displayBounds.width(), displayBounds.height());
|
||||||
|
|
||||||
mDragEnded = false;
|
mDragEnded = false;
|
||||||
|
|
||||||
@@ -341,8 +326,11 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
mWindow = null;
|
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) {
|
if (DEBUG_TASK_POSITIONING) {
|
||||||
Slog.d(TAG, "startDrag: win=" + mWindow + ", resize=" + resize
|
Slog.d(TAG, "startDrag: win=" + mWindow + ", resize=" + resize
|
||||||
+ ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", "
|
+ ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", "
|
||||||
@@ -351,12 +339,9 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
// Use the bounds of the task which accounts for
|
// Use the bounds of the task which accounts for
|
||||||
// multiple app windows. Don't use any bounds from win itself as it
|
// multiple app windows. Don't use any bounds from win itself as it
|
||||||
// may not be the same size as the task.
|
// may not be the same size as the task.
|
||||||
mTask.getBounds(mTmpRect);
|
final Rect startBounds = mTmpRect;
|
||||||
startDrag(resize, preserveOrientation, startX, startY, mTmpRect);
|
mTask.getBounds(startBounds);
|
||||||
}
|
|
||||||
|
|
||||||
protected void startDrag(boolean resize, boolean preserveOrientation,
|
|
||||||
float startX, float startY, Rect startBounds) {
|
|
||||||
mCtrlType = CTRL_NONE;
|
mCtrlType = CTRL_NONE;
|
||||||
mStartDragX = startX;
|
mStartDragX = startX;
|
||||||
mStartDragY = startY;
|
mStartDragY = startY;
|
||||||
@@ -389,20 +374,13 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
// bounds yet. This will guarantee that the app starts the backdrop renderer before
|
// bounds yet. This will guarantee that the app starts the backdrop renderer before
|
||||||
// configuration changes which could cause an activity restart.
|
// configuration changes which could cause an activity restart.
|
||||||
if (mResizing) {
|
if (mResizing) {
|
||||||
synchronized (mService.mGlobalLock) {
|
notifyMoveLocked(startX, startY);
|
||||||
notifyMoveLocked(startX, startY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the resize on the WMS handler thread when we don't have the WMS lock held
|
// The WindowPositionerEventReceiver callbacks are delivered on the same handler so this
|
||||||
// to ensure that we don't deadlock WMS and AMS. Note that WindowPositionerEventReceiver
|
// initial resize is always guaranteed to happen before subsequent drag resizes.
|
||||||
// callbacks are delivered on the same handler so this initial resize is always
|
|
||||||
// guaranteed to happen before subsequent drag resizes.
|
|
||||||
mService.mH.post(() -> {
|
mService.mH.post(() -> {
|
||||||
try {
|
mService.mAtmService.resizeTask(
|
||||||
mActivityManager.resizeTask(
|
mTask.mTaskId, startBounds, RESIZE_MODE_USER_FORCED);
|
||||||
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. */
|
/** 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) {
|
if (DEBUG_TASK_POSITIONING) {
|
||||||
Slog.d(TAG, "notifyMoveLocked: {" + x + "," + y + "}");
|
Slog.d(TAG, "notifyMoveLocked: {" + x + "," + y + "}");
|
||||||
}
|
}
|
||||||
@@ -429,12 +408,11 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is a moving or scrolling operation.
|
// This is a moving or scrolling operation.
|
||||||
mTask.getStack().getDimBounds(mTmpRect);
|
// Only allow to move in stable area so the target window won't be covered by system bar.
|
||||||
// If a target window is covered by system bar, there is no way to move it again by touch.
|
// Though {@link Task#resolveOverrideConfiguration} should also avoid the case.
|
||||||
// So we exclude them from stack bounds. and then it will be shown inside stable area.
|
mDisplayContent.getStableRect(mTmpRect);
|
||||||
Rect stableBounds = new Rect();
|
// The task may be put in a limited display area.
|
||||||
mDisplayContent.getStableRect(stableBounds);
|
mTmpRect.intersect(mTask.getRootTask().getParent().getBounds());
|
||||||
mTmpRect.intersect(stableBounds);
|
|
||||||
|
|
||||||
int nX = (int) x;
|
int nX = (int) x;
|
||||||
int nY = (int) y;
|
int nY = (int) y;
|
||||||
|
|||||||
@@ -234,6 +234,10 @@ class ActivityTestsBase extends SystemServiceTestsBase {
|
|||||||
mTask = new TaskBuilder(mService.mStackSupervisor)
|
mTask = new TaskBuilder(mService.mStackSupervisor)
|
||||||
.setComponent(mComponent)
|
.setComponent(mComponent)
|
||||||
.setStack(mStack).build();
|
.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();
|
Intent intent = new Intent();
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import android.graphics.Rect;
|
|||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Display;
|
|
||||||
|
|
||||||
import androidx.test.filters.FlakyTest;
|
import androidx.test.filters.FlakyTest;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -71,18 +70,21 @@ public class TaskPositionerTests extends WindowTestsBase {
|
|||||||
public void setUp() {
|
public void setUp() {
|
||||||
TaskPositioner.setFactory(null);
|
TaskPositioner.setFactory(null);
|
||||||
|
|
||||||
final Display display = mDisplayContent.getDisplay();
|
final DisplayMetrics dm = mDisplayContent.getDisplayMetrics();
|
||||||
final DisplayMetrics dm = new DisplayMetrics();
|
|
||||||
display.getMetrics(dm);
|
|
||||||
|
|
||||||
// This should be the same calculation as the TaskPositioner uses.
|
// This should be the same calculation as the TaskPositioner uses.
|
||||||
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
|
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
|
||||||
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
|
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
|
||||||
removeGlobalMinSizeRestriction();
|
removeGlobalMinSizeRestriction();
|
||||||
|
|
||||||
WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "window");
|
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
|
||||||
mPositioner = new TaskPositioner(mWm, mWm.mAtmService);
|
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);
|
mPositioner.register(mDisplayContent, win);
|
||||||
|
|
||||||
win.getRootTask().setWindowingMode(WINDOWING_MODE_FREEFORM);
|
win.getRootTask().setWindowingMode(WINDOWING_MODE_FREEFORM);
|
||||||
@@ -109,6 +111,28 @@ public class TaskPositionerTests extends WindowTestsBase {
|
|||||||
assertTrue(created[0]);
|
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
|
* 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).
|
* as does some basic tests (e.g. dragging in Y only will keep X stable).
|
||||||
|
|||||||
Reference in New Issue
Block a user