Removed used of DisplayContent.getReadOnlyWindowList()

Changed the call points to use DisplayContent.forAllWindows() to
get windows on the display.

Test: Existing tests pass.
Change-Id: I6f8bf15ba246fac69c4a496ebb1d9e0b9b6a95a2
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 869e207..49ffa22 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 @@
 
             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 @@
 
         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 6a625f4..ff39853 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 @@
 
     /** 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 @@
         }
     }
 
-    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 6326148..c56f6b8 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 @@
     }
 
     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 d52168c..4d195e8 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 @@
             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 299fa05..88986e3 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 @@
         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 @@
             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 @@
     }
 
     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 @@
                 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 @@
     }
 
     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 178fbe7..d3e8e8e 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 @@
         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 @@
 
     /** 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 @@
         return true;
     }
 
-    private boolean updateWallpaperWindowsTargetByLayer(ReadOnlyWindowList windows,
+    private boolean updateWallpaperWindowsTargetByLayer(WindowList windows,
             FindWallpaperTargetResult result) {
 
         WindowState wallpaperTarget = result.wallpaperTarget;
@@ -641,7 +641,7 @@
         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 @@
         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 fdefcfe..3a76cd4 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 @@
         }
     }
 
-    boolean updateWallpaperWindowsPlacement(ReadOnlyWindowList windowList,
+    boolean updateWallpaperWindowsPlacement(WindowList windowList,
             WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible, int dw, int dh,
             int wallpaperAnimLayerAdj) {
 
@@ -193,7 +193,7 @@
      * @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 62ad217..150160c 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 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 @@
         }
     }
 
+    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 d94094a..c06e5cc 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 @@
     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 @@
             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 @@
         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 8486e52..a7ac35e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4747,37 +4747,42 @@
             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.
@@ -4809,9 +4814,9 @@
         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);
@@ -4820,8 +4825,7 @@
         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.
@@ -4839,9 +4843,9 @@
         // 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");
@@ -4862,10 +4866,9 @@
             }
 
             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();
@@ -4878,8 +4881,7 @@
             }
         }
 
-        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();
@@ -4890,7 +4892,8 @@
                 mRoot.mOrientationChangeComplete = false;
                 w.mLastFreezeDuration = 0;
             }
-        }
+
+        }, true /* traverseTopToBottom */);
 
         if (rotateSeamlessly) {
             mH.removeMessages(H.SEAMLESS_ROTATION_TIMEOUT);
@@ -4908,7 +4911,7 @@
         // 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);
         }
@@ -5141,7 +5144,7 @@
 
         final WindowList windows = new WindowList();
         synchronized (mWindowMap) {
-            mRoot.getWindows(windows);
+            mRoot.forAllWindows(windows::add, false /* traverseTopToBottom */);
         }
 
         BufferedWriter out = null;
@@ -5368,7 +5371,7 @@
         }
 
         synchronized (mWindowMap) {
-            return mRoot.findWindow(hashCode);
+            return mRoot.getWindow((w) -> System.identityHashCode(w) == hashCode);
         }
     }
 
@@ -8051,7 +8054,12 @@
                     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 1a56518..5e65aec 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.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.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 @@
         }
     }
 
+    WindowState getWindow(Predicate<WindowState> callback) {
+        if (callback.test(this)) {
+            return this;
+        }
+        return super.getWindow(callback);
+    }
+
     boolean isWindowAnimationSet() {
         if (mWinAnimator.isWindowAnimationSet()) {
             return true;