Merge "Moved window focus calculation to DisplayContent"

This commit is contained in:
Wale Ogunwale
2016-09-15 12:03:01 +00:00
committed by Android (Google) Code Review
7 changed files with 192 additions and 67 deletions

View File

@@ -26,7 +26,10 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -764,4 +767,65 @@ class DisplayContent {
}
}
}
WindowState findFocusedWindow() {
final AppWindowToken focusedApp = mService.mFocusedApp;
for (int i = mWindows.size() - 1; i >= 0; i--) {
final WindowState win = mWindows.get(i);
if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win
+ ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys());
if (!win.canReceiveKeys()) {
continue;
}
final AppWindowToken wtoken = win.mAppToken;
// If this window's application has been removed, just skip it.
if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
+ (wtoken.removed ? "removed" : "sendingToBottom"));
continue;
}
if (focusedApp == null) {
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
+ " using new focus @ " + i + " = " + win);
return win;
}
if (!focusedApp.windowsAreFocusable()) {
// Current focused app windows aren't focusable...
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
+ " focusable using new focus @ " + i + " = " + win);
return win;
}
// Descend through all of the app tokens and find the first that either matches
// win.mAppToken (return win) or mFocusedApp (return null).
if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
final TaskStack focusedAppStack = focusedApp.mTask.mStack;
final TaskStack appStack = wtoken.mTask.mStack;
// TODO: Use WindowContainer.compareTo() once everything is using WindowContainer
if ((focusedAppStack == appStack
&& appStack.isFirstGreaterThanSecond(focusedApp, wtoken))
|| mStacks.indexOf(focusedAppStack) > mStacks.indexOf(appStack)) {
// App stack below focused app stack. No focus for you!!!
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
"findFocusedWindow: Reached focused app=" + focusedApp);
return null;
}
}
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ "
+ i + " = " + win);
return win;
}
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
return null;
}
}

View File

@@ -684,6 +684,11 @@ class Task implements DimLayer.DimLayerUser {
return false;
}
// TODO: Use WindowContainer.compareTo() once everything is using WindowContainer
boolean isFirstGreaterThanSecond(AppWindowToken first, AppWindowToken second) {
return mAppTokens.indexOf(first) > mAppTokens.indexOf(second);
}
boolean fillsParent() {
return mFullscreen || !StackId.isTaskResizeAllowed(mStack.mStackId);
}

View File

