Loading services/core/java/com/android/server/wm/AppWindowToken.java +28 −0 Original line number Diff line number Diff line Loading @@ -676,6 +676,34 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mPendingRelaunchCount = 0; } /** * Returns true if the new child window we are adding to this token is considered greater than * the existing child window in this token in terms of z-order. */ @Override protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow, WindowState existingWindow) { final int type1 = newWindow.mAttrs.type; final int type2 = existingWindow.mAttrs.type; // Base application windows should be z-ordered BELOW all other windows in the app token. if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) { return false; } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) { return true; } // Starting windows should be z-ordered ABOVE all other windows in the app token. if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) { return true; } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) { return false; } // Otherwise the new window is greater than the existing window. return true; } @Override void addWindow(WindowState w) { super.addWindow(w); Loading services/core/java/com/android/server/wm/DisplayContent.java +6 −16 Original line number Diff line number Diff line Loading @@ -1085,12 +1085,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return null; } int addAppWindowToWindowList(final WindowState win) { void addAppWindowToWindowList(final WindowState win) { final IWindow client = win.mClient; WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken); if (!tokenWindowList.isEmpty()) { return addAppWindowExisting(win, tokenWindowList); addAppWindowExisting(win, tokenWindowList); return; } // No windows from this token on this display Loading Loading @@ -1128,7 +1129,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } addWindowToListBefore(win, pos); return 0; return; } // Continue looking down until we find the first token that has windows on this display. Loading @@ -1154,7 +1155,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } addWindowToListAfter(win, pos); return 0; return; } // Just search for the start of this layer. Loading @@ -1175,7 +1176,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo + mWindows.size()); mWindows.add(i + 1, win); mService.mWindowsChanged = true; return 0; } /** Adds this non-app window to the window list. */ Loading Loading @@ -1778,23 +1778,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mLayoutNeeded; } private int addAppWindowExisting(WindowState win, WindowList tokenWindowList) { private void addAppWindowExisting(WindowState win, WindowList tokenWindowList) { int tokenWindowsPos; // If this application has existing windows, we simply place the new window on top of // them... but keep the starting window on top. if (win.mAttrs.type == TYPE_BASE_APPLICATION) { // Base windows go behind everything else. final WindowState lowestWindow = tokenWindowList.get(0); addWindowToListBefore(win, lowestWindow); tokenWindowsPos = win.mToken.getWindowIndex(lowestWindow); } else { final AppWindowToken atoken = win.mAppToken; final int windowListPos = tokenWindowList.size(); final WindowState lastWindow = tokenWindowList.get(windowListPos - 1); if (atoken != null && lastWindow == atoken.startingWindow) { addWindowToListBefore(win, lastWindow); tokenWindowsPos = win.mToken.getWindowIndex(lastWindow); } else { int newIdx = findIdxBasedOnAppTokens(win); // There is a window above this one associated with the same apptoken note that the Loading @@ -1804,16 +1801,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + mWindows.size()); mWindows.add(newIdx + 1, win); if (newIdx < 0) { // No window from token found on win's display. tokenWindowsPos = 0; } else { tokenWindowsPos = win.mToken.getWindowIndex(mWindows.get(newIdx)) + 1; } mService.mWindowsChanged = true; } } return tokenWindowsPos; } /** Places the first input window after the second input window in the window list. */ Loading services/core/java/com/android/server/wm/WindowToken.java +37 −4 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.util.Slog; import android.view.DisplayInfo; import java.io.PrintWriter; import java.util.Comparator; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; Loading Loading @@ -82,6 +83,26 @@ class WindowToken extends WindowContainer<WindowState> { // The display this token is on. private DisplayContent mDisplayContent; /** * Compares two child window of this token and returns -1 if the first is lesser than the * second in terms of z-order and 1 otherwise. */ private final Comparator<WindowState> mWindowComparator = (WindowState newWindow, WindowState existingWindow) -> { final WindowToken token = WindowToken.this; if (newWindow.mToken != token) { throw new IllegalArgumentException("newWindow=" + newWindow + " is not a child of token=" + token); } if (existingWindow.mToken != token) { throw new IllegalArgumentException("existingWindow=" + existingWindow + " is not a child of token=" + token); } return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1; }; WindowToken(WindowManagerService service, IBinder _token, int type, boolean _explicit, DisplayContent dc) { mService = service; Loading Loading @@ -168,19 +189,31 @@ class WindowToken extends WindowContainer<WindowState> { return -1; } /** * Returns true if the new window is considered greater than the existing window in terms of * z-order. */ protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow, WindowState existingWindow) { // By default the first window isn't greater than the second to preserve existing logic of // how new windows are added to the token return false; } void addWindow(final WindowState win) { if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindow: win=" + win + " Callers=" + Debug.getCallers(5)); if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindow: win=" + win + " Callers=" + Debug.getCallers(5)); if (!win.isChildWindow()) { int tokenWindowsPos = 0; if (asAppWindowToken() != null) { tokenWindowsPos = mDisplayContent.addAppWindowToWindowList(win); mDisplayContent.addAppWindowToWindowList(win); } else { mDisplayContent.addNonAppWindowToWindowList(win); } if (!mChildren.contains(win)) { if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this); addChild(win, tokenWindowsPos); addChild(win, mWindowComparator); } } else { mDisplayContent.addChildWindowToWindowList(win); Loading services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java +43 −3 Original line number Diff line number Diff line Loading @@ -29,17 +29,19 @@ import android.view.IWindow; import android.view.WindowManager; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; /** * Tests for the {@link WindowState} class. * * Build: mmma -j32 frameworks/base/services/tests/servicestests * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk * Run: adb shell am instrument -w -e class com.android.server.wm.AppWindowTokenTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner * Build/Install/Run: * bit FrameworksServicesTests:com.android.server.wm.AppWindowTokenTests */ @SmallTest @Presubmit Loading @@ -55,6 +57,36 @@ public class AppWindowTokenTests { sWm = TestWindowManagerPolicy.getWindowManagerService(context); } @Test public void testAddWindow_Order() throws Exception { final TestAppWindowToken token = new TestAppWindowToken(); assertEquals(0, token.getWindowsCount()); final WindowState win1 = createWindow(null, TYPE_APPLICATION, token); final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, token); final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, token); final WindowState win4 = createWindow(null, TYPE_APPLICATION, token); token.addWindow(win1); token.addWindow(startingWin); token.addWindow(baseWin); token.addWindow(win4); // Should not contain the windows that were added above. assertEquals(4, token.getWindowsCount()); assertTrue(token.hasWindow(win1)); assertTrue(token.hasWindow(startingWin)); assertTrue(token.hasWindow(baseWin)); assertTrue(token.hasWindow(win4)); // The starting window should be on-top of all other windows. assertEquals(startingWin, token.getLastChild()); // The base application window should be below all other windows. assertEquals(baseWin, token.getFirstChild()); } @Test public void testFindMainWindow() throws Exception { final TestAppWindowToken token = new TestAppWindowToken(); Loading Loading @@ -93,5 +125,13 @@ public class AppWindowTokenTests { boolean hasWindow(WindowState w) { return mChildren.contains(w); } WindowState getFirstChild() { return mChildren.getFirst(); } WindowState getLastChild() { return mChildren.getLast(); } } } services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java +2 −3 Original line number Diff line number Diff line Loading @@ -41,9 +41,8 @@ import static org.mockito.Mockito.mock; /** * Tests for the {@link WindowState} class. * * Build: mmma -j32 frameworks/base/services/tests/servicestests * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk * Run: adb shell am instrument -w -e class com.android.server.wm.WindowTokenTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner * Build/Install/Run: * bit FrameworksServicesTests:com.android.server.wm.WindowTokenTests */ @SmallTest @Presubmit Loading Loading
services/core/java/com/android/server/wm/AppWindowToken.java +28 −0 Original line number Diff line number Diff line Loading @@ -676,6 +676,34 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mPendingRelaunchCount = 0; } /** * Returns true if the new child window we are adding to this token is considered greater than * the existing child window in this token in terms of z-order. */ @Override protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow, WindowState existingWindow) { final int type1 = newWindow.mAttrs.type; final int type2 = existingWindow.mAttrs.type; // Base application windows should be z-ordered BELOW all other windows in the app token. if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) { return false; } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) { return true; } // Starting windows should be z-ordered ABOVE all other windows in the app token. if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) { return true; } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) { return false; } // Otherwise the new window is greater than the existing window. return true; } @Override void addWindow(WindowState w) { super.addWindow(w); Loading
services/core/java/com/android/server/wm/DisplayContent.java +6 −16 Original line number Diff line number Diff line Loading @@ -1085,12 +1085,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return null; } int addAppWindowToWindowList(final WindowState win) { void addAppWindowToWindowList(final WindowState win) { final IWindow client = win.mClient; WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken); if (!tokenWindowList.isEmpty()) { return addAppWindowExisting(win, tokenWindowList); addAppWindowExisting(win, tokenWindowList); return; } // No windows from this token on this display Loading Loading @@ -1128,7 +1129,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } addWindowToListBefore(win, pos); return 0; return; } // Continue looking down until we find the first token that has windows on this display. Loading @@ -1154,7 +1155,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } addWindowToListAfter(win, pos); return 0; return; } // Just search for the start of this layer. Loading @@ -1175,7 +1176,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo + mWindows.size()); mWindows.add(i + 1, win); mService.mWindowsChanged = true; return 0; } /** Adds this non-app window to the window list. */ Loading Loading @@ -1778,23 +1778,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mLayoutNeeded; } private int addAppWindowExisting(WindowState win, WindowList tokenWindowList) { private void addAppWindowExisting(WindowState win, WindowList tokenWindowList) { int tokenWindowsPos; // If this application has existing windows, we simply place the new window on top of // them... but keep the starting window on top. if (win.mAttrs.type == TYPE_BASE_APPLICATION) { // Base windows go behind everything else. final WindowState lowestWindow = tokenWindowList.get(0); addWindowToListBefore(win, lowestWindow); tokenWindowsPos = win.mToken.getWindowIndex(lowestWindow); } else { final AppWindowToken atoken = win.mAppToken; final int windowListPos = tokenWindowList.size(); final WindowState lastWindow = tokenWindowList.get(windowListPos - 1); if (atoken != null && lastWindow == atoken.startingWindow) { addWindowToListBefore(win, lastWindow); tokenWindowsPos = win.mToken.getWindowIndex(lastWindow); } else { int newIdx = findIdxBasedOnAppTokens(win); // There is a window above this one associated with the same apptoken note that the Loading @@ -1804,16 +1801,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + mWindows.size()); mWindows.add(newIdx + 1, win); if (newIdx < 0) { // No window from token found on win's display. tokenWindowsPos = 0; } else { tokenWindowsPos = win.mToken.getWindowIndex(mWindows.get(newIdx)) + 1; } mService.mWindowsChanged = true; } } return tokenWindowsPos; } /** Places the first input window after the second input window in the window list. */ Loading
services/core/java/com/android/server/wm/WindowToken.java +37 −4 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.util.Slog; import android.view.DisplayInfo; import java.io.PrintWriter; import java.util.Comparator; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; Loading Loading @@ -82,6 +83,26 @@ class WindowToken extends WindowContainer<WindowState> { // The display this token is on. private DisplayContent mDisplayContent; /** * Compares two child window of this token and returns -1 if the first is lesser than the * second in terms of z-order and 1 otherwise. */ private final Comparator<WindowState> mWindowComparator = (WindowState newWindow, WindowState existingWindow) -> { final WindowToken token = WindowToken.this; if (newWindow.mToken != token) { throw new IllegalArgumentException("newWindow=" + newWindow + " is not a child of token=" + token); } if (existingWindow.mToken != token) { throw new IllegalArgumentException("existingWindow=" + existingWindow + " is not a child of token=" + token); } return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1; }; WindowToken(WindowManagerService service, IBinder _token, int type, boolean _explicit, DisplayContent dc) { mService = service; Loading Loading @@ -168,19 +189,31 @@ class WindowToken extends WindowContainer<WindowState> { return -1; } /** * Returns true if the new window is considered greater than the existing window in terms of * z-order. */ protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow, WindowState existingWindow) { // By default the first window isn't greater than the second to preserve existing logic of // how new windows are added to the token return false; } void addWindow(final WindowState win) { if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindow: win=" + win + " Callers=" + Debug.getCallers(5)); if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindow: win=" + win + " Callers=" + Debug.getCallers(5)); if (!win.isChildWindow()) { int tokenWindowsPos = 0; if (asAppWindowToken() != null) { tokenWindowsPos = mDisplayContent.addAppWindowToWindowList(win); mDisplayContent.addAppWindowToWindowList(win); } else { mDisplayContent.addNonAppWindowToWindowList(win); } if (!mChildren.contains(win)) { if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this); addChild(win, tokenWindowsPos); addChild(win, mWindowComparator); } } else { mDisplayContent.addChildWindowToWindowList(win); Loading
services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java +43 −3 Original line number Diff line number Diff line Loading @@ -29,17 +29,19 @@ import android.view.IWindow; import android.view.WindowManager; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; /** * Tests for the {@link WindowState} class. * * Build: mmma -j32 frameworks/base/services/tests/servicestests * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk * Run: adb shell am instrument -w -e class com.android.server.wm.AppWindowTokenTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner * Build/Install/Run: * bit FrameworksServicesTests:com.android.server.wm.AppWindowTokenTests */ @SmallTest @Presubmit Loading @@ -55,6 +57,36 @@ public class AppWindowTokenTests { sWm = TestWindowManagerPolicy.getWindowManagerService(context); } @Test public void testAddWindow_Order() throws Exception { final TestAppWindowToken token = new TestAppWindowToken(); assertEquals(0, token.getWindowsCount()); final WindowState win1 = createWindow(null, TYPE_APPLICATION, token); final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, token); final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, token); final WindowState win4 = createWindow(null, TYPE_APPLICATION, token); token.addWindow(win1); token.addWindow(startingWin); token.addWindow(baseWin); token.addWindow(win4); // Should not contain the windows that were added above. assertEquals(4, token.getWindowsCount()); assertTrue(token.hasWindow(win1)); assertTrue(token.hasWindow(startingWin)); assertTrue(token.hasWindow(baseWin)); assertTrue(token.hasWindow(win4)); // The starting window should be on-top of all other windows. assertEquals(startingWin, token.getLastChild()); // The base application window should be below all other windows. assertEquals(baseWin, token.getFirstChild()); } @Test public void testFindMainWindow() throws Exception { final TestAppWindowToken token = new TestAppWindowToken(); Loading Loading @@ -93,5 +125,13 @@ public class AppWindowTokenTests { boolean hasWindow(WindowState w) { return mChildren.contains(w); } WindowState getFirstChild() { return mChildren.getFirst(); } WindowState getLastChild() { return mChildren.getLast(); } } }
services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java +2 −3 Original line number Diff line number Diff line Loading @@ -41,9 +41,8 @@ import static org.mockito.Mockito.mock; /** * Tests for the {@link WindowState} class. * * Build: mmma -j32 frameworks/base/services/tests/servicestests * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk * Run: adb shell am instrument -w -e class com.android.server.wm.WindowTokenTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner * Build/Install/Run: * bit FrameworksServicesTests:com.android.server.wm.WindowTokenTests */ @SmallTest @Presubmit Loading