Have forAllWindows return IME windows in order with IME target

If there is an IME target make sure to return the IME windows next
to the IME target when processing WindowContainer.forAllWindows().
Several users of forAllWindows are expecting this to be the cases so
it is close to the visual order.

Test: bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
Test: bit FrameworksServicesTests:com.android.server.wm.WindowLayersControllerTests
Change-Id: I737f88ca607ab2694391419d0d38060c03b53840
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 18568ba4..79d58a3 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -457,6 +457,43 @@
     }
 
     @Override
+    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
+        // Special handling so we can process IME windows with #forAllImeWindows above their IME
+        // target, or here in order if there isn't an IME target.
+        if (traverseTopToBottom) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                final DisplayChildWindowContainer child = mChildren.get(i);
+                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
+                    // In this case the Ime windows will be processed above their target so we skip
+                    // here.
+                    continue;
+                }
+                if (child.forAllWindows(callback, traverseTopToBottom)) {
+                    return true;
+                }
+            }
+        } else {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                final DisplayChildWindowContainer child = mChildren.get(i);
+                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
+                    // In this case the Ime windows will be processed above their target so we skip
+                    // here.
+                    continue;
+                }
+                if (child.forAllWindows(callback, traverseTopToBottom)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
+        return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
+    }
+
+    @Override
     int getOrientation() {
         final WindowManagerPolicy policy = mService.mPolicy;
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2ee1e18..1b5e817 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3251,7 +3251,7 @@
                     pw.print(mPolicyVisibilityAfterAnim);
                     pw.print(" mAppOpVisibility=");
                     pw.print(mAppOpVisibility);
-                    pw.print(" parentHidden="); pw.println(isParentWindowHidden());
+                    pw.print(" parentHidden="); pw.print(isParentWindowHidden());
                     pw.print(" mPermanentlyHidden="); pw.println(mPermanentlyHidden);
         }
         if (!mRelayoutCalled || mLayoutNeeded) {
@@ -3837,7 +3837,7 @@
     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
         if (mChildren.isEmpty()) {
             // The window has no children so we just return it.
-            return callback.apply(this);
+            return applyInOrderWithImeWindows(callback, traverseTopToBottom);
         }
 
         if (traverseTopToBottom) {
@@ -3866,7 +3866,7 @@
             child = mChildren.get(i);
         }
 
-        if (callback.apply(this)) {
+        if (applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
             return true;
         }
 
@@ -3902,7 +3902,7 @@
             child = mChildren.get(i);
         }
 
-        if (callback.apply(this)) {
+        if (applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
             return true;
         }
 
@@ -3920,6 +3920,35 @@
         return false;
     }
 
+    private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback,
+            boolean traverseTopToBottom) {
+        if (traverseTopToBottom) {
+            if (mService.mInputMethodTarget == this) {
+                // This window is the current IME target, so we need to process the IME windows
+                // directly above it.
+                if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
+                    return true;
+                }
+            }
+            if (callback.apply(this)) {
+                return true;
+            }
+        } else {
+            if (callback.apply(this)) {
+                return true;
+            }
+            if (mService.mInputMethodTarget == this) {
+                // This window is the current IME target, so we need to process the IME windows
+                // directly above it.
+                if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
     WindowState getWindow(Predicate<WindowState> callback) {
         if (callback.test(this)) {
             return this;