@@ -1309,6 +1309,17 @@ public class TaskStack implements DimLayer.DimLayerUser,
}
}
// TODO: Use WindowContainer.compareTo() once everything is using WindowContainer
boolean isFirstGreaterThanSecond(AppWindowToken first, AppWindowToken second) {
final Task firstTask = first.mTask;
final Task secondTask = second.mTask;
if (firstTask == secondTask) {
return firstTask.isFirstGreaterThanSecond(first, second);
}
return mTasks.indexOf(first) > mTasks.indexOf(second);
}
// TODO: Remove once switched to use WindowContainer
int getOrientation() {
if (!StackId.canSpecifyOrientation(mStackId)) {

View File

@@ -31,7 +31,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
* The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
* changes are made to this class.
*/
class WindowContainer {
class WindowContainer implements Comparable<WindowContainer> {
// The parent of this window container.
private WindowContainer mParent = null;
@@ -47,6 +47,10 @@ class WindowContainer {
return mParent;
}
// Temp. holders for a chain of containers we are currently processing.
private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList();
private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList();
/**
* Adds the input window container has a child of this container in order based on the input
* comparator.
@@ -311,4 +315,65 @@ class WindowContainer {
boolean fillsParent() {
return false;
}
/**
* Returns -1, 0, or 1 depending on if the input container is greater than, equal to, or lesser
* than the input container in terms of z-order.
*/
@Override
public int compareTo(WindowContainer other) {
if (this == other) {
return 0;
}
if (mParent != null && mParent == other.mParent) {
final LinkedList<WindowContainer> list = mParent.mChildren;
return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
}
final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
getParents(thisParentChain);
other.getParents(otherParentChain);
// Find the common ancestor of both containers.
WindowContainer commonAncestor = null;
WindowContainer thisTop = thisParentChain.peekLast();
WindowContainer otherTop = otherParentChain.peekLast();
while (thisTop != null && otherTop != null && thisTop == otherTop) {
commonAncestor = thisParentChain.removeLast();
otherParentChain.removeLast();
thisTop = thisParentChain.peekLast();
otherTop = otherParentChain.peekLast();
}
// Containers don't belong to the same hierarchy???
if (commonAncestor == null) {
throw new IllegalArgumentException("No in the same hierarchy this="
+ thisParentChain + " other=" + otherParentChain);
}
// Children are always considered greater than their parents, so if one of the containers
// we are comparing it the parent of the other then whichever is the child is greater.
if (commonAncestor == this) {
return -1;
} else if (commonAncestor == other) {
return 1;
}
// The position of the first non-common ancestor in the common ancestor list determines
// which is greater the which.
final LinkedList<WindowContainer> list = commonAncestor.mChildren;
return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
? 1 : -1;
}
private void getParents(LinkedList<WindowContainer> parents) {
parents.clear();
WindowContainer current = this;
do {
parents.addLast(current);
current = current.mParent;
} while (current != null);
}
}

View File

@@ -3638,8 +3638,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
// We're launchingBehind, add the launching activity to mOpeningApps.
final WindowState win =
findFocusedWindowLocked(getDefaultDisplayContentLocked());
final WindowState win = getDefaultDisplayContentLocked().findFocusedWindow();
if (win != null) {
final AppWindowToken focusedToken = win.mAppToken;
if (focusedToken != null) {
@@ -8772,7 +8771,7 @@ public class WindowManagerService extends IWindowManager.Stub
final int displayCount = mDisplayContents.size();
for (int i = 0; i < displayCount; i++) {
final DisplayContent displayContent = mDisplayContents.valueAt(i);
WindowState win = findFocusedWindowLocked(displayContent);
final WindowState win = displayContent.findFocusedWindow();
if (win != null) {
return win;
}
@@ -8780,67 +8779,6 @@ public class WindowManagerService extends IWindowManager.Stub
return null;
}
WindowState findFocusedWindowLocked(DisplayContent displayContent) {
final WindowList windows = displayContent.getWindowList();
for (int i = windows.size() - 1; i >= 0; i--) {
final WindowState win = windows.get(i);
if (localLOGV || DEBUG_FOCUS) Slog.v(
TAG_WM, "Looking for focus: " + i
+ " = " + win
+ ", flags=" + win.mAttrs.flags
+ ", canReceive=" + win.canReceiveKeys());
if (!win.canReceiveKeys()) {
continue;
}
AppWindowToken wtoken = win.mAppToken;
// If this window's application has been removed, just skip it.
if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
+ (wtoken.removed ? "removed" : "sendingToBottom"));
continue;
}
// Descend through all of the app tokens and find the first that either matches
// win.mAppToken (return win) or mFocusedApp (return null).
if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
mFocusedApp != null) {
ArrayList<Task> tasks = displayContent.getTasks();
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
int tokenNdx = tokens.size() - 1;
for ( ; tokenNdx >= 0; --tokenNdx) {
final AppWindowToken token = tokens.get(tokenNdx);
if (wtoken == token) {
break;
}
if (mFocusedApp == token && token.windowsAreFocusable()) {
// Whoops, we are below the focused app whose windows are focusable...
// No focus for you!!!
if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
"findFocusedWindow: Reached focused app=" + mFocusedApp);
return null;
}
}
if (tokenNdx >= 0) {
// Early exit from loop, must have found the matching token.
break;
}
}
}
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + i +
" = " + win);
return win;
}
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
return null;
}
void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
if (mDisplayFrozen) {
return;

View File

@@ -1569,8 +1569,7 @@ class WindowSurfacePlacer {
private void processApplicationsAnimatingInPlace(int transit) {
if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
// Find the focused window
final WindowState win = mService.findFocusedWindowLocked(
mService.getDefaultDisplayContentLocked());
final WindowState win = mService.getDefaultDisplayContentLocked().findFocusedWindow();
if (win != null) {
final AppWindowToken wtoken = win.mAppToken;
final AppWindowAnimator appAnimator = wtoken.mAppAnimator;

View File

@@ -326,6 +326,49 @@ public class WindowContainerTests {
assertEquals(SCREEN_ORIENTATION_PORTRAIT, root.getOrientation());
}
@Test
public void testCompareTo() throws Exception {
final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
final TestWindowContainer root = builder.setLayer(0).build();
final TestWindowContainer child1 = root.addChildWindow();
final TestWindowContainer child11 = child1.addChildWindow();
final TestWindowContainer child12 = child1.addChildWindow();
final TestWindowContainer child2 = root.addChildWindow();
final TestWindowContainer child21 = child2.addChildWindow();
final TestWindowContainer child22 = child2.addChildWindow();
final TestWindowContainer child23 = child2.addChildWindow();
final TestWindowContainer child221 = child22.addChildWindow();
final TestWindowContainer child222 = child22.addChildWindow();
final TestWindowContainer child223 = child22.addChildWindow();
final TestWindowContainer child2221 = child222.addChildWindow();
final TestWindowContainer child2222 = child222.addChildWindow();
final TestWindowContainer child2223 = child222.addChildWindow();
final TestWindowContainer root2 = builder.setLayer(0).build();
assertEquals(0, root.compareTo(root));
assertEquals(-1, child1.compareTo(child2));
assertEquals(1, child2.compareTo(child1));
boolean inTheSameTree = true;
try {
root.compareTo(root2);
} catch (IllegalArgumentException e) {
inTheSameTree = false;
}
assertFalse(inTheSameTree);
assertEquals(-1, child1.compareTo(child11));
assertEquals(1, child21.compareTo(root));
assertEquals(1, child21.compareTo(child12));
assertEquals(-1, child11.compareTo(child2));
assertEquals(1, child2221.compareTo(child11));
assertEquals(-1, child2222.compareTo(child223));
assertEquals(1, child2223.compareTo(child21));
}
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
private class TestWindowContainer extends WindowContainer {
private final int mLayer;