diff options
4 files changed, 49 insertions, 17 deletions
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java index 2eceeccd9d8f..025047588ea5 100644 --- a/services/core/java/com/android/server/wm/AsyncRotationController.java +++ b/services/core/java/com/android/server/wm/AsyncRotationController.java @@ -172,10 +172,9 @@ class AsyncRotationController extends FadeAnimationController implements Consume if (recents != null && recents.isNavigationBarAttachedToApp()) { return; } - } else if (navigationBarCanMove || mTransitionOp == OP_CHANGE_MAY_SEAMLESS) { + } else if (navigationBarCanMove || mTransitionOp == OP_CHANGE_MAY_SEAMLESS + || mDisplayContent.mTransitionController.mNavigationBarAttachedToApp) { action = Operation.ACTION_SEAMLESS; - } else if (mDisplayContent.mTransitionController.mNavigationBarAttachedToApp) { - return; } mTargetWindowTokens.put(w.mToken, new Operation(action)); return; @@ -294,6 +293,11 @@ class AsyncRotationController extends FadeAnimationController implements Consume finishOp(mTargetWindowTokens.keyAt(i)); } mTargetWindowTokens.clear(); + onAllCompleted(); + } + + private void onAllCompleted() { + if (DEBUG) Slog.d(TAG, "onAllCompleted"); if (mTimeoutRunnable != null) { mService.mH.removeCallbacks(mTimeoutRunnable); } @@ -333,7 +337,7 @@ class AsyncRotationController extends FadeAnimationController implements Consume if (DEBUG) Slog.d(TAG, "Complete directly " + token.getTopChild()); finishOp(token); if (mTargetWindowTokens.isEmpty()) { - if (mTimeoutRunnable != null) mService.mH.removeCallbacks(mTimeoutRunnable); + onAllCompleted(); return true; } } @@ -411,14 +415,18 @@ class AsyncRotationController extends FadeAnimationController implements Consume if (mDisplayContent.mInputMethodWindow == null) return; final WindowToken imeWindowToken = mDisplayContent.mInputMethodWindow.mToken; if (isTargetToken(imeWindowToken)) return; + hideImmediately(imeWindowToken, Operation.ACTION_TOGGLE_IME); + if (DEBUG) Slog.d(TAG, "hideImeImmediately " + imeWindowToken.getTopChild()); + } + + private void hideImmediately(WindowToken token, @Operation.Action int action) { final boolean original = mHideImmediately; mHideImmediately = true; - final Operation op = new Operation(Operation.ACTION_TOGGLE_IME); - mTargetWindowTokens.put(imeWindowToken, op); - fadeWindowToken(false /* show */, imeWindowToken, ANIMATION_TYPE_TOKEN_TRANSFORM); - op.mLeash = imeWindowToken.getAnimationLeash(); + final Operation op = new Operation(action); + mTargetWindowTokens.put(token, op); + fadeWindowToken(false /* show */, token, ANIMATION_TYPE_TOKEN_TRANSFORM); + op.mLeash = token.getAnimationLeash(); mHideImmediately = original; - if (DEBUG) Slog.d(TAG, "hideImeImmediately " + imeWindowToken.getTopChild()); } /** Returns {@code true} if the window will rotate independently. */ @@ -428,11 +436,20 @@ class AsyncRotationController extends FadeAnimationController implements Consume || isTargetToken(w.mToken); } - /** Returns {@code true} if the controller will run fade animations on the window. */ + /** + * Returns {@code true} if the rotation transition appearance of the window is currently + * managed by this controller. + */ boolean isTargetToken(WindowToken token) { return mTargetWindowTokens.containsKey(token); } + /** Returns {@code true} if the controller will run fade animations on the window. */ + boolean hasFadeOperation(WindowToken token) { + final Operation op = mTargetWindowTokens.get(token); + return op != null && op.mAction == Operation.ACTION_FADE; + } + /** * Whether the insets animation leash should use previous position when running fade animation * or seamless transformation in a rotated display. @@ -564,7 +581,18 @@ class AsyncRotationController extends FadeAnimationController implements Consume return false; } final Operation op = mTargetWindowTokens.get(w.mToken); - if (op == null) return false; + if (op == null) { + // If a window becomes visible after the rotation transition is requested but before + // the transition is ready, hide it by an animation leash so it won't be flickering + // by drawing the rotated content before applying projection transaction of display. + // And it will fade in after the display transition is finished. + if (mTransitionOp == OP_APP_SWITCH && !mIsStartTransactionCommitted + && canBeAsync(w.mToken)) { + hideImmediately(w.mToken, Operation.ACTION_FADE); + if (DEBUG) Slog.d(TAG, "Hide on finishDrawing " + w.mToken.getTopChild()); + } + return false; + } if (DEBUG) Slog.d(TAG, "handleFinishDrawing " + w); if (postDrawTransaction == null || !mIsSyncDrawRequested || canDrawBeforeStartTransaction(op)) { diff --git a/services/core/java/com/android/server/wm/NavBarFadeAnimationController.java b/services/core/java/com/android/server/wm/NavBarFadeAnimationController.java index 2e5474e5e415..79b26d2ee994 100644 --- a/services/core/java/com/android/server/wm/NavBarFadeAnimationController.java +++ b/services/core/java/com/android/server/wm/NavBarFadeAnimationController.java @@ -86,7 +86,7 @@ public class NavBarFadeAnimationController extends FadeAnimationController{ ANIMATION_TYPE_TOKEN_TRANSFORM); if (controller == null) { fadeAnim.run(); - } else if (!controller.isTargetToken(mNavigationBar.mToken)) { + } else if (!controller.hasFadeOperation(mNavigationBar.mToken)) { // If fade rotation animation is running and the nav bar is not controlled by it: // - For fade-in animation, defer the animation until fade rotation animation finishes. // - For fade-out animation, just play the animation. diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 1566bb2c8610..e9af42bb7b90 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -1930,11 +1930,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { break; } - final AsyncRotationController asyncRotationController = dc.getAsyncRotationController(); - if (asyncRotationController != null) { - asyncRotationController.accept(navWindow); - } - if (animate) { final NavBarFadeAnimationController controller = new NavBarFadeAnimationController(dc); diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 9b6d4e216744..873d09b42c83 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -1191,6 +1191,7 @@ public class TransitionTests extends WindowTestsBase { final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar"); makeWindowVisible(statusBar); mDisplayContent.getDisplayPolicy().addWindowLw(statusBar, statusBar.mAttrs); + final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar"); final ActivityRecord app = createActivityRecord(mDisplayContent); final Transition transition = app.mTransitionController.createTransition(TRANSIT_OPEN); app.mTransitionController.requestStartTransition(transition, app.getTask(), @@ -1220,9 +1221,17 @@ public class TransitionTests extends WindowTestsBase { mDisplayContent.mTransitionController.dispatchLegacyAppTransitionFinished(app); assertTrue(mDisplayContent.hasTopFixedRotationLaunchingApp()); + // The bar was invisible so it is not handled by the controller. But if it becomes visible + // and drawn before the transition starts, + assertFalse(asyncRotationController.isTargetToken(navBar.mToken)); + navBar.finishDrawing(null /* postDrawTransaction */, Integer.MAX_VALUE); + assertTrue(asyncRotationController.isTargetToken(navBar.mToken)); + player.startTransition(); // Non-app windows should not be collected. assertFalse(mDisplayContent.mTransitionController.isCollecting(statusBar.mToken)); + // Avoid DeviceStateController disturbing the test by triggering another rotation change. + doReturn(false).when(mDisplayContent).updateRotationUnchecked(); onRotationTransactionReady(player, mWm.mTransactionFactory.get()).onTransactionCommitted(); assertEquals(ROTATION_ANIMATION_SEAMLESS, player.mLastReady.getChange( |