Merge "Add windows to window tokens in expected z-order"
This commit is contained in:
committed by
Android (Google) Code Review
commit
fbee823e88
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -1154,7 +1155,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
}
|
||||
}
|
||||
addWindowToListAfter(win, pos);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Just search for the start of this layer.
|
||||
@@ -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. */
|
||||
@@ -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
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user