summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl5
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java2
-rw-r--r--core/java/android/view/IWindow.aidl2
-rw-r--r--core/java/android/view/IWindowManager.aidl6
-rw-r--r--core/java/android/view/ViewRootImpl.java27
-rw-r--r--core/java/android/view/WindowCallbacks.java18
-rw-r--r--core/java/android/view/WindowlessWindowManager.java4
-rw-r--r--core/java/com/android/internal/policy/DecorView.java13
-rw-r--r--core/java/com/android/internal/view/BaseIWindow.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java13
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java12
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java6
-rw-r--r--services/core/java/com/android/server/wm/DockedTaskDividerController.java63
-rw-r--r--services/core/java/com/android/server/wm/DragResizeMode.java47
-rw-r--r--services/core/java/com/android/server/wm/Task.java37
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java14
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java44
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestIWindow.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java5
24 files changed, 297 insertions, 39 deletions
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index f20503cef705..91add2783c0d 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -249,6 +249,11 @@ interface IActivityTaskManager {
/** Returns an interface enabling the management of window organizers. */
IWindowOrganizerController getWindowOrganizerController();
+ /**
+ * Sets whether we are currently in an interactive split screen resize operation where we
+ * are changing the docked stack size.
+ */
+ void setSplitScreenResizing(boolean resizing);
boolean supportsLocalVoiceInteraction();
// Get device configuration
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 9d95d0b705ef..84a233ffd2ad 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -394,7 +394,7 @@ public abstract class WallpaperService extends Service {
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, InsetsState insetsState,
boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
- int syncSeqId, boolean dragResizing) {
+ int syncSeqId, int resizeMode) {
Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
reportDraw ? 1 : 0,
mergedConfiguration);
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index d554514349c3..8e16f24b154f 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -57,7 +57,7 @@ oneway interface IWindow {
void resized(in ClientWindowFrames frames, boolean reportDraw,
in MergedConfiguration newMergedConfiguration, in InsetsState insetsState,
boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
- int syncSeqId, boolean dragResizing);
+ int syncSeqId, int resizeMode);
/**
* Called when this window retrieved control over a specified set of insets sources.
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0aba80db5378..6d9f99f76958 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -457,6 +457,12 @@ interface IWindowManager
int getDockedStackSide();
/**
+ * Sets the region the user can touch the divider. This region will be excluded from the region
+ * which is used to cause a focus switch when dispatching touch.
+ */
+ void setDockedTaskDividerTouchRegion(in Rect touchableRegion);
+
+ /**
* Registers a listener that will be called when the pinned task state changes.
*/
void registerPinnedTaskListener(int displayId, IPinnedTaskListener listener);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index eaa6820c6864..33b58d762412 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -51,6 +51,8 @@ import static android.view.ViewRootImplProto.WIDTH;
import static android.view.ViewRootImplProto.WINDOW_ATTRIBUTES;
import static android.view.ViewRootImplProto.WIN_FRAME;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
+import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
+import static android.view.WindowCallbacks.RESIZE_MODE_INVALID;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -513,6 +515,7 @@ public final class ViewRootImpl implements ViewParent,
private boolean mPendingDragResizing;
private boolean mDragResizing;
private boolean mInvalidateRootRequested;
+ private int mResizeMode = RESIZE_MODE_INVALID;
private int mCanvasOffsetX;
private int mCanvasOffsetY;
private boolean mActivityRelaunched;
@@ -1790,7 +1793,7 @@ public final class ViewRootImpl implements ViewParent,
CompatibilityInfo.applyOverrideScaleIfNeeded(mergedConfiguration);
final boolean forceNextWindowRelayout = args.argi1 != 0;
final int displayId = args.argi3;
- final boolean dragResizing = args.argi5 != 0;
+ final int resizeMode = args.argi5;
final Rect frame = frames.frame;
final Rect displayFrame = frames.displayFrame;
@@ -1806,14 +1809,16 @@ public final class ViewRootImpl implements ViewParent,
final boolean attachedFrameChanged = LOCAL_LAYOUT
&& !Objects.equals(mTmpFrames.attachedFrame, attachedFrame);
final boolean displayChanged = mDisplay.getDisplayId() != displayId;
+ final boolean resizeModeChanged = mResizeMode != resizeMode;
final boolean compatScaleChanged = mTmpFrames.compatScale != compatScale;
if (msg == MSG_RESIZED && !frameChanged && !configChanged && !attachedFrameChanged
- && !displayChanged && !forceNextWindowRelayout
+ && !displayChanged && !resizeModeChanged && !forceNextWindowRelayout
&& !compatScaleChanged) {
return;
}
- mPendingDragResizing = dragResizing;
+ mPendingDragResizing = resizeMode != RESIZE_MODE_INVALID;
+ mResizeMode = resizeMode;
mTmpFrames.compatScale = compatScale;
mInvCompatScale = 1f / compatScale;
@@ -3010,7 +3015,7 @@ public final class ViewRootImpl implements ViewParent,
frame.width() < desiredWindowWidth && frame.width() != mWidth)
|| (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT &&
frame.height() < desiredWindowHeight && frame.height() != mHeight));
- windowShouldResize |= mDragResizing && mPendingDragResizing;
+ windowShouldResize |= mDragResizing && mResizeMode == RESIZE_MODE_FREEFORM;
// If the activity was just relaunched, it might have unfrozen the task bounds (while
// relaunching), so we need to force a call into window manager to pick up the latest
@@ -3257,7 +3262,7 @@ public final class ViewRootImpl implements ViewParent,
&& mWinFrame.height() == mPendingBackDropFrame.height();
// TODO: Need cutout?
startDragResizing(mPendingBackDropFrame, !backdropSizeMatchesFrame,
- mAttachInfo.mContentInsets, mAttachInfo.mStableInsets);
+ mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mResizeMode);
} else {
// We shouldn't come here, but if we come we should end the resize.
endDragResizing();
@@ -8825,7 +8830,7 @@ public final class ViewRootImpl implements ViewParent,
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void dispatchResized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, InsetsState insetsState, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId, int syncSeqId, boolean dragResizing) {
+ boolean alwaysConsumeSystemBars, int displayId, int syncSeqId, int resizeMode) {
Message msg = mHandler.obtainMessage(reportDraw ? MSG_RESIZED_REPORT : MSG_RESIZED);
SomeArgs args = SomeArgs.obtain();
final boolean sameProcessCall = (Binder.getCallingPid() == android.os.Process.myPid());
@@ -8847,7 +8852,7 @@ public final class ViewRootImpl implements ViewParent,
args.argi2 = alwaysConsumeSystemBars ? 1 : 0;
args.argi3 = displayId;
args.argi4 = syncSeqId;
- args.argi5 = dragResizing ? 1 : 0;
+ args.argi5 = resizeMode;
msg.obj = args;
mHandler.sendMessage(msg);
@@ -10239,11 +10244,11 @@ public final class ViewRootImpl implements ViewParent,
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, InsetsState insetsState,
boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, int syncSeqId,
- boolean dragResizing) {
+ int resizeMode) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, insetsState,
- forceLayout, alwaysConsumeSystemBars, displayId, syncSeqId, dragResizing);
+ forceLayout, alwaysConsumeSystemBars, displayId, syncSeqId, resizeMode);
}
}
@@ -10448,13 +10453,13 @@ public final class ViewRootImpl implements ViewParent,
* Start a drag resizing which will inform all listeners that a window resize is taking place.
*/
private void startDragResizing(Rect initialBounds, boolean fullscreen, Rect systemInsets,
- Rect stableInsets) {
+ Rect stableInsets, int resizeMode) {
if (!mDragResizing) {
mDragResizing = true;
if (mUseMTRenderer) {
for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
mWindowCallbacks.get(i).onWindowDragResizeStart(
- initialBounds, fullscreen, systemInsets, stableInsets);
+ initialBounds, fullscreen, systemInsets, stableInsets, resizeMode);
}
}
mFullRedrawNeeded = true;
diff --git a/core/java/android/view/WindowCallbacks.java b/core/java/android/view/WindowCallbacks.java
index 94b2d93455d3..a7f0ef0a0324 100644
--- a/core/java/android/view/WindowCallbacks.java
+++ b/core/java/android/view/WindowCallbacks.java
@@ -28,6 +28,22 @@ import android.graphics.Rect;
*/
public interface WindowCallbacks {
+ int RESIZE_MODE_INVALID = -1;
+
+ /**
+ * The window is being resized by dragging one of the window corners,
+ * in this case the surface would be fullscreen-sized. The client should
+ * render to the actual frame location (instead of (0,curScrollY)).
+ */
+ int RESIZE_MODE_FREEFORM = 0;
+
+ /**
+ * The window is being resized by dragging on the docked divider. The client should render
+ * at (0, 0) and extend its background to the background frame passed into
+ * {@link IWindow#resized}.
+ */
+ int RESIZE_MODE_DOCKED_DIVIDER = 1;
+
/**
* Called by the system when the window got changed by the user, before the layouter got called.
* It also gets called when the insets changed, or when the window switched between a fullscreen
@@ -53,7 +69,7 @@ public interface WindowCallbacks {
* @param stableInsets The stable insets for the window.
*/
void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen, Rect systemInsets,
- Rect stableInsets);
+ Rect stableInsets, int resizeMode);
/**
* Called when a drag resize ends.
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 2d6c1d913e90..69340aa39daf 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -16,6 +16,8 @@
package android.view;
+import static android.view.WindowCallbacks.RESIZE_MODE_INVALID;
+
import android.annotation.Nullable;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
@@ -548,7 +550,7 @@ public class WindowlessWindowManager implements IWindowSession {
mTmpConfig.setConfiguration(mConfiguration, mConfiguration);
s.mClient.resized(mTmpFrames, false /* reportDraw */, mTmpConfig, state,
false /* forceLayout */, false /* alwaysConsumeSystemBars */, s.mDisplayId,
- Integer.MAX_VALUE, false /* dragResizing */);
+ Integer.MAX_VALUE, RESIZE_MODE_INVALID);
} catch (RemoteException e) {
// Too bad
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index b5b27f5289c9..145aeafb46a1 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -274,6 +274,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
private boolean mApplyFloatingVerticalInsets = false;
private boolean mApplyFloatingHorizontalInsets = false;
+ private int mResizeMode = RESIZE_MODE_INVALID;
private final int mResizeShadowSize;
private final Paint mVerticalResizeShadowPaint = new Paint();
private final Paint mHorizontalResizeShadowPaint = new Paint();
@@ -807,7 +808,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
updateElevation();
mAllowUpdateElevation = true;
- if (changed && mDrawLegacyNavigationBarBackground) {
+ if (changed
+ && (mResizeMode == RESIZE_MODE_DOCKED_DIVIDER
+ || mDrawLegacyNavigationBarBackground)) {
getViewRootImpl().requestInvalidateRootRenderNode();
}
}
@@ -2389,7 +2392,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
@Override
public void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen, Rect systemInsets,
- Rect stableInsets) {
+ Rect stableInsets, int resizeMode) {
if (mWindow.isDestroyed()) {
// If the owner's window is gone, we should not be able to come here anymore.
releaseThreadedRenderer();
@@ -2415,6 +2418,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
updateColorViews(null /* insets */, false);
}
+ mResizeMode = resizeMode;
getViewRootImpl().requestInvalidateRootRenderNode();
}
@@ -2422,6 +2426,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
public void onWindowDragResizeEnd() {
releaseThreadedRenderer();
updateColorViews(null /* insets */, false);
+ mResizeMode = RESIZE_MODE_INVALID;
getViewRootImpl().requestInvalidateRootRenderNode();
}
@@ -2466,7 +2471,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
private void drawResizingShadowIfNeeded(RecordingCanvas canvas) {
- if (mWindow.mIsFloating || mWindow.isTranslucent() || mWindow.isShowingWallpaper()) {
+ if (mResizeMode != RESIZE_MODE_DOCKED_DIVIDER || mWindow.mIsFloating
+ || mWindow.isTranslucent()
+ || mWindow.isShowingWallpaper()) {
return;
}
canvas.save();
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 4a5ed7e8970d..2ac43099c741 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -53,7 +53,7 @@ public class BaseIWindow extends IWindow.Stub {
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, InsetsState insetsState, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId, int seqId, boolean dragResizing) {
+ boolean alwaysConsumeSystemBars, int displayId, int seqId, int resizeMode) {
if (reportDraw) {
try {
mSession.finishDrawing(this, null /* postDrawTransaction */, seqId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 94aeb2beb1e0..af13bf54f691 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -346,7 +346,7 @@ public class SystemWindows {
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration newMergedConfiguration, InsetsState insetsState,
boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, int syncSeqId,
- boolean dragResizing) {}
+ int resizeMode) {}
@Override
public void insetsControlChanged(InsetsState insetsState,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index 65da757b1396..9d6711f42efe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -239,7 +239,7 @@ public class TaskSnapshotWindow {
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, InsetsState insetsState,
boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, int seqId,
- boolean dragResizing) {
+ int resizeMode) {
final TaskSnapshotWindow snapshot = mOuter.get();
if (snapshot == null) {
return;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 866fef76f3ca..eb04687d7d0c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3616,6 +3616,19 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
+ public void setSplitScreenResizing(boolean resizing) {
+ enforceTaskPermission("setSplitScreenResizing()");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ mTaskSupervisor.setSplitScreenResizing(resizing);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public IWindowOrganizerController getWindowOrganizerController() {
return mWindowOrganizerController;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 23c2ec71336f..33c90a00234b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -207,6 +207,9 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
// Used to indicate that a task is removed it should also be removed from recents.
static final boolean REMOVE_FROM_RECENTS = true;
+ /** True if the docked root task is currently being resized. */
+ private boolean mDockedRootTaskResizing;
+
// Activity actions an app cannot start if it uses a permission which is not granted.
private static final ArrayMap<String, String> ACTION_TO_RUNTIME_PERMISSION =
new ArrayMap<>();
@@ -1523,6 +1526,15 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
return mLaunchParamsController;
}
+ void setSplitScreenResizing(boolean resizing) {
+ if (resizing == mDockedRootTaskResizing) {
+ return;
+ }
+
+ mDockedRootTaskResizing = resizing;
+ mWindowManager.setDockedRootTaskResizing(resizing);
+ }
+
private void removePinnedRootTaskInSurfaceTransaction(Task rootTask) {
/**
* Workaround: Force-stop all the activities in the root pinned task before we reparent them
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 169e7703b1ee..c6dc24f32837 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -525,6 +525,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
/** Remove this display when animation on it has completed. */
private boolean mDeferredRemoval;
+ final DockedTaskDividerController mDividerControllerLocked;
final PinnedTaskController mPinnedTaskController;
final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
@@ -1162,6 +1163,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mDisplayPolicy.systemReady();
}
mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius();
+ mDividerControllerLocked = new DockedTaskDividerController(this);
mPinnedTaskController = new PinnedTaskController(mWmService, this);
final Transaction pendingTransaction = getPendingTransaction();
@@ -2592,6 +2594,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
}
+ DockedTaskDividerController getDockedDividerController() {
+ return mDividerControllerLocked;
+ }
+
PinnedTaskController getPinnedTaskController() {
return mPinnedTaskController;
}
diff --git a/services/core/java/com/android/server/wm/DockedTaskDividerController.java b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
new file mode 100644
index 000000000000..925a6d858a3d
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 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.server.wm;
+
+import android.graphics.Rect;
+
+/**
+ * Keeps information about the docked task divider.
+ */
+public class DockedTaskDividerController {
+
+ private final DisplayContent mDisplayContent;
+ private boolean mResizing;
+
+ private final Rect mTouchRegion = new Rect();
+
+ DockedTaskDividerController(DisplayContent displayContent) {
+ mDisplayContent = displayContent;
+ }
+
+ boolean isResizing() {
+ return mResizing;
+ }
+
+ void setResizing(boolean resizing) {
+ if (mResizing != resizing) {
+ mResizing = resizing;
+ resetDragResizingChangeReported();
+ }
+ }
+
+ void setTouchRegion(Rect touchRegion) {
+ mTouchRegion.set(touchRegion);
+ // We need to report touchable region changes to accessibility.
+ if (mDisplayContent.mWmService.mAccessibilityController.hasCallbacks()) {
+ mDisplayContent.mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(
+ mDisplayContent.getDisplayId());
+ }
+ }
+
+ void getTouchRegion(Rect outRegion) {
+ outRegion.set(mTouchRegion);
+ }
+
+ private void resetDragResizingChangeReported() {
+ mDisplayContent.forAllWindows(WindowState::resetDragResizingChangeReported,
+ true /* traverseTopToBottom */);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DragResizeMode.java b/services/core/java/com/android/server/wm/DragResizeMode.java
new file mode 100644
index 000000000000..684cf06e08b8
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DragResizeMode.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 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.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
+/**
+ * Describes the mode in which a window is drag resizing.
+ */
+class DragResizeMode {
+
+ /**
+ * Freeform mode: Client surface is fullscreen, and client is responsible to draw window at
+ * the correct position.
+ */
+ static final int DRAG_RESIZE_MODE_FREEFORM = 0;
+
+ /**
+ * Mode for resizing the docked (and adjacent) root task: Client surface is fullscreen, but
+ * window is drawn at (0, 0), window manager is responsible for positioning the surface when
+ * dragging.
+ */
+ static final int DRAG_RESIZE_MODE_DOCKED_DIVIDER = 1;
+
+ static boolean isModeAllowedForRootTask(Task rootTask, int mode) {
+ switch (mode) {
+ case DRAG_RESIZE_MODE_FREEFORM:
+ return rootTask.getWindowingMode() == WINDOWING_MODE_FREEFORM;
+ default:
+ return false;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7291e27840a9..07e3b836bd1d 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -469,6 +469,7 @@ class Task extends TaskFragment {
// Whether the task is currently being drag-resized
private boolean mDragResizing;
+ private int mDragResizeMode;
// This represents the last resolved activity values for this task
// NOTE: This value needs to be persisted with each task
@@ -2809,6 +2810,11 @@ class Task extends TaskFragment {
}
final Task rootTask = getRootTask();
+ final DisplayContent displayContent = rootTask.getDisplayContent();
+ // It doesn't matter if we in particular are part of the resize, since we couldn't have
+ // a DimLayer anyway if we weren't visible.
+ final boolean dockedResizing = displayContent != null
+ && displayContent.mDividerControllerLocked.isResizing();
if (inFreeformWindowingMode()) {
boolean[] foundTop = { false };
forAllActivities(a -> { getMaxVisibleBounds(a, out, foundTop); });
@@ -2819,10 +2825,18 @@ class Task extends TaskFragment {
if (!matchParentBounds()) {
// When minimizing the root docked task when going home, we don't adjust the task bounds
- // so we need to intersect the task bounds with the root task bounds here..
- rootTask.getBounds(mTmpRect);
- mTmpRect.intersect(getBounds());
- out.set(mTmpRect);
+ // so we need to intersect the task bounds with the root task bounds here.
+ //
+ // If we are Docked Resizing with snap points, the task bounds could be smaller than the
+ // root task bounds and so we don't even want to use them. Even if the app should not be
+ // resized the Dim should keep up with the divider.
+ if (dockedResizing) {
+ rootTask.getBounds(out);
+ } else {
+ rootTask.getBounds(mTmpRect);
+ mTmpRect.intersect(getBounds());
+ out.set(mTmpRect);
+ }
} else {
out.set(getBounds());
}
@@ -2853,15 +2867,16 @@ class Task extends TaskFragment {
}
}
- void setDragResizing(boolean dragResizing) {
+ void setDragResizing(boolean dragResizing, int dragResizeMode) {
if (mDragResizing != dragResizing) {
- // No need to check if allowed if it's leaving dragResize
+ // No need to check if the mode is allowed if it's leaving dragResize
if (dragResizing
- && !(getRootTask().getWindowingMode() == WINDOWING_MODE_FREEFORM)) {
- throw new IllegalArgumentException("Drag resize not allow for root task id="
- + getRootTaskId());
+ && !DragResizeMode.isModeAllowedForRootTask(getRootTask(), dragResizeMode)) {
+ throw new IllegalArgumentException("Drag resize mode not allow for root task id="
+ + getRootTaskId() + " dragResizeMode=" + dragResizeMode);
}
mDragResizing = dragResizing;
+ mDragResizeMode = dragResizeMode;
resetDragResizingChangeReported();
}
}
@@ -2870,6 +2885,10 @@ class Task extends TaskFragment {
return mDragResizing;
}
+ int getDragResizeMode() {
+ return mDragResizeMode;
+ }
+
void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
if (displayContent == null) {
return;
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 9b3fb6b881c4..5b32149b818d 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -27,6 +27,7 @@ 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.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -367,7 +368,7 @@ class TaskPositioner implements IBinder.DeathRecipient {
private void endDragLocked() {
mResizing = false;
- mTask.setDragResizing(false);
+ mTask.setDragResizing(false, DRAG_RESIZE_MODE_FREEFORM);
}
/** Returns true if the move operation should be ended. */
@@ -379,7 +380,7 @@ class TaskPositioner implements IBinder.DeathRecipient {
if (mCtrlType != CTRL_NONE) {
resizeDrag(x, y);
- mTask.setDragResizing(true);
+ mTask.setDragResizing(true, DRAG_RESIZE_MODE_FREEFORM);
return false;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 23bce36fc5d4..be1e7e6977fa 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7128,6 +7128,20 @@ public class WindowManagerService extends IWindowManager.Stub
return 0;
}
+ void setDockedRootTaskResizing(boolean resizing) {
+ getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
+ requestTraversal();
+ }
+
+ @Override
+ public void setDockedTaskDividerTouchRegion(Rect touchRegion) {
+ synchronized (mGlobalLock) {
+ final DisplayContent dc = getDefaultDisplayContentLocked();
+ dc.getDockedDividerController().setTouchRegion(touchRegion);
+ dc.updateTouchExcludeRegion();
+ }
+ }
+
void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) {
synchronized (mGlobalLock) {
mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays;
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 9b69369d8195..72411727361a 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -51,6 +51,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANI
import static com.android.server.wm.ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED;
import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
import static com.android.server.wm.TaskFragment.EMBEDDING_ALLOWED;
@@ -721,7 +722,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
if ((c.getChangeMask() & WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING) != 0) {
- tr.setDragResizing(c.getDragResizing());
+ tr.setDragResizing(c.getDragResizing(), DRAG_RESIZE_MODE_FREEFORM);
}
final int childWindowingMode = c.getActivityWindowingMode();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4d6f7bc5011e..1b7bd9e1f36f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -36,6 +36,9 @@ import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
+import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
+import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
+import static android.view.WindowCallbacks.RESIZE_MODE_INVALID;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.systemBars;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
@@ -120,6 +123,8 @@ import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE
import static com.android.server.wm.AnimationSpecProto.MOVE;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.DisplayContent.logsGestureExclusionRestrictions;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
@@ -365,6 +370,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
boolean mHidden = true; // Used to determine if to show child windows.
private boolean mDragResizing;
private boolean mDragResizingChangeReported = true;
+ private int mResizeMode;
private boolean mRedrawForSyncReported;
/**
@@ -3938,14 +3944,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (isDragResizeChanged) {
setDragResizing();
}
- final boolean isDragResizing = isDragResizing();
+ int resizeMode = RESIZE_MODE_INVALID;
+ if (isDragResizing()) {
+ switch (getResizeMode()) {
+ case DRAG_RESIZE_MODE_FREEFORM:
+ resizeMode = RESIZE_MODE_FREEFORM;
+ break;
+ case DRAG_RESIZE_MODE_DOCKED_DIVIDER:
+ resizeMode = RESIZE_MODE_DOCKED_DIVIDER;
+ break;
+ }
+ }
markRedrawForSyncReported();
try {
mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration,
getCompatInsetsState(), forceRelayout, alwaysConsumeSystemBars, displayId,
- syncWithBuffers ? mSyncSeqId : -1, isDragResizing);
+ syncWithBuffers ? mSyncSeqId : -1, resizeMode);
if (drawPending && prevRotation >= 0 && prevRotation != mLastReportedConfiguration
.getMergedConfiguration().windowConfiguration.getRotation()) {
mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
@@ -4188,6 +4204,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
super.resetDragResizingChangeReported();
}
+ int getResizeMode() {
+ return mResizeMode;
+ }
+
private boolean computeDragResizing() {
final Task task = getTask();
if (task == null) {
@@ -4210,7 +4230,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return true;
}
- return false;
+ return getDisplayContent().mDividerControllerLocked.isResizing()
+ && !task.inFreeformWindowingMode() && !isGoneForLayout();
}
void setDragResizing() {
@@ -4219,12 +4240,25 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return;
}
mDragResizing = resizing;
+ final Task task = getTask();
+ if (task != null && task.isDragResizing()) {
+ mResizeMode = task.getDragResizeMode();
+ } else {
+ mResizeMode = mDragResizing && getDisplayContent().mDividerControllerLocked.isResizing()
+ ? DRAG_RESIZE_MODE_DOCKED_DIVIDER
+ : DRAG_RESIZE_MODE_FREEFORM;
+ }
}
boolean isDragResizing() {
return mDragResizing;
}
+ boolean isDockedResizing() {
+ return (mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER)
+ || (isChildWindow() && getParentWindow().isDockedResizing());
+ }
+
@CallSuper
@Override
public void dumpDebug(ProtoOutputStream proto, long fieldId,
@@ -5900,6 +5934,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// level. Because the animation runs before display is rotated, task bounds should
// represent the frames in display space coordinates.
outFrame.set(getTask().getBounds());
+ } else if (isDockedResizing()) {
+ // If we are animating while docked resizing, then use the root task bounds as the
+ // animation target (which will be different than the task bounds)
+ outFrame.set(getTask().getParent().getBounds());
} else {
outFrame.set(getParentFrame());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 982137b00bfc..f983fa9b49e3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -3284,7 +3284,7 @@ public class ActivityRecordTests extends WindowTestsBase {
assertFalse(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);
verify(app2.mClient, atLeastOnce()).resized(any(), anyBoolean(), any(),
insetsStateCaptor.capture(), anyBoolean(), anyBoolean(), anyInt(), anyInt(),
- anyBoolean());
+ anyInt());
assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index 3f8acc651110..6e72bf360295 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -46,7 +46,7 @@ public class TestIWindow extends IWindow.Stub {
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfig, InsetsState insetsState, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId, int seqId, boolean dragResizing)
+ boolean alwaysConsumeSystemBars, int displayId, int seqId, int resizeMode)
throws RemoteException {
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 183ccceec4f4..69e3244af1b6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -276,9 +276,12 @@ public class WindowStateTests extends WindowTestsBase {
assertFalse(imeWindow.canBeImeTarget());
// Simulate the window is in split screen root task.
+ final DockedTaskDividerController controller =
+ mDisplayContent.getDockedDividerController();
final Task rootTask = createTask(mDisplayContent,
WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
spyOn(appWindow);
+ spyOn(controller);
spyOn(rootTask);
rootTask.setFocusable(false);
doReturn(rootTask).when(appWindow).getRootTask();
@@ -772,7 +775,7 @@ public class WindowStateTests extends WindowTestsBase {
anyBoolean() /* reportDraw */, any() /* mergedConfig */,
any() /* insetsState */, anyBoolean() /* forceLayout */,
anyBoolean() /* alwaysConsumeSystemBars */, anyInt() /* displayId */,
- anyInt() /* seqId */, anyBoolean() /* dragResizing */);
+ anyInt() /* seqId */, anyInt() /* resizeMode */);
} catch (RemoteException ignored) {
}
win.reportResized();