Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34247958 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Fixed issues with child windows been IME targets

- Fixed issue with WindowState.getWindow() returning the parent window before
its children with positive sub-layers. Positive sub-layer children should be
returned first, then the parent window, and then negative sub-layer children.
This was causing the the parent window to be selected as the IME target
instead of the child on-top of it since they both can be IME targets and the
parent window was returned first.
- Fixed issue with WindowState.forAllWindow() not returning the IME window if
the current IME target is a child window.
- Add test WindowStateTest.testGetWindow(),
DisplayContentTests.testForAllWindows_WithChildWindowImeTarget(), and
DisplayContentTests.testComputeImeTarget() to cover the failing cases.

Change-Id: I0c93e0344601fc870011e8a8d84528f62b0a2a06
Fixes: 34786357
Fixes: 34306127
Fixes: 34711958
Fixes: 35362942
Test: bit FrameworksServicesTests:com.android.server.wm.WindowStateTests
Test: bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
parent cd52950a
Loading
Loading
Loading
Loading
+40 −7
Original line number Original line Diff line number Diff line
@@ -3876,7 +3876,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }
    }


    private boolean forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback) {
    private boolean forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback) {
        // We want to consumer the negative sublayer children first because they need to appear
        // We want to consume the negative sublayer children first because they need to appear
        // below the parent, then this window (the parent), and then the positive sublayer children
        // below the parent, then this window (the parent), and then the positive sublayer children
        // because they need to appear above the parent.
        // because they need to appear above the parent.
        int i = 0;
        int i = 0;
@@ -3884,7 +3884,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        WindowState child = mChildren.get(i);
        WindowState child = mChildren.get(i);


        while (i < count && child.mSubLayer < 0) {
        while (i < count && child.mSubLayer < 0) {
            if (callback.apply(child)) {
            if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
                return true;
                return true;
            }
            }
            i++;
            i++;
@@ -3899,7 +3899,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        }
        }


        while (i < count) {
        while (i < count) {
            if (callback.apply(child)) {
            if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
                return true;
                return true;
            }
            }
            i++;
            i++;
@@ -3913,14 +3913,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }
    }


    private boolean forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback) {
    private boolean forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback) {
        // We want to consumer the positive sublayer children first because they need to appear
        // We want to consume the positive sublayer children first because they need to appear
        // above the parent, then this window (the parent), and then the negative sublayer children
        // above the parent, then this window (the parent), and then the negative sublayer children
        // because they need to appear above the parent.
        // because they need to appear above the parent.
        int i = mChildren.size() - 1;
        int i = mChildren.size() - 1;
        WindowState child = mChildren.get(i);
        WindowState child = mChildren.get(i);


        while (i >= 0 && child.mSubLayer >= 0) {
        while (i >= 0 && child.mSubLayer >= 0) {
            if (callback.apply(child)) {
            if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
                return true;
                return true;
            }
            }
            --i;
            --i;
@@ -3935,7 +3935,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        }
        }


        while (i >= 0) {
        while (i >= 0) {
            if (callback.apply(child)) {
            if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
                return true;
                return true;
            }
            }
            --i;
            --i;
@@ -3978,10 +3978,43 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }
    }


    WindowState getWindow(Predicate<WindowState> callback) {
    WindowState getWindow(Predicate<WindowState> callback) {
        if (mChildren.isEmpty()) {
            return callback.test(this) ? this : null;
        }

        // We want to consume the positive sublayer children first because they need to appear
        // above the parent, then this window (the parent), and then the negative sublayer children
        // because they need to appear above the parent.
        int i = mChildren.size() - 1;
        WindowState child = mChildren.get(i);

        while (i >= 0 && child.mSubLayer >= 0) {
            if (callback.test(child)) {
                return child;
            }
            --i;
            if (i < 0) {
                break;
            }
            child = mChildren.get(i);
        }

        if (callback.test(this)) {
        if (callback.test(this)) {
            return this;
            return this;
        }
        }
        return super.getWindow(callback);

        while (i >= 0) {
            if (callback.test(child)) {
                return child;
            }
            --i;
            if (i < 0) {
                break;
            }
            child = mChildren.get(i);
        }

        return null;
    }
    }


    boolean isWindowAnimationSet() {
    boolean isWindowAnimationSet() {
+106 −138
Original line number Original line Diff line number Diff line
@@ -16,24 +16,25 @@


package com.android.server.wm;
package com.android.server.wm;


import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;


import android.content.res.Configuration;
import android.content.res.Configuration;
import android.hardware.display.DisplayManagerGlobal;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
import android.view.DisplayInfo;


import java.util.ArrayList;
import java.util.Arrays;

import java.util.LinkedList;
import static android.view.Display.DEFAULT_DISPLAY;
import java.util.List;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static org.junit.Assert.assertEquals;


/**
/**
 * Tests for the {@link DisplayContent} class.
 * Tests for the {@link DisplayContent} class.
@@ -54,38 +55,17 @@ public class DisplayContentTests extends WindowTestsBase {
        exitingAppToken.mIsExiting = true;
        exitingAppToken.mIsExiting = true;
        exitingAppToken.mTask.mStack.mExitingAppTokens.add(exitingAppToken);
        exitingAppToken.mTask.mStack.mExitingAppTokens.add(exitingAppToken);


        final ArrayList<WindowState> windows = new ArrayList();
        assertForAllWindowsOrder(Arrays.asList(

                sWallpaperWindow,
        // Test forward traversal.
                exitingAppWindow,
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
                sChildAppWindowBelow,

                sAppWindow,
        assertEquals(sWallpaperWindow, windows.get(0));
                sChildAppWindowAbove,
        assertEquals(exitingAppWindow, windows.get(1));
                sDockedDividerWindow,
        assertEquals(sChildAppWindowBelow, windows.get(2));
                sStatusBarWindow,
        assertEquals(sAppWindow, windows.get(3));
                sNavBarWindow,
        assertEquals(sChildAppWindowAbove, windows.get(4));
                sImeWindow,
        assertEquals(sDockedDividerWindow, windows.get(5));
                sImeDialogWindow));
        assertEquals(sStatusBarWindow, windows.get(6));
        assertEquals(sNavBarWindow, windows.get(7));
        assertEquals(sImeWindow, windows.get(8));
        assertEquals(sImeDialogWindow, windows.get(9));

        // Test backward traversal.
        windows.clear();
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(9));
        assertEquals(exitingAppWindow, windows.get(8));
        assertEquals(sChildAppWindowBelow, windows.get(7));
        assertEquals(sAppWindow, windows.get(6));
        assertEquals(sChildAppWindowAbove, windows.get(5));
        assertEquals(sDockedDividerWindow, windows.get(4));
        assertEquals(sStatusBarWindow, windows.get(3));
        assertEquals(sNavBarWindow, windows.get(2));
        assertEquals(sImeWindow, windows.get(1));
        assertEquals(sImeDialogWindow, windows.get(0));

        exitingAppWindow.removeImmediately();
    }
    }


    @Test
    @Test
@@ -95,78 +75,49 @@ public class DisplayContentTests extends WindowTestsBase {


        sWm.mInputMethodTarget = imeAppTarget;
        sWm.mInputMethodTarget = imeAppTarget;


        final ArrayList<WindowState> windows = new ArrayList();
        assertForAllWindowsOrder(Arrays.asList(

                sWallpaperWindow,
        // Test forward traversal.
                sChildAppWindowBelow,
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
                sAppWindow,

                sChildAppWindowAbove,
        assertEquals(sWallpaperWindow, windows.get(0));
                imeAppTarget,
        assertEquals(sChildAppWindowBelow, windows.get(1));
                sImeWindow,
        assertEquals(sAppWindow, windows.get(2));
                sImeDialogWindow,
        assertEquals(sChildAppWindowAbove, windows.get(3));
                sDockedDividerWindow,
        assertEquals(imeAppTarget, windows.get(4));
                sStatusBarWindow,
        assertEquals(sImeWindow, windows.get(5));
                sNavBarWindow));
        assertEquals(sImeDialogWindow, windows.get(6));
    }
        assertEquals(sDockedDividerWindow, windows.get(7));
        assertEquals(sStatusBarWindow, windows.get(8));
        assertEquals(sNavBarWindow, windows.get(9));


        // Test backward traversal.
    @Test
        windows.clear();
    public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
        sWm.mInputMethodTarget = sChildAppWindowAbove;


        assertEquals(sWallpaperWindow, windows.get(9));
        assertForAllWindowsOrder(Arrays.asList(
        assertEquals(sChildAppWindowBelow, windows.get(8));
                sWallpaperWindow,
        assertEquals(sAppWindow, windows.get(7));
                sChildAppWindowBelow,
        assertEquals(sChildAppWindowAbove, windows.get(6));
                sAppWindow,
        assertEquals(imeAppTarget, windows.get(5));
                sChildAppWindowAbove,
        assertEquals(sImeWindow, windows.get(4));
                sImeWindow,
        assertEquals(sImeDialogWindow, windows.get(3));
                sImeDialogWindow,
        assertEquals(sDockedDividerWindow, windows.get(2));
                sDockedDividerWindow,
        assertEquals(sStatusBarWindow, windows.get(1));
                sStatusBarWindow,
        assertEquals(sNavBarWindow, windows.get(0));
                sNavBarWindow));

        // Clean-up
        sWm.mInputMethodTarget = null;
        imeAppTarget.removeImmediately();
    }
    }


    @Test
    @Test
    public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
    public void testForAllWindows_WithStatusBarImeTarget() throws Exception {

        sWm.mInputMethodTarget = sStatusBarWindow;
        sWm.mInputMethodTarget = sStatusBarWindow;


        final ArrayList<WindowState> windows = new ArrayList();
        assertForAllWindowsOrder(Arrays.asList(

                sWallpaperWindow,
        // Test forward traversal.
                sChildAppWindowBelow,
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
                sAppWindow,

                sChildAppWindowAbove,
        assertEquals(sWallpaperWindow, windows.get(0));
                sDockedDividerWindow,
        assertEquals(sChildAppWindowBelow, windows.get(1));
                sStatusBarWindow,
        assertEquals(sAppWindow, windows.get(2));
                sImeWindow,
        assertEquals(sChildAppWindowAbove, windows.get(3));
                sImeDialogWindow,
        assertEquals(sDockedDividerWindow, windows.get(4));
                sNavBarWindow));
        assertEquals(sStatusBarWindow, windows.get(5));
        assertEquals(sImeWindow, windows.get(6));
        assertEquals(sImeDialogWindow, windows.get(7));
        assertEquals(sNavBarWindow, windows.get(8));

        // Test backward traversal.
        windows.clear();
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(8));
        assertEquals(sChildAppWindowBelow, windows.get(7));
        assertEquals(sAppWindow, windows.get(6));
        assertEquals(sChildAppWindowAbove, windows.get(5));
        assertEquals(sDockedDividerWindow, windows.get(4));
        assertEquals(sStatusBarWindow, windows.get(3));
        assertEquals(sImeWindow, windows.get(2));
        assertEquals(sImeDialogWindow, windows.get(1));
        assertEquals(sNavBarWindow, windows.get(0));

        // Clean-up
        sWm.mInputMethodTarget = null;
    }
    }


    @Test
    @Test
@@ -176,38 +127,35 @@ public class DisplayContentTests extends WindowTestsBase {
        final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
        final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
                sDisplayContent, "voiceInteractionWindow");
                sDisplayContent, "voiceInteractionWindow");


        final ArrayList<WindowState> windows = new ArrayList();
        assertForAllWindowsOrder(Arrays.asList(

                sWallpaperWindow,
        // Test forward traversal.
                sChildAppWindowBelow,
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
                sAppWindow,

                sChildAppWindowAbove,
        assertEquals(sWallpaperWindow, windows.get(0));
                sDockedDividerWindow,
        assertEquals(sChildAppWindowBelow, windows.get(1));
                voiceInteractionWindow,
        assertEquals(sAppWindow, windows.get(2));
                sStatusBarWindow,
        assertEquals(sChildAppWindowAbove, windows.get(3));
                sNavBarWindow,
        assertEquals(sDockedDividerWindow, windows.get(4));
                sImeWindow,
        assertEquals(voiceInteractionWindow, windows.get(5));
                sImeDialogWindow));
        assertEquals(sStatusBarWindow, windows.get(6));
    }
        assertEquals(sNavBarWindow, windows.get(7));
        assertEquals(sImeWindow, windows.get(8));
        assertEquals(sImeDialogWindow, windows.get(9));


        // Test backward traversal.
    @Test
        windows.clear();
    public void testComputeImeTarget() throws Exception {
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
        // Verify that an app window can be an ime target.

        final WindowState appWin = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin");
        assertEquals(sWallpaperWindow, windows.get(9));
        appWin.setHasSurface(true);
        assertEquals(sChildAppWindowBelow, windows.get(8));
        assertTrue(appWin.canBeImeTarget());
        assertEquals(sAppWindow, windows.get(7));
        WindowState imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
        assertEquals(sChildAppWindowAbove, windows.get(6));
        assertEquals(appWin, imeTarget);
        assertEquals(sDockedDividerWindow, windows.get(5));

        assertEquals(voiceInteractionWindow, windows.get(4));
        // Verify that an child window can be an ime target.
        assertEquals(sStatusBarWindow, windows.get(3));
        final WindowState childWin = createWindow(appWin,
        assertEquals(sNavBarWindow, windows.get(2));
                TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
        assertEquals(sImeWindow, windows.get(1));
        childWin.setHasSurface(true);
        assertEquals(sImeDialogWindow, windows.get(0));
        assertTrue(childWin.canBeImeTarget());

        imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
        voiceInteractionWindow.removeImmediately();
        assertEquals(childWin, imeTarget);
    }
    }


    /**
    /**
@@ -284,4 +232,24 @@ public class DisplayContentTests extends WindowTestsBase {
        assertEquals(currentOverrideConfig.densityDpi, globalConfig.densityDpi);
        assertEquals(currentOverrideConfig.densityDpi, globalConfig.densityDpi);
        assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
        assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
    }
    }

    private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
        final LinkedList<WindowState> actualWindows = new LinkedList();

        // Test forward traversal.
        sDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
        assertEquals(expectedWindows.size(), actualWindows.size());
        for (WindowState w : expectedWindows) {
            assertEquals(w, actualWindows.pollFirst());
        }
        assertTrue(actualWindows.isEmpty());

        // Test backward traversal.
        sDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
        assertEquals(expectedWindows.size(), actualWindows.size());
        for (WindowState w : expectedWindows) {
            assertEquals(w, actualWindows.pollLast());
        }
        assertTrue(actualWindows.isEmpty());
    }
}
}
+37 −0
Original line number Original line Diff line number Diff line
@@ -23,10 +23,17 @@ import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.runner.AndroidJUnit4;


import java.util.LinkedList;

import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
@@ -167,4 +174,34 @@ public class WindowStateTests extends WindowTestsBase {
        assertFalse(appWindow.canBeImeTarget());
        assertFalse(appWindow.canBeImeTarget());
        assertFalse(imeWindow.canBeImeTarget());
        assertFalse(imeWindow.canBeImeTarget());
    }
    }

    @Test
    public void testGetWindow() throws Exception {
        final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
        final WindowState mediaChild = createWindow(root, TYPE_APPLICATION_MEDIA, "mediaChild");
        final WindowState mediaOverlayChild = createWindow(root,
                TYPE_APPLICATION_MEDIA_OVERLAY, "mediaOverlayChild");
        final WindowState attachedDialogChild = createWindow(root,
                TYPE_APPLICATION_ATTACHED_DIALOG, "attachedDialogChild");
        final WindowState subPanelChild = createWindow(root,
                TYPE_APPLICATION_SUB_PANEL, "subPanelChild");
        final WindowState aboveSubPanelChild = createWindow(root,
                TYPE_APPLICATION_ABOVE_SUB_PANEL, "aboveSubPanelChild");

        final LinkedList<WindowState> windows = new LinkedList();

        root.getWindow(w -> {
            windows.addLast(w);
            return false;
        });

        // getWindow should have returned candidate windows in z-order.
        assertEquals(aboveSubPanelChild, windows.pollFirst());
        assertEquals(subPanelChild, windows.pollFirst());
        assertEquals(attachedDialogChild, windows.pollFirst());
        assertEquals(root, windows.pollFirst());
        assertEquals(mediaOverlayChild, windows.pollFirst());
        assertEquals(mediaChild, windows.pollFirst());
        assertTrue(windows.isEmpty());
    }
}
}
+13 −1
Original line number Original line Diff line number Diff line
@@ -44,6 +44,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.EMPTY;
import static android.content.res.Configuration.EMPTY;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
@@ -60,6 +61,7 @@ import static org.mockito.Mockito.mock;
import com.android.server.AttributeCache;
import com.android.server.AttributeCache;


import java.util.HashSet;
import java.util.HashSet;
import java.util.LinkedList;


/**
/**
 * Common base class for window manager unit test classes.
 * Common base class for window manager unit test classes.
@@ -120,6 +122,7 @@ class WindowTestsBase {
        sCommonWindows = new HashSet();
        sCommonWindows = new HashSet();
        sWallpaperWindow = createCommonWindow(null, TYPE_WALLPAPER, "wallpaperWindow");
        sWallpaperWindow = createCommonWindow(null, TYPE_WALLPAPER, "wallpaperWindow");
        sImeWindow = createCommonWindow(null, TYPE_INPUT_METHOD, "sImeWindow");
        sImeWindow = createCommonWindow(null, TYPE_INPUT_METHOD, "sImeWindow");
        sWm.mInputMethodWindow = sImeWindow;
        sImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG, "sImeDialogWindow");
        sImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG, "sImeDialogWindow");
        sStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "sStatusBarWindow");
        sStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "sStatusBarWindow");
        sNavBarWindow = createCommonWindow(null, TYPE_NAVIGATION_BAR, "sNavBarWindow");
        sNavBarWindow = createCommonWindow(null, TYPE_NAVIGATION_BAR, "sNavBarWindow");
@@ -133,16 +136,25 @@ class WindowTestsBase {


    @After
    @After
    public void tearDown() throws Exception {
    public void tearDown() throws Exception {
        final LinkedList<WindowState> nonCommonWindows = new LinkedList();
        sWm.mRoot.forAllWindows(w -> {
        sWm.mRoot.forAllWindows(w -> {
            if (!sCommonWindows.contains(w)) {
            if (!sCommonWindows.contains(w)) {
                w.removeImmediately();
                nonCommonWindows.addLast(w);
            }
            }
        }, true /* traverseTopToBottom */);
        }, true /* traverseTopToBottom */);

        while (!nonCommonWindows.isEmpty()) {
            nonCommonWindows.pollLast().removeImmediately();
        }

        sWm.mInputMethodTarget = null;
    }
    }


    private static WindowState createCommonWindow(WindowState parent, int type, String name) {
    private static WindowState createCommonWindow(WindowState parent, int type, String name) {
        final WindowState win = createWindow(parent, type, name);
        final WindowState win = createWindow(parent, type, name);
        sCommonWindows.add(win);
        sCommonWindows.add(win);
        // Prevent common windows from been IMe targets
        win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
        return win;
        return win;
    }
    }