From ffc11bb712343b634901fe2d0e0022e7e578dd5c Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Sat, 10 Oct 2015 13:05:45 -0700 Subject: [PATCH] Don't set incorrect stack bounds when rotating screen in docked mode Both window manager and activity manager could decide what the bounds of other stacks should be when the docked stack exist which can get out of sync. Now window manager does the bounds calculation and activity manager asks window manager what the bounds should be when it needs to resize the stack. Bug: 24738105 Change-Id: I97356f008b676d2f58a8b54fdb08735ab51394af --- cmds/am/src/com/android/commands/am/Am.java | 6 +- core/java/android/app/ActivityManagerNative.java | 9 ++- core/java/android/app/IActivityManager.java | 2 +- .../android/server/am/ActivityManagerService.java | 5 +- .../android/server/am/ActivityStackSupervisor.java | 28 ++++----- .../server/wm/DockedStackDividerController.java | 5 +- .../core/java/com/android/server/wm/TaskStack.java | 70 +++++++++++++++++----- .../android/server/wm/WindowManagerService.java | 13 +++- 8 files changed, 96 insertions(+), 42 deletions(-) diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 4a13136fa8d9..81da6af20eb2 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -2033,7 +2033,7 @@ public class Am extends BaseCommand { } try { - mAm.resizeStack(stackId, bounds); + mAm.resizeStack(stackId, bounds, false); Thread.sleep(delayMs); } catch (RemoteException e) { showError("Error: resizing stack " + e); @@ -2127,8 +2127,8 @@ public class Am extends BaseCommand { } // Resize stacks - mAm.resizeStack(currentStackInfo.stackId, currentStackBounds); - mAm.resizeStack(newStackInfo.stackId, newStackBounds); + mAm.resizeStack(currentStackInfo.stackId, currentStackBounds, false); + mAm.resizeStack(newStackInfo.stackId, newStackBounds, false); } catch (RemoteException e) { } } diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index faa3a43f6c2e..b97f94735b9f 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -757,9 +757,10 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case RESIZE_STACK_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - int stackId = data.readInt(); + final int stackId = data.readInt(); Rect r = Rect.CREATOR.createFromParcel(data); - resizeStack(stackId, r); + final boolean allowResizeInDockedMode = data.readInt() == 1; + resizeStack(stackId, r, allowResizeInDockedMode); reply.writeNoException(); return true; } @@ -3554,13 +3555,15 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } @Override - public void resizeStack(int stackId, Rect r) throws RemoteException + public void resizeStack(int stackId, Rect r, boolean allowResizeInDockedMode) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeInt(stackId); r.writeToParcel(data, 0); + data.writeInt(allowResizeInDockedMode ? 1 : 0); mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index e23620d9b0ea..c26a44cae57c 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -143,7 +143,7 @@ public interface IActivityManager extends IInterface { public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException; public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop) throws RemoteException; - public void resizeStack(int stackId, Rect bounds) throws RemoteException; + public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode) throws RemoteException; public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException; public List getAllStackInfos() throws RemoteException; public StackInfo getStackInfo(int stackId) throws RemoteException; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 759a4f380ba4..e7601c2ec93e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9161,13 +9161,14 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void resizeStack(int stackId, Rect bounds) { + public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode) { enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, "resizeStack()"); long ident = Binder.clearCallingIdentity(); try { synchronized (this) { - mStackSupervisor.resizeStackLocked(stackId, bounds, !PRESERVE_WINDOWS); + mStackSupervisor.resizeStackLocked( + stackId, bounds, !PRESERVE_WINDOWS, allowResizeInDockedMode); } } finally { Binder.restoreCallingIdentity(ident); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 8bec7f7cad97..4a58b1fa6fe2 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2972,13 +2972,21 @@ public final class ActivityStackSupervisor implements DisplayListener { } } - void resizeStackLocked(int stackId, Rect bounds, boolean preserveWindows) { + void resizeStackLocked(int stackId, Rect bounds, boolean preserveWindows, + boolean allowResizeInDockedMode) { final ActivityStack stack = getStack(stackId); if (stack == null) { Slog.w(TAG, "resizeStack: stackId " + stackId + " not found."); return; } + if (!allowResizeInDockedMode + && stackId != DOCKED_STACK_ID && getStack(DOCKED_STACK_ID) != null) { + // If the docked stack exist we don't allow resizes of stacks not caused by the docked + // stack size changing so things don't get out of sync. + return; + } + Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId); ActivityRecord r = stack.topRunningActivityLocked(); @@ -3013,7 +3021,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // docked stack tasks to the fullscreen stack. for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) { if (i != DOCKED_STACK_ID && getStack(i) != null) { - resizeStackLocked(i, null, preserveWindows); + resizeStackLocked(i, null, preserveWindows, true); } } @@ -3028,23 +3036,15 @@ public final class ActivityStackSupervisor implements DisplayListener { } else { // Docked stacks occupy a dedicated region on screen so the size of all other // static stacks need to be adjusted so they don't overlap with the docked stack. - final int leftChange = stack.mBounds.left - bounds.left; - final int rightChange = stack.mBounds.right - bounds.right; - final int topChange = stack.mBounds.top - bounds.top; - final int bottomChange = stack.mBounds.bottom - bounds.bottom; + // We get the bounds to use from window manager which has been adjusted for any + // screen controls and is also the same for all stacks. + mWindowManager.getStackDockedModeBounds(HOME_STACK_ID, tempRect); for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) { if (i != DOCKED_STACK_ID) { ActivityStack otherStack = getStack(i); if (otherStack != null) { - tempRect.set(otherStack.mBounds); - // We adjust the opposing sides of the other stacks to - // the side in the dock stack that changed. - tempRect.left -= rightChange; - tempRect.right -= leftChange; - tempRect.top -= bottomChange; - tempRect.bottom -= topChange; - resizeStackLocked(i, tempRect, PRESERVE_WINDOWS); + resizeStackLocked(i, tempRect, PRESERVE_WINDOWS, true); } } } diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 3c2864853fab..2d8712375757 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -206,7 +206,8 @@ public class DockedStackDividerController implements View.OnTouchListener, DimLa } if (distance <= mSideMargin) { try { - mDisplayContent.mService.mActivityManager.resizeStack(mTaskStack.mStackId, null); + mDisplayContent.mService.mActivityManager.resizeStack( + mTaskStack.mStackId, null, true); } catch (RemoteException e) { // This can't happen because we are in the same process. } @@ -364,7 +365,7 @@ public class DockedStackDividerController implements View.OnTouchListener, DimLa } mLastResizeRect.set(mTmpRect); try { - mDisplayContent.mService.mActivityManager.resizeStack(DOCKED_STACK_ID, mTmpRect); + mDisplayContent.mService.mActivityManager.resizeStack(DOCKED_STACK_ID, mTmpRect, true); } catch (RemoteException e) { // This can't happen because we are in the same process. } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index ca358b15bbb8..b409cea249c2 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -238,8 +238,8 @@ public class TaskStack implements DimLayer.DimLayerUser { // Post message to inform activity manager of the bounds change simulating // a one-way call. We do this to prevent a deadlock between window manager // lock and activity manager lock been held. - mService.mH.sendMessage( - mService.mH.obtainMessage(RESIZE_STACK, mStackId, UNUSED, mBounds)); + mService.mH.sendMessage(mService.mH.obtainMessage( + RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mBounds)); } } } @@ -399,8 +399,11 @@ public class TaskStack implements DimLayer.DimLayerUser { if (dockedStack != null) { dockedStack.getRawBounds(mTmpRect2); } - getInitialDockedStackBounds(mTmpRect, bounds, mStackId, mTmpRect2, - mDisplayContent.mDividerControllerLocked.getWidthAdjustment()); + final boolean dockedOnTopOrLeft = WindowManagerService.sDockedStackCreateMode + == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; + getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2, + mDisplayContent.mDividerControllerLocked.getWidthAdjustment(), + dockedOnTopOrLeft); } updateDisplayInfo(bounds); @@ -413,28 +416,60 @@ public class TaskStack implements DimLayer.DimLayerUser { } } + void getStackDockedModeBoundsLocked(Rect outBounds) { + if (mStackId == DOCKED_STACK_ID + || mStackId > LAST_STATIC_STACK_ID + || mDisplayContent == null) { + outBounds.set(mBounds); + return; + } + + final TaskStack dockedStack = mDisplayContent.getDockedStackLocked(); + if (dockedStack == null) { + // Not sure why you are calling this method when there is no docked stack... + throw new IllegalStateException( + "Calling getStackDockedModeBoundsLocked() when there is no docked stack."); + } + + @DockSide + final int dockedSide = dockedStack.getDockSide(); + if (dockedSide == DOCKED_INVALID) { + // Not sure how you got here...Only thing we can do is return current bounds. + Slog.e(TAG, "Failed to get valid docked side for docked stack=" + dockedStack); + outBounds.set(mBounds); + return; + } + + mDisplayContent.getLogicalDisplayRect(mTmpRect); + dockedStack.getRawBounds(mTmpRect2); + final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT; + getStackDockedModeBounds(mTmpRect, outBounds, mStackId, mTmpRect2, + mDisplayContent.mDividerControllerLocked.getWidthAdjustment(), dockedOnTopOrLeft); + + } + /** - * Outputs the initial bounds a stack should be given the presence of a docked stack on the - * display. + * Outputs the bounds a stack should be given the presence of a docked stack on the display. * @param displayRect The bounds of the display the docked stack is on. * @param outBounds Output bounds that should be used for the stack. * @param stackId Id of stack we are calculating the bounds for. * @param dockedBounds Bounds of the docked stack. - * @param adjustment + * @param adjustment Additional adjustment to make to the output bounds close to the side of the + * dock. + * @param dockOntopOrLeft If the docked stack is on the top or left side of the screen. */ - private static void getInitialDockedStackBounds( - Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int adjustment) { + private static void getStackDockedModeBounds( + Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int adjustment, + boolean dockOntopOrLeft) { final boolean dockedStack = stackId == DOCKED_STACK_ID; final boolean splitHorizontally = displayRect.width() > displayRect.height(); - final boolean topOrLeftCreateMode = - WindowManagerService.sDockedStackCreateMode == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; outBounds.set(displayRect); if (dockedStack) { // The initial bounds of the docked stack when it is created half the screen space and // its bounds can be adjusted after that. The bounds of all other stacks are adjusted // to occupy whatever screen space the docked stack isn't occupying. - if (topOrLeftCreateMode) { + if (dockOntopOrLeft) { if (splitHorizontally) { outBounds.right = displayRect.centerX() - adjustment; } else { @@ -451,7 +486,7 @@ public class TaskStack implements DimLayer.DimLayerUser { } // Other stacks occupy whatever space is left by the docked stack. - if (!topOrLeftCreateMode) { + if (!dockOntopOrLeft) { if (splitHorizontally) { outBounds.right = dockedBounds.left - adjustment; } else { @@ -477,8 +512,10 @@ public class TaskStack implements DimLayer.DimLayerUser { final Rect bounds = new Rect(); mDisplayContent.getLogicalDisplayRect(bounds); if (!fullscreen) { - getInitialDockedStackBounds(bounds, bounds, FULLSCREEN_WORKSPACE_STACK_ID, dockedBounds, - mDisplayContent.mDividerControllerLocked.getWidth()); + final boolean dockedOnTopOrLeft = WindowManagerService.sDockedStackCreateMode + == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; + getStackDockedModeBounds(bounds, bounds, FULLSCREEN_WORKSPACE_STACK_ID, dockedBounds, + mDisplayContent.mDividerControllerLocked.getWidth(), dockedOnTopOrLeft); } final int count = mService.mStackIdToStack.size(); @@ -489,7 +526,8 @@ public class TaskStack implements DimLayer.DimLayerUser { && otherStackId >= FIRST_STATIC_STACK_ID && otherStackId <= LAST_STATIC_STACK_ID) { mService.mH.sendMessage( - mService.mH.obtainMessage(RESIZE_STACK, otherStackId, UNUSED, bounds)); + mService.mH.obtainMessage(RESIZE_STACK, otherStackId, + 1 /*allowResizeInDockedMode*/, bounds)); } } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 0170bb965540..264af41a9de4 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4617,6 +4617,17 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void getStackDockedModeBounds(int stackId, Rect bounds) { + synchronized (mWindowMap) { + final TaskStack stack = mStackIdToStack.get(stackId); + if (stack != null) { + stack.getStackDockedModeBoundsLocked(bounds); + return; + } + bounds.setEmpty(); + } + } + public void getStackBounds(int stackId, Rect bounds) { synchronized (mWindowMap) { final TaskStack stack = mStackIdToStack.get(stackId); @@ -7777,7 +7788,7 @@ public class WindowManagerService extends IWindowManager.Stub break; case RESIZE_STACK: { try { - mActivityManager.resizeStack(msg.arg1, (Rect) msg.obj); + mActivityManager.resizeStack(msg.arg1, (Rect) msg.obj, msg.arg2 == 1); } catch (RemoteException e) { // This will not happen since we are in the same process. } -- 2.11.0