diff options
11 files changed, 162 insertions, 273 deletions
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 869e20745a48..49ffa22b53e3 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -649,15 +649,12 @@ final class AccessibilityController { private void populateWindowsOnScreenLocked(SparseArray<WindowState> outWindows) { final DisplayContent dc = mWindowManagerService.getDefaultDisplayContentLocked(); - final ReadOnlyWindowList windowList = dc.getReadOnlyWindowList(); - final int windowCount = windowList.size(); - for (int i = 0; i < windowCount; i++) { - final WindowState windowState = windowList.get(i); - if (windowState.isOnScreen() && windowState.isVisibleLw() && - !windowState.mWinAnimator.mEnterAnimationPending) { - outWindows.put(windowState.mLayer, windowState); + dc.forAllWindows((w) -> { + if (w.isOnScreen() && w.isVisibleLw() + && !w.mWinAnimator.mEnterAnimationPending) { + outWindows.put(w.mLayer, w); } - } + }, false /* traverseTopToBottom */ ); } private final class ViewportWindow { @@ -1296,14 +1293,11 @@ final class AccessibilityController { private void populateVisibleWindowsOnScreenLocked(SparseArray<WindowState> outWindows) { final DisplayContent dc = mWindowManagerService.getDefaultDisplayContentLocked(); - final ReadOnlyWindowList windowList = dc.getReadOnlyWindowList(); - final int windowCount = windowList.size(); - for (int i = 0; i < windowCount; i++) { - final WindowState windowState = windowList.get(i); - if (windowState.isVisibleLw()) { - outWindows.put(windowState.mLayer, windowState); + dc.forAllWindows((w) -> { + if (w.isVisibleLw()) { + outWindows.put(w.mLayer, w); } - } + }, false /* traverseTopToBottom */ ); } private class MyHandler extends Handler { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 6a625f45f2b7..ff39853833da 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1400,14 +1400,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo /** Updates the layer assignment of windows on this display. */ void assignWindowLayers(boolean setLayoutNeeded) { - mLayersController.assignWindowLayers(mWindows.getReadOnly()); + mLayersController.assignWindowLayers(this); if (setLayoutNeeded) { setLayoutNeeded(); } } void adjustWallpaperWindows() { - if (mWallpaperController.adjustWallpaperWindows(mWindows.getReadOnly())) { + if (mWallpaperController.adjustWallpaperWindows(mWindows)) { assignWindowLayers(true /*setLayoutNeeded*/); } } @@ -2457,14 +2457,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } - ReadOnlyWindowList getReadOnlyWindowList() { - return mWindows.getReadOnly(); - } - - void getWindows(WindowList output) { - output.addAll(mWindows); - } - // TODO: Super crazy long method that should be broken down... boolean applySurfaceChangesTransaction(boolean recoveringMemory) { diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 6326148d7d86..c56f6b86aa16 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -266,10 +266,8 @@ public class DockedStackDividerController implements DimLayerUser { } private void resetDragResizingChangeReported() { - final ReadOnlyWindowList windowList = mDisplayContent.getReadOnlyWindowList(); - for (int i = windowList.size() - 1; i >= 0; i--) { - windowList.get(i).resetDragResizingChangeReported(); - } + mDisplayContent.forAllWindows(WindowState::resetDragResizingChangeReported, + true /* traverseTopToBottom */ ); } void setWindow(WindowState window) { diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index d52168c46ff3..4d195e838bf7 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -271,11 +271,8 @@ class DragState { Slog.d(TAG_WM, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")"); } - final ReadOnlyWindowList windows = mDisplayContent.getReadOnlyWindowList(); - final int N = windows.size(); - for (int i = 0; i < N; i++) { - sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription); - } + mDisplayContent.forAllWindows((w) -> sendDragStartedLw(w, touchX, touchY, mDataDescription), + false /* traverseTopToBottom */ ); } /* helper - send a ACTION_DRAG_STARTED event, if the diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 299fa05d0ed9..88986e33894a 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -219,28 +219,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { return false; } - void getWindows(WindowList output) { - final int count = mChildren.size(); - for (int i = 0; i < count; ++i) { - final DisplayContent dc = mChildren.get(i); - dc.getWindows(output); - } - } - - void getWindows(WindowList output, boolean visibleOnly, boolean appsOnly) { - final int numDisplays = mChildren.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final ReadOnlyWindowList windowList = mChildren.get(displayNdx).getReadOnlyWindowList(); - for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { - final WindowState w = windowList.get(winNdx); - if ((!visibleOnly || w.mWinAnimator.getShown()) - && (!appsOnly || w.mAppToken != null)) { - output.add(w); - } - } - } - } - void getWindowsByName(WindowList output, String name) { int objectId = 0; // See if this is an object ID. @@ -249,36 +227,20 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { name = null; } catch (RuntimeException e) { } - final int numDisplays = mChildren.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final ReadOnlyWindowList windowList = mChildren.get(displayNdx).getReadOnlyWindowList(); - for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { - final WindowState w = windowList.get(winNdx); - if (name != null) { - if (w.mAttrs.getTitle().toString().contains(name)) { - output.add(w); - } - } else if (System.identityHashCode(w) == objectId) { - output.add(w); - } - } - } + + getWindowsByName(output, name, objectId); } - WindowState findWindow(int hashCode) { - final int numDisplays = mChildren.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final ReadOnlyWindowList windows = mChildren.get(displayNdx).getReadOnlyWindowList(); - final int numWindows = windows.size(); - for (int winNdx = 0; winNdx < numWindows; ++winNdx) { - final WindowState w = windows.get(winNdx); - if (System.identityHashCode(w) == hashCode) { - return w; + private void getWindowsByName(WindowList output, String name, int objectId) { + forAllWindows((w) -> { + if (name != null) { + if (w.mAttrs.getTitle().toString().contains(name)) { + output.add(w); } + } else if (System.identityHashCode(w) == objectId) { + output.add(w); } - } - - return null; + }, true /* traverseTopToBottom */); } /** @@ -399,81 +361,50 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { } void setSecureSurfaceState(int userId, boolean disabled) { - for (int i = mChildren.size() - 1; i >= 0; --i) { - final ReadOnlyWindowList windows = mChildren.get(i).getReadOnlyWindowList(); - for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { - final WindowState win = windows.get(winNdx); - if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) { - win.mWinAnimator.setSecureLocked(disabled); - } + forAllWindows((w) -> { + if (w.mHasSurface && userId == UserHandle.getUserId(w.mOwnerUid)) { + w.mWinAnimator.setSecureLocked(disabled); } - } + }, true /* traverseTopToBottom */); } void updateAppOpsState() { - final int count = mChildren.size(); - for (int i = 0; i < count; ++i) { - final ReadOnlyWindowList windows = mChildren.get(i).getReadOnlyWindowList(); - final int numWindows = windows.size(); - for (int winNdx = 0; winNdx < numWindows; ++winNdx) { - final WindowState win = windows.get(winNdx); - if (win.mAppOp == OP_NONE) { - continue; - } - final int mode = mService.mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), - win.getOwningPackage()); - win.setAppOpVisibilityLw(mode == MODE_ALLOWED || mode == MODE_DEFAULT); + forAllWindows((w) -> { + if (w.mAppOp == OP_NONE) { + return; } - } + final int mode = mService.mAppOps.checkOpNoThrow(w.mAppOp, w.getOwningUid(), + w.getOwningPackage()); + w.setAppOpVisibilityLw(mode == MODE_ALLOWED || mode == MODE_DEFAULT); + }, false /* traverseTopToBottom */); } boolean canShowStrictModeViolation(int pid) { - final int count = mChildren.size(); - for (int i = 0; i < count; ++i) { - final ReadOnlyWindowList windows = mChildren.get(i).getReadOnlyWindowList(); - final int numWindows = windows.size(); - for (int winNdx = 0; winNdx < numWindows; ++winNdx) { - final WindowState ws = windows.get(winNdx); - if (ws.mSession.mPid == pid && ws.isVisibleLw()) { - return true; - } - } - } - return false; + final WindowState win = getWindow((w) -> w.mSession.mPid == pid && w.isVisibleLw()); + return win != null; } void closeSystemDialogs(String reason) { - final int count = mChildren.size(); - for (int i = 0; i < count; ++i) { - final ReadOnlyWindowList windows = mChildren.get(i).getReadOnlyWindowList(); - final int numWindows = windows.size(); - for (int j = 0; j < numWindows; ++j) { - final WindowState w = windows.get(j); - if (w.mHasSurface) { - try { - w.mClient.closeSystemDialogs(reason); - } catch (RemoteException e) { - } + forAllWindows((w) -> { + if (w.mHasSurface) { + try { + w.mClient.closeSystemDialogs(reason); + } catch (RemoteException e) { } } - } + }, false /* traverseTopToBottom */); } void removeReplacedWindows() { if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows"); mService.openSurfaceTransaction(); try { - for (int i = mChildren.size() - 1; i >= 0; i--) { - DisplayContent dc = mChildren.get(i); - final ReadOnlyWindowList windows = mChildren.get(i).getReadOnlyWindowList(); - for (int j = windows.size() - 1; j >= 0; j--) { - final WindowState win = windows.get(j); - final AppWindowToken aToken = win.mAppToken; - if (aToken != null) { - aToken.removeReplacedWindowIfNeeded(win); - } + forAllWindows((w) -> { + final AppWindowToken aToken = w.mAppToken; + if (aToken != null) { + aToken.removeReplacedWindowIfNeeded(w); } - } + }, true /* traverseTopToBottom */); } finally { mService.closeSurfaceTransaction(); if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows"); @@ -530,19 +461,15 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { Slog.w(TAG_WM, "No leaked surfaces; killing applications!"); final SparseIntArray pidCandidates = new SparseIntArray(); for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final ReadOnlyWindowList windows = - mChildren.get(displayNdx).getReadOnlyWindowList(); - final int numWindows = windows.size(); - for (int winNdx = 0; winNdx < numWindows; ++winNdx) { - final WindowState ws = windows.get(winNdx); - if (mService.mForceRemoves.contains(ws)) { - continue; + mChildren.get(displayNdx).forAllWindows((w) -> { + if (mService.mForceRemoves.contains(w)) { + return; } - final WindowStateAnimator wsa = ws.mWinAnimator; + final WindowStateAnimator wsa = w.mWinAnimator; if (wsa.mSurfaceController != null) { pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); } - } + }, false /* traverseTopToBottom */); if (pidCandidates.size() > 0) { int[] pids = new int[pidCandidates.size()]; @@ -1078,17 +1005,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { } void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) { - final int numDisplays = mChildren.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final ReadOnlyWindowList windowList = mChildren.get(displayNdx).getReadOnlyWindowList(); - for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { - final WindowState w = windowList.get(winNdx); - if (windows == null || windows.contains(w)) { - pw.println(" Window #" + winNdx + " " + w + ":"); - w.dump(pw, " ", dumpAll || windows != null); - } + final int[] index = new int[1]; + forAllWindows((w) -> { + if (windows == null || windows.contains(w)) { + pw.println(" Window #" + index[0] + " " + w + ":"); + w.dump(pw, " ", dumpAll || windows != null); + index[0] = index[0] + 1; } - } + }, true /* traverseTopToBottom */); } void dumpTokens(PrintWriter pw, boolean dumpAll) { diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 178fbe75ca59..d3e8e8eba880 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -388,7 +388,7 @@ class WallpaperController { return mWallpaperAnimLayerAdjustment; } - private void findWallpaperTarget(ReadOnlyWindowList windows, FindWallpaperTargetResult result) { + private void findWallpaperTarget(WindowList windows, FindWallpaperTargetResult result) { final WindowAnimator winAnimator = mService.mAnimator; result.reset(); WindowState w = null; @@ -489,7 +489,7 @@ class WallpaperController { /** Updates the target wallpaper if needed and returns true if an update happened. */ private boolean updateWallpaperWindowsTarget( - ReadOnlyWindowList windows, FindWallpaperTargetResult result) { + WindowList windows, FindWallpaperTargetResult result) { WindowState wallpaperTarget = result.wallpaperTarget; int wallpaperTargetIndex = result.wallpaperTargetIndex; @@ -590,7 +590,7 @@ class WallpaperController { return true; } - private boolean updateWallpaperWindowsTargetByLayer(ReadOnlyWindowList windows, + private boolean updateWallpaperWindowsTargetByLayer(WindowList windows, FindWallpaperTargetResult result) { WindowState wallpaperTarget = result.wallpaperTarget; @@ -641,7 +641,7 @@ class WallpaperController { return visible; } - private boolean updateWallpaperWindowsPlacement(ReadOnlyWindowList windows, + private boolean updateWallpaperWindowsPlacement(WindowList windows, WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible) { // TODO(multidisplay): Wallpapers on main screen only. @@ -660,7 +660,7 @@ class WallpaperController { return changed; } - boolean adjustWallpaperWindows(ReadOnlyWindowList windows) { + boolean adjustWallpaperWindows(WindowList windows) { mService.mRoot.mWallpaperMayChange = false; // First find top-most window that has asked to be on top of the wallpaper; diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java index fdefcfe2d174..3a76cd4d1bde 100644 --- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java +++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java @@ -119,7 +119,7 @@ class WallpaperWindowToken extends WindowToken { } } - boolean updateWallpaperWindowsPlacement(ReadOnlyWindowList windowList, + boolean updateWallpaperWindowsPlacement(WindowList windowList, WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible, int dw, int dh, int wallpaperAnimLayerAdj) { @@ -193,7 +193,7 @@ class WallpaperWindowToken extends WindowToken { * @return The index in {@param windows} of the lowest window that is currently on screen and * not hidden by the policy. */ - private int findLowestWindowOnScreen(ReadOnlyWindowList windowList) { + private int findLowestWindowOnScreen(WindowList windowList) { final int size = windowList.size(); for (int index = 0; index < size; index++) { final WindowState win = windowList.get(index); diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 62ad21737a7e..150160c3302e 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -23,6 +23,7 @@ import android.view.animation.Animation; import java.util.Comparator; import java.util.LinkedList; import java.util.function.Consumer; +import java.util.function.Predicate; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; @@ -508,6 +509,17 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon } } + WindowState getWindow(Predicate<WindowState> callback) { + for (int i = mChildren.size() - 1; i >= 0; --i) { + final WindowState w = mChildren.get(i).getWindow(callback); + if (w != null) { + return w; + } + } + + return null; + } + /** * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than * the input container in terms of z-order. diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java index d94094ab5c1f..c06e5cc6d7ad 100644 --- a/services/core/java/com/android/server/wm/WindowLayersController.java +++ b/services/core/java/com/android/server/wm/WindowLayersController.java @@ -60,33 +60,32 @@ class WindowLayersController { private ArrayDeque<WindowState> mOnTopLauncherWindows = new ArrayDeque<>(); private WindowState mDockDivider = null; private ArrayDeque<WindowState> mReplacingWindows = new ArrayDeque<>(); + private int mCurBaseLayer; + private int mCurLayer; + private boolean mAnyLayerChanged; - final void assignWindowLayers(ReadOnlyWindowList windows) { - if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based on windows=" + windows, + final void assignWindowLayers(DisplayContent dc) { + if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based", new RuntimeException("here").fillInStackTrace()); clear(); - int curBaseLayer = 0; - int curLayer = 0; - boolean anyLayerChanged = false; - for (int i = 0, windowCount = windows.size(); i < windowCount; i++) { - final WindowState w = windows.get(i); + dc.forAllWindows((w) -> { boolean layerChanged = false; int oldLayer = w.mLayer; - if (w.mBaseLayer == curBaseLayer || w.mIsImWindow || (i > 0 && w.mIsWallpaper)) { - curLayer += WINDOW_LAYER_MULTIPLIER; + if (w.mBaseLayer == mCurBaseLayer || w.mIsImWindow) { + mCurLayer += WINDOW_LAYER_MULTIPLIER; } else { - curBaseLayer = curLayer = w.mBaseLayer; + mCurBaseLayer = mCurLayer = w.mBaseLayer; } - assignAnimLayer(w, curLayer); + assignAnimLayer(w, mCurLayer); - // TODO: Preserved old behavior of code here but not sure comparing - // oldLayer to mAnimLayer and mLayer makes sense...though the - // worst case would be unintentional layer reassignment. + // TODO: Preserved old behavior of code here but not sure comparing oldLayer to + // mAnimLayer and mLayer makes sense...though the worst case would be unintentional + // layer reassignment. if (w.mLayer != oldLayer || w.mWinAnimator.mAnimLayer != oldLayer) { layerChanged = true; - anyLayerChanged = true; + mAnyLayerChanged = true; } if (w.mAppToken != null) { @@ -98,28 +97,27 @@ class WindowLayersController { if (layerChanged) { w.scheduleAnimationIfDimming(); } - } + }, false /* traverseTopToBottom */); adjustSpecialWindows(); //TODO (multidisplay): Magnification is supported only for the default display. - if (mService.mAccessibilityController != null && anyLayerChanged - && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { + if (mService.mAccessibilityController != null && mAnyLayerChanged + && dc.getDisplayId() == Display.DEFAULT_DISPLAY) { mService.mAccessibilityController.onWindowLayersChangedLocked(); } - if (DEBUG_LAYERS) logDebugLayers(windows); + if (DEBUG_LAYERS) logDebugLayers(dc); } - private void logDebugLayers(ReadOnlyWindowList windows) { - for (int i = 0, n = windows.size(); i < n; i++) { - final WindowState w = windows.get(i); + private void logDebugLayers(DisplayContent dc) { + dc.forAllWindows((w) -> { final WindowStateAnimator winAnimator = w.mWinAnimator; Slog.v(TAG_WM, "Assign layer " + w + ": " + "mBase=" + w.mBaseLayer + " mLayer=" + w.mLayer + (w.mAppToken == null ? "" : " mAppLayer=" + w.mAppToken.mAppAnimator.animLayerAdjustment) + " =mAnimLayer=" + winAnimator.mAnimLayer); - } + }, false /* traverseTopToBottom */); } private void clear() { @@ -130,6 +128,10 @@ class WindowLayersController { mOnTopLauncherWindows.clear(); mReplacingWindows.clear(); mDockDivider = null; + + mCurBaseLayer = 0; + mCurLayer = 0; + mAnyLayerChanged = false; } private void collectSpecialWindows(WindowState w) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 5c9dc10f31de..c4c4bcd7da0f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4787,37 +4787,42 @@ public class WindowManagerService extends IWindowManager.Stub return false; } - final DisplayContent displayContent = mRoot.getDisplayContent(displayId); - final ReadOnlyWindowList windows = displayContent.getReadOnlyWindowList(); + final DisplayContent dc = mRoot.getDisplayContent(displayId); final int oldRotation = mRotation; int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation); - boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, rotation); + final boolean rotateSeamlessly; - if (rotateSeamlessly) { - for (int i = windows.size() - 1; i >= 0; i--) { - WindowState w = windows.get(i); + if (mPolicy.shouldRotateSeamlessly(oldRotation, rotation)) { + final WindowState seamlessRotated = dc.getWindow((w) -> w.mSeamlesslyRotated); + if (seamlessRotated != null) { // We can't rotate (seamlessly or not) while waiting for the last seamless rotation // to complete (that is, waiting for windows to redraw). It's tempting to check - // w.mSeamlessRotationCount but that could be incorrect in the case of window-removal. - if (w.mSeamlesslyRotated) { - return false; - } - // In what can only be called an unfortunate workaround we require - // seamlessly rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE - // flag. Due to limitations in the client API, there is no way for - // the client to set this flag in a race free fashion. If we seamlessly rotate - // a window which does not have this flag, but then gains it, we will get - // an incorrect visual result (rotated viewfinder). This means if we want to - // support seamlessly rotating windows which could gain this flag, we can't - // rotate windows without it. This limits seamless rotation in N to camera framework - // users, windows without children, and native code. This is unfortunate but - // having the camera work is our primary goal. - if (w.isChildWindow() & w.isVisibleNow() && - !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()) { - rotateSeamlessly = false; - } + // w.mSeamlessRotationCount but that could be incorrect in the case of + // window-removal. + return false; + } + + final WindowState cantSeamlesslyRotate = dc.getWindow((w) -> + w.isChildWindow() && w.isVisibleNow() + && !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()); + if (cantSeamlesslyRotate != null) { + // In what can only be called an unfortunate workaround we require seamlessly + // rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE flag. Due to + // limitations in the client API, there is no way for the client to set this flag in + // a race free fashion. If we seamlessly rotate a window which does not have this + // flag, but then gains it, we will get an incorrect visual result + // (rotated viewfinder). This means if we want to support seamlessly rotating + // windows which could gain this flag, we can't rotate windows without it. This + // limits seamless rotation in N to camera framework users, windows without + // children, and native code. This is unfortunate but having the camera work is our + // primary goal. + rotateSeamlessly = false; + } else { + rotateSeamlessly = true; } + } else { + rotateSeamlessly = false; } // TODO: Implement forced rotation changes. @@ -4849,9 +4854,9 @@ public class WindowManagerService extends IWindowManager.Stub mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); mWaitingForConfig = true; - displayContent.setLayoutNeeded(); + dc.setLayoutNeeded(); final int[] anim = new int[2]; - if (displayContent.isDimming()) { + if (dc.isDimming()) { anim[0] = anim[1] = 0; } else { mPolicy.selectRotationAnimationLw(anim); @@ -4860,8 +4865,7 @@ public class WindowManagerService extends IWindowManager.Stub if (!rotateSeamlessly) { startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); // startFreezingDisplayLocked can reset the ScreenRotationAnimation. - screenRotationAnimation = - mAnimator.getScreenRotationAnimationLocked(displayId); + screenRotationAnimation = mAnimator.getScreenRotationAnimationLocked(displayId); } else { // The screen rotation animation uses a screenshot to freeze the screen // while windows resize underneath. @@ -4879,9 +4883,9 @@ public class WindowManagerService extends IWindowManager.Stub // the top of the method, the caller is obligated to call computeNewConfigurationLocked(). // By updating the Display info here it will be available to // computeScreenConfigurationLocked later. - updateDisplayAndOrientationLocked(displayContent.getConfiguration().uiMode, displayId); + updateDisplayAndOrientationLocked(dc.getConfiguration().uiMode, displayId); - final DisplayInfo displayInfo = displayContent.getDisplayInfo(); + final DisplayInfo displayInfo = dc.getDisplayInfo(); if (!inTransaction) { if (SHOW_TRANSACTIONS) { Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked"); @@ -4902,10 +4906,9 @@ public class WindowManagerService extends IWindowManager.Stub } if (rotateSeamlessly) { - for (int i = windows.size() - 1; i >= 0; i--) { - WindowState w = windows.get(i); - w.mWinAnimator.seamlesslyRotateWindow(oldRotation, mRotation); - } + dc.forAllWindows((w) -> + w.mWinAnimator.seamlesslyRotateWindow(oldRotation, mRotation), + true /* traverseTopToBottom */); } mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); @@ -4918,8 +4921,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - for (int i = windows.size() - 1; i >= 0; i--) { - WindowState w = windows.get(i); + dc.forAllWindows((w) -> { // Discard surface after orientation change, these can't be reused. if (w.mAppToken != null) { w.mAppToken.destroySavedSurfaces(); @@ -4930,7 +4932,8 @@ public class WindowManagerService extends IWindowManager.Stub mRoot.mOrientationChangeComplete = false; w.mLastFreezeDuration = 0; } - } + + }, true /* traverseTopToBottom */); if (rotateSeamlessly) { mH.removeMessages(H.SEAMLESS_ROTATION_TIMEOUT); @@ -4948,7 +4951,7 @@ public class WindowManagerService extends IWindowManager.Stub // Announce rotation only if we will not animate as we already have the // windows in final state. Otherwise, we make this call at the rotation end. if (screenRotationAnimation == null && mAccessibilityController != null - && displayContent.getDisplayId() == DEFAULT_DISPLAY) { + && dc.getDisplayId() == DEFAULT_DISPLAY) { mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); } @@ -5181,7 +5184,7 @@ public class WindowManagerService extends IWindowManager.Stub final WindowList windows = new WindowList(); synchronized (mWindowMap) { - mRoot.getWindows(windows); + mRoot.forAllWindows(windows::add, false /* traverseTopToBottom */); } BufferedWriter out = null; @@ -5408,7 +5411,7 @@ public class WindowManagerService extends IWindowManager.Stub } synchronized (mWindowMap) { - return mRoot.findWindow(hashCode); + return mRoot.getWindow((w) -> System.identityHashCode(w) == hashCode); } } @@ -8091,7 +8094,12 @@ public class WindowManagerService extends IWindowManager.Stub mRoot.dumpDisplayContents(pw); } - mRoot.getWindows(windows, visibleOnly, appsOnly); + mRoot.forAllWindows((w) -> { + if ((!visibleOnly || w.mWinAnimator.getShown()) + && (!appsOnly || w.mAppToken != null)) { + windows.add(w); + } + }, true /* traverseTopToBottom */); } } else { synchronized(mWindowMap) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 1a5651853818..5e65aec28c40 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -60,6 +60,7 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.LinkedList; import java.util.function.Consumer; +import java.util.function.Predicate; import static android.app.ActivityManager.StackId; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; @@ -138,52 +139,6 @@ import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; class WindowList extends ArrayList<WindowState> { - - /** - * Read-only interface for the window list that the creator of the window list can pass-out to - * other users to prevent them from modifying the window list. - */ - private ReadOnlyWindowList mReadOnly; - - WindowList() { - mReadOnly = new ReadOnlyWindowList(this); - } - - /** Returns the read-only interface for this window list. */ - ReadOnlyWindowList getReadOnly() { - return mReadOnly; - } -} - -/** - * Read-only interface for a list of windows. It is common for the owner of a list of windows to - * want to provide a way for external classes to iterate of its windows, but prevent them from - * modifying the list in any way. This call provides a way for them to do that by wrapping the - * original window list and only exposing the read-only APIs. - */ -final class ReadOnlyWindowList { - // List of windows this read-only class is tied to. - private final WindowList mWindows; - - ReadOnlyWindowList(WindowList windows) { - mWindows = windows; - } - - WindowState get(int index) { - return mWindows.get(index); - } - - int indexOf(WindowState w) { - return mWindows.indexOf(w); - } - - int size() { - return mWindows.size(); - } - - boolean isEmpty() { - return mWindows.isEmpty(); - } } /** A window in the window manager. */ @@ -3949,6 +3904,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } + WindowState getWindow(Predicate<WindowState> callback) { + if (callback.test(this)) { + return this; + } + return super.getWindow(callback); + } + boolean isWindowAnimationSet() { if (mWinAnimator.isWindowAnimationSet()) { return true; |