From f8853f75c1979a185bbb4c5b6b3dc8a187af442c Mon Sep 17 00:00:00 2001 From: Issei Suzuki Date: Thu, 8 Apr 2021 18:47:05 +0200 Subject: [PATCH] Wait OCCLUDE transition until screen turning on activity becomes ready. When the screen is off, WindowManger usually skips running an app transition animation when updating visibility of activities. However, in case the activity is going to turn on the screen, we should not skip an app transition animation even if the screen is not yet on. I extended ActivityRecord#okToAnimate, so that it can ignore screen status and it can be used with ActivityRecord#canTurnScreenOn predicate. Bug: 175687166 Bug: 182975035 Change-Id: Id8079df2027becadc9c5e8266149f6eb76b467b6 Test: Receive phone call while the screen is off. --- .../server/policy/PhoneWindowManager.java | 4 ++-- .../server/policy/WindowManagerPolicy.java | 3 ++- .../com/android/server/wm/ActivityRecord.java | 3 ++- .../com/android/server/wm/DisplayContent.java | 16 +++++++++++++--- .../com/android/server/wm/DisplayRotation.java | 2 +- .../android/server/wm/KeyguardController.java | 16 +++++++++++----- .../com/android/server/wm/WindowContainer.java | 5 +++++ .../server/wm/TestWindowManagerPolicy.java | 2 +- 8 files changed, 37 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 c7789eecc68fe..b25581eb98681 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -4437,8 +4437,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override - public boolean okToAnimate() { - return mDefaultDisplayPolicy.isAwake() && !mDeviceGoingToSleep; + public boolean okToAnimate(boolean ignoreScreenOn) { + return (ignoreScreenOn || mDefaultDisplayPolicy.isAwake()) && !mDeviceGoingToSleep; } /** {@inheritDoc} */ diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index d512edfb066a7..78b03b2b88e76 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -897,12 +897,13 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { public boolean isScreenOn(); /** + * @param ignoreScreenOn {@code true} if screen state should be ignored. * @return whether the device is currently allowed to animate. * * Note: this can be true even if it is not appropriate to animate for reasons that are outside * of the policy's authority. */ - boolean okToAnimate(); + boolean okToAnimate(boolean ignoreScreenOn); /** * Tell the policy that the lid switch has changed state. diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 01a46b311740c..e6b2b01664dd1 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4568,7 +4568,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // still check DC#okToAnimate again if the transition animation is fine to apply. // TODO(new-app-transition): Rewrite this logic using WM Shell. final boolean recentsAnimating = isAnimating(PARENTS, ANIMATION_TYPE_RECENTS); - if (okToAnimate(true /* ignoreFrozen */) && (appTransition.isTransitionSet() + if (okToAnimate(true /* ignoreFrozen */, canTurnScreenOn()) + && (appTransition.isTransitionSet() || (recentsAnimating && !isActivityTypeHome()))) { if (visible) { displayContent.mOpeningApps.add(this); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index b1606c9e5d2d7..853c08bdf1632 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4429,9 +4429,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } boolean okToDisplay(boolean ignoreFrozen) { + return okToDisplay(ignoreFrozen, false /* ignoreScreenOn */); + } + + boolean okToDisplay(boolean ignoreFrozen, boolean ignoreScreenOn) { if (mDisplayId == DEFAULT_DISPLAY) { return (!mWmService.mDisplayFrozen || ignoreFrozen) - && mWmService.mDisplayEnabled && mWmService.mPolicy.isScreenOn(); + && mWmService.mDisplayEnabled + && (ignoreScreenOn || mWmService.mPolicy.isScreenOn()); } return mDisplayInfo.state == Display.STATE_ON; } @@ -4441,8 +4446,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } boolean okToAnimate(boolean ignoreFrozen) { - return okToDisplay(ignoreFrozen) && - (mDisplayId != DEFAULT_DISPLAY || mWmService.mPolicy.okToAnimate()); + return okToAnimate(ignoreFrozen, false /* ignoreScreenOn */); + } + + boolean okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn) { + return okToDisplay(ignoreFrozen, ignoreScreenOn) + && (mDisplayId != DEFAULT_DISPLAY + || mWmService.mPolicy.okToAnimate(ignoreScreenOn)); } static final class TaskForResizePointSearchResult { diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 9ff701cafd667..e1fc75e6fd9f5 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -731,7 +731,7 @@ public class DisplayRotation { private RotationAnimationPair selectRotationAnimation() { // If the screen is off or non-interactive, force a jumpcut. final boolean forceJumpcut = !mDisplayPolicy.isScreenOnFully() - || !mService.mPolicy.okToAnimate(); + || !mService.mPolicy.okToAnimate(false /* ignoreScreenOn */); final WindowState topFullscreen = mDisplayPolicy.getTopFullscreenOpaqueWindow(); if (DEBUG_ANIM) Slog.i(TAG, "selectRotationAnimation topFullscreen=" + topFullscreen + " rotationAnimation=" diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 20216c3afcd49..8ff9fbaa39952 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -341,11 +341,10 @@ class KeyguardController { /** * Called when occluded state changed. * - * @param currentTaskControllingOcclusion the task that controls the state whether keyguard - * should be occluded. That is the task to be shown on top of keyguard if it requests so. + * @param topActivity the activity that controls the state whether keyguard should + * be occluded. That is the activity to be shown on top of keyguard if it requests so. */ - private void handleOccludedChanged( - int displayId, @Nullable Task currentTaskControllingOcclusion) { + private void handleOccludedChanged(int displayId, @Nullable ActivityRecord topActivity) { // TODO(b/113840485): Handle app transition for individual display, and apply occluded // state change to secondary displays. // For now, only default display fully supports occluded change. Other displays only @@ -364,6 +363,13 @@ class KeyguardController { isDisplayOccluded(DEFAULT_DISPLAY) ? TRANSIT_KEYGUARD_OCCLUDE : TRANSIT_KEYGUARD_UNOCCLUDE); + // When the occluding activity also turns on the display, visibility of the activity + // can be committed before KEYGUARD_OCCLUDE transition is handled. + // Set mRequestForceTransition flag to make sure that the app transition animation + // is applied for such case. + if (topActivity != null) { + topActivity.mRequestForceTransition = true; + } updateKeyguardSleepToken(DEFAULT_DISPLAY); mWindowManager.executeAppTransition(); } finally { @@ -580,7 +586,7 @@ class KeyguardController { if (lastOccluded != mOccluded) { occludingChange = true; - controller.handleOccludedChanged(mDisplayId, task); + controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity); } if (occludingChange || turningScreenOn) { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 070a7252a3bff..191c3a117e851 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2796,6 +2796,11 @@ class WindowContainer extends ConfigurationContainer< return dc != null && dc.okToAnimate(ignoreFrozen); } + boolean okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn) { + final DisplayContent dc = getDisplayContent(); + return dc != null && dc.okToAnimate(ignoreFrozen, ignoreScreenOn); + } + @Override public void commitPendingTransaction() { scheduleAnimation(); diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java index ae8e2ded359dc..acadb74d333f0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -210,7 +210,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override - public boolean okToAnimate() { + public boolean okToAnimate(boolean ignoreScreenOn) { return mOkToAnimate; }