Loading services/core/java/com/android/server/wm/WindowState.java +40 −7 Original line number Original line Diff line number Diff line Loading @@ -3889,7 +3889,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; Loading @@ -3897,7 +3897,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++; Loading @@ -3912,7 +3912,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++; Loading @@ -3926,14 +3926,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; Loading @@ -3948,7 +3948,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; Loading Loading @@ -3991,10 +3991,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() { Loading services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +106 −138 Original line number Original line Diff line number Diff line Loading @@ -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. Loading @@ -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 Loading @@ -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 Loading @@ -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); } } /** /** Loading Loading @@ -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()); } } } services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java +37 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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()); } } } services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java +13 −1 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading Loading @@ -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"); Loading @@ -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; } } Loading Loading
services/core/java/com/android/server/wm/WindowState.java +40 −7 Original line number Original line Diff line number Diff line Loading @@ -3889,7 +3889,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; Loading @@ -3897,7 +3897,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++; Loading @@ -3912,7 +3912,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++; Loading @@ -3926,14 +3926,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; Loading @@ -3948,7 +3948,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; Loading Loading @@ -3991,10 +3991,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() { Loading
services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +106 −138 Original line number Original line Diff line number Diff line Loading @@ -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. Loading @@ -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 Loading @@ -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 Loading @@ -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); } } /** /** Loading Loading @@ -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()); } } }
services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java +37 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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()); } } }
services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java +13 −1 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading Loading @@ -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"); Loading @@ -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; } } Loading