From 825581a3eefac8565184caf7ddb7f7e30efaa51f Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Fri, 30 Mar 2018 14:00:53 -0700 Subject: [PATCH 1/2] Fix computation of child window insets. Translate some old code that derived conditions from Surface layers to directly infer the conditions. Bug: 75253006 Test: Manual. go/wm-smoke Change-Id: Ib114e8cb3b7c2255d68237e18eebba8f48e0fb16 --- .../server/policy/PhoneWindowManager.java | 18 +++++++++--------- .../server/policy/WindowManagerPolicy.java | 2 ++ .../com/android/server/wm/WindowState.java | 15 ++++++++++----- .../android/server/policy/FakeWindowState.java | 5 +++++ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fd023476c9e4a..9a25dcc547cfd 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -4976,13 +4976,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf, DisplayFrames displayFrames) { - if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { - // Here's a special case: if this attached window is a panel that is above the dock - // window, and the window it is attached to is below the dock window, then the frames we - // computed for the window it is attached to can not be used because the dock is - // effectively part of the underlying window and the attached window is floating on top - // of the whole thing. So, we ignore the attached window and explicitly compute the - // frames that would be appropriate without the dock. + if (!win.isInputMethodTarget() && attached.isInputMethodTarget()) { + // Here's a special case: if the child window is not the 'dock window' + // or input method target, and the window it is attached to is below + // the dock window, then the frames we computed for the window it is + // attached to can not be used because the dock is effectively part + // of the underlying window and the attached window is floating on top + // of the whole thing. So, we ignore the attached window and explicitly + // compute the frames that would be appropriate without the dock. vf.set(displayFrames.mDock); cf.set(displayFrames.mDock); of.set(displayFrames.mDock); @@ -5009,7 +5010,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { cf.set(attached.getContentFrameLw()); if (attached.isVoiceInteraction()) { cf.intersectUnchecked(displayFrames.mVoiceContent); - } else if (attached.getSurfaceLayer() < mDockLayer) { + } else if (win.isInputMethodTarget() || attached.isInputMethodTarget()) { cf.intersectUnchecked(displayFrames.mContent); } } @@ -5500,7 +5501,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf, displayFrames.mDisplayCutout, parentFrameWasClippedByDisplayCutout); - // Dock windows carve out the bottom of the screen, so normal windows // can't appear underneath them. if (type == TYPE_INPUT_METHOD && win.isVisibleLw() diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 0a6ae4e2f2d97..ccbf502bc2b51 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -474,6 +474,8 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { public boolean isInputMethodWindow(); + public boolean isInputMethodTarget(); + public int getDisplayId(); /** diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 30bbfe0b83c4d..0debf83713f15 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -897,7 +897,7 @@ class WindowState extends WindowContainer implements WindowManagerP } final WindowState imeWin = mService.mInputMethodWindow; // IME is up and obscuring this window. Adjust the window position so it is visible. - if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) { + if (imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget()) { if (inFreeformWindowingMode() && mContainingFrame.bottom > contentFrame.bottom) { // In freeform we want to move the top up directly. @@ -1885,7 +1885,7 @@ class WindowState extends WindowContainer implements WindowManagerP } final DisplayContent dc = getDisplayContent(); - if (mService.mInputMethodTarget == this) { + if (isInputMethodTarget()) { dc.computeImeTarget(true /* updateImeTarget */); } @@ -3949,7 +3949,7 @@ class WindowState extends WindowContainer implements WindowManagerP private boolean applyInOrderWithImeWindows(ToBooleanFunction callback, boolean traverseTopToBottom) { if (traverseTopToBottom) { - if (mService.mInputMethodTarget == this) { + if (isInputMethodTarget()) { // This window is the current IME target, so we need to process the IME windows // directly above it. if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) { @@ -3963,7 +3963,7 @@ class WindowState extends WindowContainer implements WindowManagerP if (callback.apply(this)) { return true; } - if (mService.mInputMethodTarget == this) { + if (isInputMethodTarget()) { // This window is the current IME target, so we need to process the IME windows // directly above it. if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) { @@ -4673,7 +4673,7 @@ class WindowState extends WindowContainer implements WindowManagerP void assignLayer(Transaction t, int layer) { // See comment in assignRelativeLayerForImeTargetChild if (!isChildWindow() - || (mService.mInputMethodTarget != getParentWindow()) + || (!getParentWindow().isInputMethodTarget()) || !inSplitScreenWindowingMode()) { super.assignLayer(t, layer); return; @@ -4741,6 +4741,11 @@ class WindowState extends WindowContainer implements WindowManagerP mTapExcludeRegionHolder.amendRegion(region, getBounds()); } + @Override + public boolean isInputMethodTarget() { + return mService.mInputMethodTarget == this; + } + private final class MoveAnimationSpec implements AnimationSpec { private final long mDuration; diff --git a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java index 56ba047338a79..7487d4490d9a5 100644 --- a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java +++ b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java @@ -258,4 +258,9 @@ public class FakeWindowState implements WindowManagerPolicy.WindowState { public void writeIdentifierToProto(ProtoOutputStream proto, long fieldId){ throw new UnsupportedOperationException("not implemented"); } + + @Override + public boolean isInputMethodTarget() { + return false; + } } From b6d4e2be31eeae83a1b80689073f10ffaeab8a58 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Fri, 30 Mar 2018 15:39:58 -0700 Subject: [PATCH 2/2] Avoid calling detachChildren from onAppVisibilityChanged When entering PiP we use mDeferHidingClient to prevent sending the app visibility to the client before it has a chance to enter PiP. However, WindowState#onAppVisibilityChanged is not guarded by this so we could end up detaching children when we mean to enter PiP. Instead only detach children from sendAppVisibilityToClients so that we are correctly guarded by the mDeferHidingClient flag. Bug: 77294187 Test: Manual. go/wm-smoke. Change-Id: Ia9df12fadf3c48d0704e9e6d7e98a6e9cf46783d --- services/core/java/com/android/server/wm/WindowState.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 0debf83713f15..54c2e9badc7b0 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1691,13 +1691,6 @@ class WindowState extends WindowContainer implements WindowManagerP return changed; } - // Next up we will notify the client that it's visibility has changed. - // We need to prevent it from destroying child surfaces until - // the animation has finished. - if (!visible && isVisibleNow()) { - mWinAnimator.detachChildren(); - } - if (visible != isVisibleNow()) { if (!runningAppAnimation) { final AccessibilityController accessibilityController =