CVE-2024-31324 AI-generated analysis
platform/frameworks/base, WindowManager (services/core/java/com/android/server/wm/WindowState.java)
WindowState.hide() now decides whether to defer the visibility change based on whether an exit animation was actually applied to the window itself (return value of mWinAnimator.applyAnimationLocked), instead of checking isAnimating(TRANSITION | PARENTS), so a window with no hide animation is committed invisible immediately even when its parent container is animating.
Root cause
In WindowState.hide(doAnimation, requestAnim), after calling mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false), the code only fell back to immediate hiding when !isAnimating(TRANSITION | PARENTS). Per the commit message, commit 9bca6b4 overextended this condition to include the parent container. If the parent was animating but the window itself had no exit animation, doAnimation stayed true and the window waited for onAnimationFinished -> checkPolicyVisibilityChange to hide it. That callback never arrives because the window is not animating, so the window that should have been hidden remained on screen.
How the fix works
- services/core/java/com/android/server/wm/WindowState.java:hide(): replaces the unconditional applyAnimationLocked call followed by `if (!isAnimating(TRANSITION | PARENTS)) doAnimation = false;` with `if (!mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false /* isEntrance */)) doAnimation = false;`. The decision is now tied to whether a hide animation was applied to this window: if yes, onAnimationFinished -> checkPolicyVisibilityChange hides it later; if no, doAnimation is cleared so the window is committed invisible immediately, regardless of parent animation state.
- services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java:testIsOnScreen_hiddenByPolicy: adds two cases: (1) parent started animating via window.getParent().startAnimation(...) and window.mAttrs.windowAnimations = 0, then hide(true, true) must yield !isSelfAnimating, !isVisibleByPolicy, !isOnScreen; (2) with mAttrs.windowAnimations = android.R.style.Animation_Dialog, hide(true, true) leaves the window self-animating and still visible by policy until cancelAnimation(), after which it is not visible by policy.
Completeness
- Covers the hide() path only: any caller of WindowState.hide(doAnimation=true, ...) now gets immediate hiding when no exit animation is applied to the window itself.
- The fix depends on mWinAnimator.applyAnimationLocked returning false exactly when no animation was applied; that method is not in the material, so its return semantics are assumed from the comment and tests.
- The show() path is not touched by the diff and its logic is not shown in the material.
- The regression test exercises both the no-animation-with-animating-parent case and the with-animation case.
Behavior changes
- A window whose hide() is requested with doAnimation=true but which has no exit animation (e.g. mAttrs.windowAnimations == 0) is now hidden immediately even if its parent container is animating; previously it remained on screen because the animation-finish callback never fired.
- A window that does get an exit animation keeps the previous behavior: it remains visible by policy until the animation finishes (onAnimationFinished -> checkPolicyVisibilityChange).
Per major
- Android 14: same fix: cherry-pick 1ec80672496e in android-security-14.0.0_r9 (from 9add9281ffc1 / 10a7f0914c87); at android-security-14.0.0_r29 the patched region is fully present (7/7 lines).
- Android 15: not affected (not listed by the bulletin); at android-security-15.0.0_r17 the patched region is present (7/7 lines).
- Android 16: not affected (not listed by the bulletin); at android-security-16.0.0_r8 the patched region is present (7/7 lines).
- Android 17: not affected (not listed by the bulletin); at android-security-17.0.0_r1 6/7 lines of the patched region are present.
Unknowns
- The concrete user-visible scenario and which window/policy path makes this an EoP per the bulletin is not shown in the material.
- The content of the referenced regression commit 9bca6b4 and the implementation of mWinAnimator.applyAnimationLocked are not in the material, nor which branches carry the 9bca6b4 form.
- Whether WindowState.show() has an analogous parent-animation condition is not shown.
- Which line of the patched region differs at android-security-17.0.0_r1 is not shown.