Traverse window hierarchy without window list

Added support for to get all windows in the hierarchy without needing
to use WindowList concept which is a very complicated implementation
in the code base.
This implementation walks the hierarchy node by node returns windows
in order to the caller using a callback.

Test: bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
Change-Id: I2719f7c96f26dad23f91c1c589be88712bd224b8
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ec4cdf2..3ff0e7a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -140,6 +140,7 @@
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.function.Consumer;
 
 /**
  * Utility class for keeping track of the WindowStates and other pertinent contents of a
@@ -3243,6 +3244,42 @@
         }
 
         @Override
+        void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
+            if (traverseTopToBottom) {
+                super.forAllWindows(callback, traverseTopToBottom);
+                forAllExitingAppTokenWindows(callback, traverseTopToBottom);
+            } else {
+                forAllExitingAppTokenWindows(callback, traverseTopToBottom);
+                super.forAllWindows(callback, traverseTopToBottom);
+            }
+        }
+
+        private void forAllExitingAppTokenWindows(Consumer<WindowState> callback,
+                boolean traverseTopToBottom) {
+            // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
+            // app tokens.
+            // TODO: Investigate if we need to continue to do this or if we can just process them
+            // in-order.
+            if (traverseTopToBottom) {
+                for (int i = mChildren.size() - 1; i >= 0; --i) {
+                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
+                    for (int j = appTokens.size() - 1; j >= 0; --j) {
+                        appTokens.get(j).forAllWindowsUnchecked(callback, traverseTopToBottom);
+                    }
+                }
+            } else {
+                final int count = mChildren.size();
+                for (int i = 0; i < count; ++i) {
+                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
+                    final int appTokensCount = appTokens.size();
+                    for (int j = 0; j < appTokensCount; j++) {
+                        appTokens.get(j).forAllWindowsUnchecked(callback, traverseTopToBottom);
+                    }
+                }
+            }
+        }
+
+        @Override
         int getOrientation() {
             if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
                     || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {