Merge "Fix freeform window cannot move up" into rvc-dev am: 34e727ec7f am: 47441ec27d

Change-Id: I59619be9532a4979c9248ee148d9185304d3d647
This commit is contained in:
Automerger Merge Worker
2020-03-09 05:46:07 +00:00
3 changed files with 77 additions and 71 deletions

View File

@@ -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;

View File

@@ -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();

View File

@@ -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).