From 0e9fb13312a79985fc9aa98fd0d0968eaca33019 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 5 Jun 2018 16:29:13 -0700 Subject: [PATCH] Prevent IME from showing when AOD shown or windows not drawn. There's always been a possibility for IME to be visible even after the screen was turned off. This was normally harmless because the IME was placed behind the lock screen. The lock screen was opaque so it would cover the IME, even in the case with AOD. However, with AOD live wallpaper, the lock screen can now be transparent. This causes the IME to be shown in between the wallpaper and lock screen. To prevent IME from showing, several things needed to change. 1. The flag that was sent from sysui to AM is now propagated to WM. If AOD is showing, IME should be hidden. 2. That flag sometimes is not a guarantee because AOD could be exiting, but still shown on screen. Instead, also rely on the mWindowManagerDrawComplete since that's only true when the windows have completed drawing. The IME only needs to be shown if the other windows on screen have drawn. Test: Open IME and allow screen to timeout. When AOD turns on with live wallpaper, IME is hidden. Test: Within 5 seconds after AOD is turned on, turn screen on. Screen turns on without IME flicker. Fixes: 79658086 Change-Id: Ife93bdfde8ba2914930497356c0e16ebd629c507 --- .../android/server/am/KeyguardController.java | 1 + .../server/policy/PhoneWindowManager.java | 20 ++++++++++++++++++- .../server/policy/WindowManagerPolicy.java | 7 +++++++ .../server/wm/WindowManagerService.java | 13 ++++++++++++ .../server/wm/TestWindowManagerPolicy.java | 5 +++++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index ddf955292c684..30fa72fb69b95 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -129,6 +129,7 @@ class KeyguardController { mKeyguardShowing = keyguardShowing; mAodShowing = aodShowing; mSecondaryDisplayShowing = secondaryDisplayShowing; + mWindowManager.setAodShowing(aodShowing); if (showingChanged) { dismissDockedStackIfNeeded(); setKeyguardGoingAway(false); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 03e34d3070ab9..7d6b896b9f00e 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -816,6 +816,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { private final MutableBoolean mTmpBoolean = new MutableBoolean(false); + private boolean mAodShowing; + private static final int MSG_ENABLE_POINTER_LOCATION = 1; private static final int MSG_DISABLE_POINTER_LOCATION = 2; private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; @@ -3058,8 +3060,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean keyguardLocked = isKeyguardLocked(); boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER && !mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + // If AOD is showing, the IME should be hidden. However, sometimes the AOD is considered + // hidden because it's in the process of hiding, but it's still being shown on screen. + // In that case, we want to continue hiding the IME until the windows have completed + // drawing. This way, we know that the IME can be safely shown since the other windows are + // now shown. + final boolean hideIme = + win.isInputMethodWindow() && (mAodShowing || !mWindowManagerDrawComplete); return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY) - || hideDockDivider; + || hideDockDivider || hideIme; } /** {@inheritDoc} */ @@ -8980,4 +8989,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void onLockTaskStateChangedLw(int lockTaskState) { mImmersiveModeConfirmation.onLockTaskModeChangedLw(lockTaskState); } + + @Override + public boolean setAodShowing(boolean aodShowing) { + if (mAodShowing != aodShowing) { + mAodShowing = aodShowing; + return true; + } + return false; + } } diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 02dd6e61707c5..a02ee225861db 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -1774,4 +1774,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * {@link ActivityManager#LOCK_TASK_MODE_PINNED}. */ void onLockTaskStateChangedLw(int lockTaskState); + + /** + * Updates the flag about whether AOD is showing. + * + * @return whether the value was changed. + */ + boolean setAodShowing(boolean aodShowing); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 2885b6fe29de6..7a2c28bd5c826 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7588,4 +7588,17 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.onLockTaskStateChangedLw(lockTaskState); } } + + /** + * Updates {@link WindowManagerPolicy} with new value about whether AOD is showing. If AOD + * has changed, this will trigger a {@link WindowSurfacePlacer#performSurfacePlacement} to + * ensure the new value takes effect. + */ + public void setAodShowing(boolean aodShowing) { + synchronized (mWindowMap) { + if (mPolicy.setAodShowing(aodShowing)) { + mWindowPlacerLocked.performSurfacePlacement(); + } + } + } } diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java index 50f3fbefaf40c..ee028ba4262b7 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -598,4 +598,9 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { @Override public void onLockTaskStateChangedLw(int lockTaskState) { } + + @Override + public boolean setAodShowing(boolean aodShowing) { + return false; + } }