diff options
6 files changed, 104 insertions, 46 deletions
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index d3cea8de1442..0a3391ca8cfe 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -3061,7 +3061,12 @@ public final class ActivityStackSupervisor implements DisplayListener { return; } - if (task.mBounds != null && task.mBounds.equals(bounds)) { + // TODO: change resizedByUser to an enum (or bitmask?) to indicate the origin of + // this resize (eg. systemResize, userResize, forcedResized). + // If the resize is a drag-resize by user, let it go through even if the bounds + // is not changing, as we might need a relayout due to surface size change + // (to/from fullscreen). + if (task.mBounds != null && task.mBounds.equals(bounds) && !resizedByUser) { // Nothing to do here... return; } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index cc9efdbe90af..58f044801f7f 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -72,6 +72,12 @@ class Task implements DimLayer.DimLayerUser { // For handling display rotations. private Rect mTmpRect2 = new Rect(); + // Whether the task is currently being drag-resized + private boolean mDragResizing; + + // Whether the task is starting or ending to be drag-resized + private boolean mDragResizeChanging; + // The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer. WindowStateAnimator mDimWinAnimator; // Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND} @@ -227,10 +233,34 @@ class Task implements DimLayer.DimLayerUser { return boundsChange; } + boolean resizeLocked(Rect bounds, Configuration configuration) { + int boundsChanged = setBounds(bounds, configuration); + if (mDragResizeChanging) { + boundsChanged |= BOUNDS_CHANGE_SIZE; + mDragResizeChanging = false; + } + if (boundsChanged == BOUNDS_CHANGE_NONE) { + return false; + } + if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) { + resizeWindows(); + } + return true; + } + void getBounds(Rect out) { out.set(mBounds); } + void setDragResizing(boolean dragResizing) { + mDragResizeChanging = mDragResizing != dragResizing; + mDragResizing = dragResizing; + } + + boolean isDragResizing() { + return mDragResizing; + } + void updateDisplayInfo(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 17b56ba2ada2..548734939fea 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -86,8 +86,7 @@ class TaskPositioner implements DimLayer.DimLayerUser { private int mMinVisibleWidth; private int mMinVisibleHeight; - private int mTaskId; - private TaskStack mStack; + private Task mTask; private boolean mResizing; private final Rect mWindowOriginalBounds = new Rect(); private final Rect mWindowDragBounds = new Rect(); @@ -136,7 +135,7 @@ class TaskPositioner implements DimLayer.DimLayerUser { } try { mService.mActivityManager.resizeTask( - mTaskId, mWindowDragBounds, true /* resizedByUser */); + mTask.mTaskId, mWindowDragBounds, true /* resizedByUser */); } catch(RemoteException e) {} } break; @@ -156,21 +155,29 @@ class TaskPositioner implements DimLayer.DimLayerUser { } if (endDrag) { - mResizing = false; + synchronized (mService.mWindowMap) { + endDragLocked(); + } try { - mService.mActivityManager.resizeTask( - mTaskId, mWindowDragBounds, true /* resizedByUser */); + if (mResizing) { + // We were using fullscreen surface during resizing. Request + // resizeTask() one last time to restore surface to window size. + mService.mActivityManager.resizeTask( + mTask.mTaskId, mWindowDragBounds, true /* resizedByUser */); + } + + if (mCurrentDimSide != CTRL_NONE) { + final int createMode = mCurrentDimSide == CTRL_LEFT + ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT + : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT; + mService.mActivityManager.moveTaskToDockedStack( + mTask.mTaskId, createMode, true /*toTop*/); + } } catch(RemoteException e) {} + // Post back to WM to handle clean-ups. We still need the input // event handler for the last finishInputEvent()! mService.mH.sendEmptyMessage(H.FINISH_TASK_POSITIONING); - if (mCurrentDimSide != CTRL_NONE) { - final int createMode = mCurrentDimSide == CTRL_LEFT - ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT - : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT; - mService.mActivityManager.moveTaskToDockedStack( - mTaskId, createMode, true /*toTop*/); - } } handled = true; } catch (Exception e) { @@ -291,10 +298,6 @@ class TaskPositioner implements DimLayer.DimLayerUser { mService.resumeRotationLocked(); } - boolean isTaskResizing(final Task task) { - return mResizing && task != null && mTaskId == task.mTaskId; - } - void startDragLocked(WindowState win, boolean resize, float startX, float startY) { if (DEBUG_TASK_POSITIONING) { Slog.d(TAG, "startDragLocked: win=" + win + ", resize=" + resize @@ -318,13 +321,16 @@ class TaskPositioner implements DimLayer.DimLayerUser { mResizing = true; } - final Task task = win.getTask(); - mTaskId = task.mTaskId; - mStack = task.mStack; + mTask = win.getTask(); mStartDragX = startX; mStartDragY = startY; - mService.getTaskBounds(mTaskId, mWindowOriginalBounds); + mService.getTaskBounds(mTask.mTaskId, mWindowOriginalBounds); + } + + private void endDragLocked() { + mResizing = false; + mTask.setDragResizing(false); } /** Returns true if the move operation should be ended. */ @@ -354,11 +360,12 @@ class TaskPositioner implements DimLayer.DimLayerUser { bottom = Math.max(top + mMinVisibleHeight, bottom + deltaY); } mWindowDragBounds.set(left, top, right, bottom); + mTask.setDragResizing(true); return false; } // This is a moving operation. - mStack.getBounds(mTmpRect); + mTask.mStack.getBounds(mTmpRect); mTmpRect.inset(mMinVisibleWidth, mMinVisibleHeight); if (!mTmpRect.contains((int) x, (int) y)) { // We end the moving operation if position is outside the stack bounds. @@ -397,13 +404,13 @@ class TaskPositioner implements DimLayer.DimLayerUser { * shouldn't be shown. */ private int getDimSide(int x) { - if (mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID - || !mStack.isFullscreen() + if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID + || !mTask.mStack.isFullscreen() || mService.mCurConfiguration.orientation != ORIENTATION_LANDSCAPE) { return CTRL_NONE; } - mStack.getBounds(mTmpRect); + mTask.mStack.getBounds(mTmpRect); if (x - mSideMargin <= mTmpRect.left) { return CTRL_LEFT; } @@ -415,7 +422,7 @@ class TaskPositioner implements DimLayer.DimLayerUser { } private void showDimLayer() { - mStack.getBounds(mTmpRect); + mTask.mStack.getBounds(mTmpRect); if (mCurrentDimSide == CTRL_LEFT) { mTmpRect.right = mTmpRect.centerX(); } else if (mCurrentDimSide == CTRL_RIGHT) { @@ -433,7 +440,7 @@ class TaskPositioner implements DimLayer.DimLayerUser { @Override /** {@link DimLayer.DimLayerUser} */ public DisplayInfo getDisplayInfo() { - return mStack.getDisplayInfo(); + return mTask.mStack.getDisplayInfo(); } private int getDragLayerLocked() { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 5bf296ef7e81..ffc848dfb4ac 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2589,9 +2589,13 @@ public class WindowManagerService extends IWindowManager.Stub } } - dragResizing = win.isDragResizing(); - if (win.mDragResizing != dragResizing) { - win.mDragResizing = dragResizing; + // If we're starting a drag-resize, we'll be changing the surface size as well as + // notifying the client to render to with an offset from the surface's top-left. + // Do a screen freeze, and keep the old surface until the the first frame drawn to + // the new surface comes back, so that we avoid a flash due to mismatching surface + // setups on window manager side and client side. + if (win.isDragResizeChanged()) { + win.setDragResizing(); if (win.mHasSurface) { winAnimator.mDestroyPendingSurfaceUponRedraw = true; winAnimator.mSurfaceDestroyDeferred = true; @@ -2600,6 +2604,7 @@ public class WindowManagerService extends IWindowManager.Stub toBeDisplayed = true; } } + dragResizing = win.isDragResizing(); try { if (!win.mHasSurface) { surfaceChanged = true; @@ -4688,16 +4693,10 @@ public class WindowManagerService extends IWindowManager.Stub throw new IllegalArgumentException("resizeTask: taskId " + taskId + " not found."); } - final int boundsChanged = task.setBounds(bounds, configuration); - if (boundsChanged != Task.BOUNDS_CHANGE_NONE) { - if ((boundsChanged & Task.BOUNDS_CHANGE_SIZE) == Task.BOUNDS_CHANGE_SIZE) { - task.resizeWindows(); - } - if (relayout) { - task.getDisplayContent().layoutNeeded = true; - mWindowPlacerLocked.performSurfacePlacement(); - } + if (task.resizeLocked(bounds, configuration) && relayout) { + task.getDisplayContent().layoutNeeded = true; + mWindowPlacerLocked.performSurfacePlacement(); } } } @@ -8480,7 +8479,7 @@ public class WindowManagerService extends IWindowManager.Stub Slog.v(TAG, "Win " + w + " config changed: " + mCurConfiguration); } - final boolean dragResizingChanged = w.mDragResizing != w.isDragResizing(); + final boolean dragResizingChanged = w.isDragResizeChanged(); if (localLOGV) Slog.v(TAG, "Resizing " + w + ": configChanged=" + configChanged + " dragResizingChanged=" + dragResizingChanged diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index fa28eba14603..7ed52491de59 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -129,6 +129,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { boolean mAttachedHidden; // is our parent window hidden? boolean mWallpaperVisible; // for wallpaper, what was last vis report? boolean mDragResizing; + boolean mDragResizeChanging; RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks; @@ -1691,9 +1692,18 @@ final class WindowState implements WindowManagerPolicy.WindowState { return task != null && task.inFreeformWorkspace(); } - boolean isDragResizing() { + boolean isDragResizeChanged() { + final Task task = getTask(); + return task != null && mDragResizing != task.isDragResizing(); + } + + void setDragResizing() { final Task task = getTask(); - return mService.mTaskPositioner != null && mService.mTaskPositioner.isTaskResizing(task); + mDragResizing = task != null && task.isDragResizing(); + } + + boolean isDragResizing() { + return mDragResizing; } void dump(PrintWriter pw, String prefix, boolean dumpAll) { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index e6fef2f0d22f..07e1fce4c741 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -818,7 +818,7 @@ class WindowStateAnimator { // so that we don't need to reallocate during the process. This also prevents // buffer drops due to size mismatch. final DisplayInfo displayInfo = w.getDisplayInfo(); - if (displayInfo != null && w.mDragResizing) { + if (displayInfo != null && w.isDragResizing()) { left = 0; top = 0; width = displayInfo.logicalWidth; @@ -1211,6 +1211,13 @@ class WindowStateAnimator { return; } else if (mIsWallpaper && mService.mWindowPlacerLocked.mWallpaperActionPending) { return; + } else if (mWin.isDragResizeChanged()) { + // This window is awaiting a relayout because user just started (or ended) + // drag-resizing. The shown frame (which affects surface size and pos) + // should not be updated until we get next finished draw with the new surface. + // Otherwise one or two frames rendered with old settings would be displayed + // with new geometry. + return; } if (WindowManagerService.localLOGV) Slog.v( @@ -1333,7 +1340,7 @@ class WindowStateAnimator { final boolean fullscreen = w.isFullscreen(displayInfo.appWidth, displayInfo.appHeight); final Rect clipRect = mTmpClipRect; - if (w.mDragResizing) { + if (w.isDragResizing()) { // When we're doing a drag-resizing, the surface is set up to cover full screen. // Set the clip rect to be the same size so that we don't get any scaling. clipRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); @@ -1423,7 +1430,7 @@ class WindowStateAnimator { // so that we don't need to reallocate during the process. This also prevents // buffer drops due to size mismatch. final DisplayInfo displayInfo = w.getDisplayInfo(); - if (displayInfo != null && w.mDragResizing) { + if (displayInfo != null && w.isDragResizing()) { left = 0; top = 0; width = displayInfo.logicalWidth; |