summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/policy/TaskResizingAlgorithm.java179
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java153
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java2
3 files changed, 192 insertions, 142 deletions
diff --git a/core/java/com/android/internal/policy/TaskResizingAlgorithm.java b/core/java/com/android/internal/policy/TaskResizingAlgorithm.java
new file mode 100644
index 000000000000..1fce098fb93e
--- /dev/null
+++ b/core/java/com/android/internal/policy/TaskResizingAlgorithm.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.policy;
+
+import android.annotation.IntDef;
+import android.graphics.Point;
+import android.graphics.Rect;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Given a move coordinate (x, y), the original taks bounds and relevant details, calculate the new
+ * bounds.
+ *
+ * @hide
+ */
+public class TaskResizingAlgorithm {
+
+ @IntDef(flag = true,
+ value = {
+ CTRL_NONE,
+ CTRL_LEFT,
+ CTRL_RIGHT,
+ CTRL_TOP,
+ CTRL_BOTTOM
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CtrlType {}
+
+ public static final int CTRL_NONE = 0x0;
+ public static final int CTRL_LEFT = 0x1;
+ public static final int CTRL_RIGHT = 0x2;
+ public static final int CTRL_TOP = 0x4;
+ public static final int CTRL_BOTTOM = 0x8;
+
+ // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait).
+ // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever
+ // aspect he desires.
+ @VisibleForTesting
+ public static final float MIN_ASPECT = 1.2f;
+
+ /**
+ * Given a (x, y) point and its original starting down point and its original bounds, calculate
+ * and return a new resized bound.
+ * @param x the new moved X point.
+ * @param y the new moved Y point.
+ * @param startDragX the original starting X point.
+ * @param startDragY the original starting Y point.
+ * @param originalBounds the original bound before resize.
+ * @param ctrlType The type of resize operation.
+ * @param minVisibleWidth The minimal width required for the new size.
+ * @param minVisibleHeight The minimal height required for the new size.
+ * @param maxVisibleSize The maximum size allowed.
+ * @param preserveOrientation
+ * @param startOrientationWasLandscape
+ * @return
+ */
+ public static Rect resizeDrag(float x, float y, float startDragX, float startDragY,
+ Rect originalBounds, int ctrlType, int minVisibleWidth, int minVisibleHeight,
+ Point maxVisibleSize, boolean preserveOrientation,
+ boolean startOrientationWasLandscape) {
+ // This is a resizing operation.
+ // We need to keep various constraints:
+ // 1. mMinVisible[Width/Height] <= [width/height] <= mMaxVisibleSize.[x/y]
+ // 2. The orientation is kept - if required.
+ final int deltaX = Math.round(x - startDragX);
+ final int deltaY = Math.round(y - startDragY);
+ int left = originalBounds.left;
+ int top = originalBounds.top;
+ int right = originalBounds.right;
+ int bottom = originalBounds.bottom;
+
+ // Calculate the resulting width and height of the drag operation.
+ int width = right - left;
+ int height = bottom - top;
+ if ((ctrlType & CTRL_LEFT) != 0) {
+ width = Math.max(minVisibleWidth, width - deltaX);
+ } else if ((ctrlType & CTRL_RIGHT) != 0) {
+ width = Math.max(minVisibleWidth, width + deltaX);
+ }
+ if ((ctrlType & CTRL_TOP) != 0) {
+ height = Math.max(minVisibleHeight, height - deltaY);
+ } else if ((ctrlType & CTRL_BOTTOM) != 0) {
+ height = Math.max(minVisibleHeight, height + deltaY);
+ }
+
+ // If we have to preserve the orientation - check that we are doing so.
+ final float aspect = (float) width / (float) height;
+ if (preserveOrientation && ((startOrientationWasLandscape && aspect < MIN_ASPECT)
+ || (!startOrientationWasLandscape && aspect > (1.0 / MIN_ASPECT)))) {
+ // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major
+ // drag axis. What ever is producing the bigger rectangle will be chosen.
+ int width1;
+ int width2;
+ int height1;
+ int height2;
+ if (startOrientationWasLandscape) {
+ // Assuming that the width is our target we calculate the height.
+ width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, width));
+ height1 = Math.min(height, Math.round((float) width1 / MIN_ASPECT));
+ if (height1 < minVisibleHeight) {
+ // If the resulting height is too small we adjust to the minimal size.
+ height1 = minVisibleHeight;
+ width1 = Math.max(minVisibleWidth,
+ Math.min(maxVisibleSize.x, Math.round((float) height1 * MIN_ASPECT)));
+ }
+ // Assuming that the height is our target we calculate the width.
+ height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, height));
+ width2 = Math.max(width, Math.round((float) height2 * MIN_ASPECT));
+ if (width2 < minVisibleWidth) {
+ // If the resulting width is too small we adjust to the minimal size.
+ width2 = minVisibleWidth;
+ height2 = Math.max(minVisibleHeight,
+ Math.min(maxVisibleSize.y, Math.round((float) width2 / MIN_ASPECT)));
+ }
+ } else {
+ // Assuming that the width is our target we calculate the height.
+ width1 = Math.max(minVisibleWidth, Math.min(maxVisibleSize.x, width));
+ height1 = Math.max(height, Math.round((float) width1 * MIN_ASPECT));
+ if (height1 < minVisibleHeight) {
+ // If the resulting height is too small we adjust to the minimal size.
+ height1 = minVisibleHeight;
+ width1 = Math.max(minVisibleWidth,
+ Math.min(maxVisibleSize.x, Math.round((float) height1 / MIN_ASPECT)));
+ }
+ // Assuming that the height is our target we calculate the width.
+ height2 = Math.max(minVisibleHeight, Math.min(maxVisibleSize.y, height));
+ width2 = Math.min(width, Math.round((float) height2 / MIN_ASPECT));
+ if (width2 < minVisibleWidth) {
+ // If the resulting width is too small we adjust to the minimal size.
+ width2 = minVisibleWidth;
+ height2 = Math.max(minVisibleHeight,
+ Math.min(maxVisibleSize.y, Math.round((float) width2 * MIN_ASPECT)));
+ }
+ }
+
+ // Use the bigger of the two rectangles if the major change was positive, otherwise
+ // do the opposite.
+ final boolean grows = width > (right - left) || height > (bottom - top);
+ if (grows == (width1 * height1 > width2 * height2)) {
+ width = width1;
+ height = height1;
+ } else {
+ width = width2;
+ height = height2;
+ }
+ }
+
+ // Generate the final bounds by keeping the opposite drag edge constant.
+ if ((ctrlType & CTRL_LEFT) != 0) {
+ left = right - width;
+ } else { // Note: The right might have changed - if we pulled at the right or not.
+ right = left + width;
+ }
+ if ((ctrlType & CTRL_TOP) != 0) {
+ top = bottom - height;
+ } else { // Note: The height might have changed - if we pulled at the bottom or not.
+ bottom = top + height;
+ }
+ return new Rect(left, top, right, bottom);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 8bbb0d7da4b6..b5892b9b4dc6 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -20,6 +20,11 @@ import static android.app.ActivityTaskManager.RESIZE_MODE_USER;
import static android.app.ActivityTaskManager.RESIZE_MODE_USER_FORCED;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_BOTTOM;
+import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT;
+import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE;
+import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_RIGHT;
+import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_TOP;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
@@ -29,7 +34,6 @@ import static com.android.server.wm.WindowManagerService.dipToPixel;
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.IntDef;
import android.annotation.NonNull;
import android.app.IActivityTaskManager;
import android.graphics.Point;
@@ -55,11 +59,10 @@ import android.view.SurfaceControl;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.TaskResizingAlgorithm;
+import com.android.internal.policy.TaskResizingAlgorithm.CtrlType;
import com.android.server.protolog.common.ProtoLog;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
class TaskPositioner implements IBinder.DeathRecipient {
private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false;
private static final String TAG_LOCAL = "TaskPositioner";
@@ -67,33 +70,10 @@ class TaskPositioner implements IBinder.DeathRecipient {
private static Factory sFactory;
- @IntDef(flag = true,
- value = {
- CTRL_NONE,
- CTRL_LEFT,
- CTRL_RIGHT,
- CTRL_TOP,
- CTRL_BOTTOM
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface CtrlType {}
-
- private static final int CTRL_NONE = 0x0;
- private static final int CTRL_LEFT = 0x1;
- private static final int CTRL_RIGHT = 0x2;
- private static final int CTRL_TOP = 0x4;
- private static final int CTRL_BOTTOM = 0x8;
-
public static final float RESIZING_HINT_ALPHA = 0.5f;
public static final int RESIZING_HINT_DURATION_MS = 0;
- // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait).
- // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever
- // aspect he desires.
- @VisibleForTesting
- static final float MIN_ASPECT = 1.2f;
-
private final WindowManagerService mService;
private final IActivityTaskManager mActivityManager;
private WindowPositionerEventReceiver mInputEventReceiver;
@@ -477,122 +457,13 @@ class TaskPositioner implements IBinder.DeathRecipient {
*/
@VisibleForTesting
void resizeDrag(float x, float y) {
- // This is a resizing operation.
- // We need to keep various constraints:
- // 1. mMinVisible[Width/Height] <= [width/height] <= mMaxVisibleSize.[x/y]
- // 2. The orientation is kept - if required.
- final int deltaX = Math.round(x - mStartDragX);
- final int deltaY = Math.round(y - mStartDragY);
- int left = mWindowOriginalBounds.left;
- int top = mWindowOriginalBounds.top;
- int right = mWindowOriginalBounds.right;
- int bottom = mWindowOriginalBounds.bottom;
-
- // Calculate the resulting width and height of the drag operation.
- int width = right - left;
- int height = bottom - top;
- if ((mCtrlType & CTRL_LEFT) != 0) {
- width = Math.max(mMinVisibleWidth, width - deltaX);
- } else if ((mCtrlType & CTRL_RIGHT) != 0) {
- width = Math.max(mMinVisibleWidth, width + deltaX);
- }
- if ((mCtrlType & CTRL_TOP) != 0) {
- height = Math.max(mMinVisibleHeight, height - deltaY);
- } else if ((mCtrlType & CTRL_BOTTOM) != 0) {
- height = Math.max(mMinVisibleHeight, height + deltaY);
- }
-
- // If we have to preserve the orientation - check that we are doing so.
- final float aspect = (float) width / (float) height;
- if (mPreserveOrientation && ((mStartOrientationWasLandscape && aspect < MIN_ASPECT)
- || (!mStartOrientationWasLandscape && aspect > (1.0 / MIN_ASPECT)))) {
- // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major
- // drag axis. What ever is producing the bigger rectangle will be chosen.
- int width1;
- int width2;
- int height1;
- int height2;
- if (mStartOrientationWasLandscape) {
- // Assuming that the width is our target we calculate the height.
- width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width));
- height1 = Math.min(height, Math.round((float)width1 / MIN_ASPECT));
- if (height1 < mMinVisibleHeight) {
- // If the resulting height is too small we adjust to the minimal size.
- height1 = mMinVisibleHeight;
- width1 = Math.max(mMinVisibleWidth,
- Math.min(mMaxVisibleSize.x, Math.round((float)height1 * MIN_ASPECT)));
- }
- // Assuming that the height is our target we calculate the width.
- height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height));
- width2 = Math.max(width, Math.round((float)height2 * MIN_ASPECT));
- if (width2 < mMinVisibleWidth) {
- // If the resulting width is too small we adjust to the minimal size.
- width2 = mMinVisibleWidth;
- height2 = Math.max(mMinVisibleHeight,
- Math.min(mMaxVisibleSize.y, Math.round((float)width2 / MIN_ASPECT)));
- }
- } else {
- // Assuming that the width is our target we calculate the height.
- width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width));
- height1 = Math.max(height, Math.round((float)width1 * MIN_ASPECT));
- if (height1 < mMinVisibleHeight) {
- // If the resulting height is too small we adjust to the minimal size.
- height1 = mMinVisibleHeight;
- width1 = Math.max(mMinVisibleWidth,
- Math.min(mMaxVisibleSize.x, Math.round((float)height1 / MIN_ASPECT)));
- }
- // Assuming that the height is our target we calculate the width.
- height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height));
- width2 = Math.min(width, Math.round((float)height2 / MIN_ASPECT));
- if (width2 < mMinVisibleWidth) {
- // If the resulting width is too small we adjust to the minimal size.
- width2 = mMinVisibleWidth;
- height2 = Math.max(mMinVisibleHeight,
- Math.min(mMaxVisibleSize.y, Math.round((float)width2 * MIN_ASPECT)));
- }
- }
-
- // Use the bigger of the two rectangles if the major change was positive, otherwise
- // do the opposite.
- final boolean grows = width > (right - left) || height > (bottom - top);
- if (grows == (width1 * height1 > width2 * height2)) {
- width = width1;
- height = height1;
- } else {
- width = width2;
- height = height2;
- }
- }
-
- // Update mWindowDragBounds to the new drag size.
- updateDraggedBounds(left, top, right, bottom, width, height);
+ updateDraggedBounds(TaskResizingAlgorithm.resizeDrag(x, y, mStartDragX, mStartDragY,
+ mWindowOriginalBounds, mCtrlType, mMinVisibleWidth, mMinVisibleHeight,
+ mMaxVisibleSize, mPreserveOrientation, mStartOrientationWasLandscape));
}
- /**
- * Given the old coordinates and the new width and height, update the mWindowDragBounds.
- *
- * @param left The original left bound before the user started dragging.
- * @param top The original top bound before the user started dragging.
- * @param right The original right bound before the user started dragging.
- * @param bottom The original bottom bound before the user started dragging.
- * @param newWidth The new dragged width.
- * @param newHeight The new dragged height.
- */
- void updateDraggedBounds(int left, int top, int right, int bottom, int newWidth,
- int newHeight) {
- // Generate the final bounds by keeping the opposite drag edge constant.
- if ((mCtrlType & CTRL_LEFT) != 0) {
- left = right - newWidth;
- } else { // Note: The right might have changed - if we pulled at the right or not.
- right = left + newWidth;
- }
- if ((mCtrlType & CTRL_TOP) != 0) {
- top = bottom - newHeight;
- } else { // Note: The height might have changed - if we pulled at the bottom or not.
- bottom = top + newHeight;
- }
-
- mWindowDragBounds.set(left, top, right, bottom);
+ private void updateDraggedBounds(Rect newBounds) {
+ mWindowDragBounds.set(newBounds);
checkBoundsForOrientationViolations(mWindowDragBounds);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index 7aaf3fbccb5e..52b465ff4634 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -20,7 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
+import static com.android.internal.policy.TaskResizingAlgorithm.MIN_ASPECT;
import static com.android.server.wm.WindowManagerService.dipToPixel;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;