Merge "Allow some app windows to display above the IME."

This commit is contained in:
TreeHugger Robot
2016-12-02 19:55:50 +00:00
committed by Android (Google) Code Review
5 changed files with 90 additions and 19 deletions

View File

@@ -141,8 +141,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Utility class for keeping track of the WindowStates and other pertinent contents of a
@@ -2546,7 +2544,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (!obscured) {
final boolean isDisplayed = w.isDisplayedLw();
if (isDisplayed && w.isObscuringFullscreen(mDisplayInfo)) {
if (isDisplayed && w.isObscuringDisplay()) {
// This window completely covers everything behind it, so we want to leave all
// of them as undimmed (for performance reasons).
root.mObscuringWindow = w;
@@ -2945,7 +2943,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
screenshotReady = true;
}
if (ws.isObscuringFullscreen(mDisplayInfo)){
if (ws.isObscuringDisplay()){
break;
}
}

View File

@@ -66,6 +66,8 @@ class WindowLayersController {
private boolean mAnyLayerChanged;
private int mHighestLayerInImeTargetBaseLayer;
private WindowState mImeTarget;
private boolean mAboveImeTarget;
private ArrayDeque<WindowState> mAboveImeTargetAppWindows = new ArrayDeque();
final void assignWindowLayers(DisplayContent dc) {
if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based",
@@ -143,6 +145,8 @@ class WindowLayersController {
mImeTarget = mService.mInputMethodTarget;
mHighestLayerInImeTargetBaseLayer = (mImeTarget != null) ? mImeTarget.mBaseLayer : 0;
mAboveImeTarget = false;
mAboveImeTargetAppWindows.clear();
}
private void collectSpecialWindows(WindowState w) {
@@ -157,6 +161,20 @@ class WindowLayersController {
mInputMethodWindows.add(w);
return;
}
if (mImeTarget != null) {
if (w.getParentWindow() == mImeTarget && w.mSubLayer > 0) {
// Child windows of the ime target with a positive sub-layer should be placed above
// the IME.
mAboveImeTargetAppWindows.add(w);
} else if (mAboveImeTarget && w.mAppToken != null) {
// windows of apps above the IME target should be placed above the IME.
mAboveImeTargetAppWindows.add(w);
}
if (w == mImeTarget) {
mAboveImeTarget = true;
}
}
final Task task = w.getTask();
if (task == null) {
return;
@@ -211,6 +229,12 @@ class WindowLayersController {
while (!mInputMethodWindows.isEmpty()) {
layer = assignAndIncreaseLayerIfNeeded(mInputMethodWindows.remove(), layer);
}
// Adjust app windows the should be displayed above the IME since they are above the IME
// target.
while (!mAboveImeTargetAppWindows.isEmpty()) {
layer = assignAndIncreaseLayerIfNeeded(mAboveImeTargetAppWindows.remove(), layer);
}
}
}

View File

@@ -60,8 +60,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import static android.app.ActivityManager.StackId;
@@ -91,7 +89,6 @@ import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
@@ -1654,18 +1651,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
&& (!mIsChildWindow || !getParentWindow().hasMoved());
}
boolean isObscuringFullscreen(final DisplayInfo displayInfo) {
boolean isObscuringDisplay() {
Task task = getTask();
if (task != null && task.mStack != null && !task.mStack.fillsParent()) {
return false;
}
if (!isOpaqueDrawn() || !isFrameFullscreen(displayInfo)) {
return false;
}
return true;
return isOpaqueDrawn() && fillsDisplay();
}
boolean isFrameFullscreen(final DisplayInfo displayInfo) {
boolean fillsDisplay() {
final DisplayInfo displayInfo = getDisplayInfo();
return mFrame.left <= 0 && mFrame.top <= 0
&& mFrame.right >= displayInfo.appWidth && mFrame.bottom >= displayInfo.appHeight;
}

View File

@@ -57,7 +57,6 @@ import android.os.Trace;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.MagnificationSpec;
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -1108,10 +1107,9 @@ class WindowStateAnimator {
/**
* Calculate the window-space crop rect and fill clipRect.
* @return true if clipRect has been filled otherwise, no window space
* crop should be applied.
* @return true if clipRect has been filled otherwise, no window space crop should be applied.
*/
boolean calculateCrop(Rect clipRect) {
private boolean calculateCrop(Rect clipRect) {
final WindowState w = mWin;
final DisplayContent displayContent = w.getDisplayContent();
clipRect.setEmpty();
@@ -1130,7 +1128,6 @@ class WindowStateAnimator {
return false;
}
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (DEBUG_WINDOW_CROP) Slog.d(TAG,
"Updating crop win=" + w + " mLastCrop=" + mLastClipRect);
@@ -1139,7 +1136,7 @@ class WindowStateAnimator {
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
+ w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
final boolean fullscreen = w.isFrameFullscreen(displayInfo);
final boolean fullscreen = w.fillsDisplay();
final boolean isFreeformResizing =
w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;

View File

@@ -25,6 +25,7 @@ import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
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_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -120,6 +121,62 @@ public class WindowLayersControllerTests extends WindowTestsBase {
assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
}
@Test
public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() throws Exception {
final WindowState imeAppTarget =
createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
final WindowState imeAppTargetChildAboveWindow = createWindow(imeAppTarget,
TYPE_APPLICATION_ATTACHED_DIALOG, imeAppTarget.mToken,
"imeAppTargetChildAboveWindow");
final WindowState imeAppTargetChildBelowWindow = createWindow(imeAppTarget,
TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken,
"imeAppTargetChildBelowWindow");
sWm.mInputMethodTarget = imeAppTarget;
sLayersController.assignWindowLayers(sDisplayContent);
// Ime should be above all app windows except for child windows that are z-ordered above it
// and below system windows if it is targeting an app window.
assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
assertWindowLayerGreaterThan(imeAppTargetChildAboveWindow, sImeWindow);
assertWindowLayerGreaterThan(sImeWindow, imeAppTargetChildBelowWindow);
assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
assertWindowLayerGreaterThan(sStatusBarWindow, sImeWindow);
// And, IME dialogs should always have an higher layer than the IME.
assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
}
@Test
public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() throws Exception {
final WindowState appBelowImeTarget =
createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "appBelowImeTarget");
final WindowState imeAppTarget =
createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
final WindowState appAboveImeTarget =
createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "appAboveImeTarget");
sWm.mInputMethodTarget = imeAppTarget;
sLayersController.assignWindowLayers(sDisplayContent);
// Ime should be above all app windows except for non-fullscreen app window above it and
// below system windows if it is targeting an app window.
assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
assertWindowLayerGreaterThan(sImeWindow, appBelowImeTarget);
assertWindowLayerGreaterThan(appAboveImeTarget, sImeWindow);
assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
assertWindowLayerGreaterThan(sStatusBarWindow, sImeWindow);
// And, IME dialogs should always have an higher layer than the IME.
assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
}
@Test
public void testAssignWindowLayers_ForImeNonAppImeTarget() throws Exception {
final WindowState imeSystemOverlayTarget =