diff options
6 files changed, 87 insertions, 22 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 5bcf1027f384..4ba97d5f8bea 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -180,7 +180,12 @@ interface IWindowManager // caller must call setNewConfiguration() sometime later. Configuration updateOrientationFromAppTokens(in Configuration currentConfig, IBinder freezeThisOneIfNeeded); - void setNewConfiguration(in Configuration config); + // Notify window manager of the new configuration. Returns an array of stack ids that's + // affected by the update, ActivityManager should resize these stacks. + int[] setNewConfiguration(in Configuration config); + + // Retrieves the new bounds after the configuration update evaluated by window manager. + Rect getBoundsForNewConfiguration(int stackId); void startFreezingScreen(int exitAnim, int enterAnim); void stopFreezingScreen(); diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index ee73b90097af..bed5a2e219ae 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -238,6 +238,14 @@ public class ArrayUtils { return total; } + public static int[] convertToIntArray(List<Integer> list) { + int[] array = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + return array; + } + /** * Adds value to given array if not already present, providing set-like * behavior. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 39df9991d16b..ef0577327596 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -18045,6 +18045,9 @@ public final class ActivityManagerService extends ActivityManagerNative ActivityRecord starting, boolean initLocale, boolean persistent, int userId) { int changes = 0; + if (mWindowManager != null) { + mWindowManager.deferSurfaceLayout(); + } if (values != null) { Configuration newConfig = new Configuration(mConfiguration); changes = newConfig.updateFrom(values); @@ -18145,6 +18148,20 @@ public final class ActivityManagerService extends ActivityManagerNative null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); } } + // Update the configuration with WM first and check if any of the stacks need to be + // resized due to the configuration change. If so, resize the stacks now and do any + // relaunches if necessary. This way we don't need to relaunch again below in + // ensureActivityConfigurationLocked(). + if (mWindowManager != null) { + final int[] resizedStacks = mWindowManager.setNewConfiguration(mConfiguration); + if (resizedStacks != null) { + for (int stackId : resizedStacks) { + final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId); + mStackSupervisor.resizeStackLocked( + stackId, newBounds, null, null, false, false); + } + } + } } boolean kept = true; @@ -18166,11 +18183,9 @@ public final class ActivityManagerService extends ActivityManagerNative !PRESERVE_WINDOWS); } } - - if (values != null && mWindowManager != null) { - mWindowManager.setNewConfiguration(mConfiguration); + if (mWindowManager != null) { + mWindowManager.continueSurfaceLayout(); } - return kept; } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 0bf7102ddeb8..b05cfb8e406d 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -128,6 +128,10 @@ public class TaskStack implements DimLayer.DimLayerUser, // in which case a second window animation would cause jitter. private boolean mFreezeMovementAnimations = false; + // Temporary storage for the new bounds that should be used after the configuration change. + // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration(). + private final Rect mBoundsAfterRotation = new Rect(); + TaskStack(WindowManagerService service, int stackId) { mService = service; mStackId = stackId; @@ -343,28 +347,28 @@ public class TaskStack implements DimLayer.DimLayerUser, setBounds(mTmpRect2); } else { mLastUpdateDisplayInfoRotation = newRotation; - updateBoundsAfterRotation(); + updateBoundsAfterRotation(true); } } - void onConfigurationChanged() { + boolean onConfigurationChanged() { mLastConfigChangedRotation = getDisplayInfo().rotation; - updateBoundsAfterRotation(); + return updateBoundsAfterRotation(false); } - void updateBoundsAfterRotation() { + boolean updateBoundsAfterRotation(boolean scheduleResize) { if (mLastConfigChangedRotation != mLastUpdateDisplayInfoRotation) { // We wait for the rotation values after configuration change and display info. update // to be equal before updating the bounds due to rotation change otherwise things might // get out of alignment... - return; + return false; } final int newRotation = getDisplayInfo().rotation; if (mRotation == newRotation) { // Nothing to do here if the rotation didn't change - return; + return false; } mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2); @@ -373,11 +377,22 @@ public class TaskStack implements DimLayer.DimLayerUser, snapDockedStackAfterRotation(mTmpRect2); } - // 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.obtainMessage( - RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget(); + if (scheduleResize) { + // 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.obtainMessage(RESIZE_STACK, mStackId, + 0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget(); + } else { + mBoundsAfterRotation.set(mTmpRect2); + } + + return true; + } + + void getBoundsForNewConfiguration(Rect outBounds) { + outBounds.set(mBoundsAfterRotation); + mBoundsAfterRotation.setEmpty(); } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index dcb4a63a560a..192ba7b879e4 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -125,6 +125,7 @@ import com.android.internal.R; import com.android.internal.app.IAssistScreenshotReceiver; import com.android.internal.os.IResultReceiver; import com.android.internal.policy.IShortcutService; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; @@ -515,6 +516,8 @@ public class WindowManagerService extends IWindowManager.Stub private final SparseIntArray mTmpTaskIds = new SparseIntArray(); + private final ArrayList<Integer> mChangedStackList = new ArrayList(); + boolean mForceResizableTasks = false; int getDragLayerLocked() { @@ -3580,7 +3583,7 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void setNewConfiguration(Configuration config) { + public int[] setNewConfiguration(Configuration config) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "setNewConfiguration()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); @@ -3592,16 +3595,30 @@ public class WindowManagerService extends IWindowManager.Stub mWaitingForConfig = false; mLastFinishedFreezeSource = "new-config"; } - onConfigurationChanged(); - mWindowPlacerLocked.performSurfacePlacement(); + return onConfigurationChanged(); } } - private void onConfigurationChanged() { + @Override + public Rect getBoundsForNewConfiguration(int stackId) { + synchronized(mWindowMap) { + final TaskStack stack = mStackIdToStack.get(stackId); + final Rect outBounds = new Rect(); + stack.getBoundsForNewConfiguration(outBounds); + return outBounds; + } + } + + private int[] onConfigurationChanged() { + mChangedStackList.clear(); for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) { final TaskStack stack = mStackIdToStack.valueAt(stackNdx); - stack.onConfigurationChanged(); + if (stack.onConfigurationChanged()) { + mChangedStackList.add(stack.mStackId); + } } + return mChangedStackList.isEmpty() ? + null : ArrayUtils.convertToIntArray(mChangedStackList); } @Override diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 7faee1b3d174..0abc3c5d1c0f 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -403,7 +403,12 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public void setNewConfiguration(Configuration arg0) throws RemoteException { + public int[] setNewConfiguration(Configuration arg0) throws RemoteException { + // TODO Auto-generated method stub + } + + @Override + public Rect getBoundsForNewConfiguration(int stackId) throws RemoteException { // TODO Auto-generated method stub } |