Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b3ba0074 authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Only wait for significant windows to unfreeze display" into sc-dev

parents 1325fdd0 1a7dc4c2
Loading
Loading
Loading
Loading
+38 −13
Original line number Diff line number Diff line
@@ -516,7 +516,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp

    /** The delay to avoid toggling the animation quickly. */
    private static final long FIXED_ROTATION_HIDE_ANIMATION_DEBOUNCE_DELAY_MS = 250;
    private FixedRotationAnimationController mFixedRotationAnimationController;
    private FadeRotationAnimationController mFadeRotationAnimationController;

    final FixedRotationTransitionListener mFixedRotationTransitionListener =
            new FixedRotationTransitionListener();
@@ -1590,8 +1590,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    }

    @VisibleForTesting
    @Nullable FixedRotationAnimationController getFixedRotationAnimationController() {
        return mFixedRotationAnimationController;
    @Nullable FadeRotationAnimationController getFadeRotationAnimationController() {
        return mFadeRotationAnimationController;
    }

    void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r) {
@@ -1601,13 +1601,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r, int rotation) {
        if (mFixedRotationLaunchingApp == null && r != null) {
            mWmService.mDisplayNotificationController.dispatchFixedRotationStarted(this, rotation);
            startFixedRotationAnimation(
            startFadeRotationAnimation(
                    // Delay the hide animation to avoid blinking by clicking navigation bar that
                    // may toggle fixed rotation in a short time.
                    r == mFixedRotationTransitionListener.mAnimatingRecents /* shouldDebounce */);
        } else if (mFixedRotationLaunchingApp != null && r == null) {
            mWmService.mDisplayNotificationController.dispatchFixedRotationFinished(this);
            finishFixedRotationAnimationIfPossible();
            finishFadeRotationAnimationIfPossible();
        }
        mFixedRotationLaunchingApp = r;
    }
@@ -1714,12 +1714,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     *
     * @return {@code true} if the animation is executed right now.
     */
    private boolean startFixedRotationAnimation(boolean shouldDebounce) {
    private boolean startFadeRotationAnimation(boolean shouldDebounce) {
        if (shouldDebounce) {
            mWmService.mH.postDelayed(() -> {
                synchronized (mWmService.mGlobalLock) {
                    if (mFixedRotationLaunchingApp != null
                            && startFixedRotationAnimation(false /* shouldDebounce */)) {
                            && startFadeRotationAnimation(false /* shouldDebounce */)) {
                        // Apply the transaction so the animation leash can take effect immediately.
                        getPendingTransaction().apply();
                    }
@@ -1727,23 +1727,41 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            }, FIXED_ROTATION_HIDE_ANIMATION_DEBOUNCE_DELAY_MS);
            return false;
        }
        if (mFixedRotationAnimationController == null) {
            mFixedRotationAnimationController = new FixedRotationAnimationController(this);
            mFixedRotationAnimationController.hide();
        if (mFadeRotationAnimationController == null) {
            mFadeRotationAnimationController = new FadeRotationAnimationController(this);
            mFadeRotationAnimationController.hide();
            return true;
        }
        return false;
    }

    /** Re-show the previously hidden windows if all seamless rotated windows are done. */
    void finishFixedRotationAnimationIfPossible() {
        final FixedRotationAnimationController controller = mFixedRotationAnimationController;
    void finishFadeRotationAnimationIfPossible() {
        final FadeRotationAnimationController controller = mFadeRotationAnimationController;
        if (controller != null && !mDisplayRotation.hasSeamlessRotatingWindow()) {
            controller.show();
            mFixedRotationAnimationController = null;
            mFadeRotationAnimationController = null;
        }
    }

    /** Shows the given window which may be hidden for screen frozen. */
    void finishFadeRotationAnimation(WindowState w) {
        final FadeRotationAnimationController controller = mFadeRotationAnimationController;
        if (controller != null && controller.show(w.mToken)) {
            mFadeRotationAnimationController = null;
        }
    }

    /** Returns {@code true} if the display should wait for the given window to stop freezing. */
    boolean waitForUnfreeze(WindowState w) {
        if (w.mForceSeamlesslyRotate) {
            // The window should look no different before and after rotation.
            return false;
        }
        final FadeRotationAnimationController controller = mFadeRotationAnimationController;
        return controller == null || !controller.isTargetToken(w.mToken);
    }

    void notifyInsetsChanged(Consumer<WindowState> dispatchInsetsChanged) {
        if (mFixedRotationLaunchingApp != null) {
            // The insets state of fixed rotation app is a rotated copy. Make sure the visibilities
@@ -2964,6 +2982,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mScreenRotationAnimation.kill();
        }
        mScreenRotationAnimation = screenRotationAnimation;

        // Hide the windows which are not significant in rotation animation. So that the windows
        // don't need to block the unfreeze time.
        if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()
                && mFadeRotationAnimationController == null) {
            startFadeRotationAnimation(false /* shouldDebounce */);
        }
    }

    public ScreenRotationAnimation getRotationAnimation() {
+2 −2
Original line number Diff line number Diff line
@@ -626,7 +626,7 @@ public class DisplayRotation {
        }, true /* traverseTopToBottom */);
        mSeamlessRotationCount = 0;
        mRotatingSeamlessly = false;
        mDisplayContent.finishFixedRotationAnimationIfPossible();
        mDisplayContent.finishFadeRotationAnimationIfPossible();
    }

    private void prepareSeamlessRotation() {
@@ -717,7 +717,7 @@ public class DisplayRotation {
                    "Performing post-rotate rotation after seamless rotation");
            // Finish seamless rotation.
            mRotatingSeamlessly = false;
            mDisplayContent.finishFixedRotationAnimationIfPossible();
            mDisplayContent.finishFadeRotationAnimationIfPossible();

            updateRotationAndSendNewConfigIfChanged();
        }
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_FIXED_TRANSFORM;

import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

import com.android.internal.R;

import java.util.ArrayList;

/**
 * Controller to fade out and in windows when the display is changing rotation. It can be used for
 * both fixed rotation and normal rotation to hide some non-activity windows. The caller should show
 * the windows until they are drawn with the new rotation.
 */
public class FadeRotationAnimationController extends FadeAnimationController {

    private final ArrayList<WindowToken> mTargetWindowTokens = new ArrayList<>();
    private final WindowManagerService mService;
    /** If non-null, it usually indicates that there will be a screen rotation animation. */
    private final Runnable mFrozenTimeoutRunnable;
    private final WindowToken mNavBarToken;

    public FadeRotationAnimationController(DisplayContent displayContent) {
        super(displayContent);
        mService = displayContent.mWmService;
        mFrozenTimeoutRunnable = mService.mDisplayFrozen ? () -> {
            synchronized (mService.mGlobalLock) {
                displayContent.finishFadeRotationAnimationIfPossible();
                mService.mWindowPlacerLocked.performSurfacePlacement();
            }
        } : null;
        final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
        final WindowState navigationBar = displayPolicy.getNavigationBar();
        if (navigationBar != null) {
            mNavBarToken = navigationBar.mToken;
            final RecentsAnimationController controller = mService.getRecentsAnimationController();
            final boolean navBarControlledByRecents =
                    controller != null && controller.isNavigationBarAttachedToApp();
            // Do not animate movable navigation bar (e.g. non-gesture mode) or when the navigation
            // bar is currently controlled by recents animation.
            if (!displayPolicy.navigationBarCanMove() && !navBarControlledByRecents) {
                mTargetWindowTokens.add(mNavBarToken);
            }
        } else {
            mNavBarToken = null;
        }
        displayContent.forAllWindows(w -> {
            if (w.mActivityRecord == null && w.mHasSurface && !w.mForceSeamlesslyRotate
                    && !w.mIsWallpaper && !w.mIsImWindow && w != navigationBar) {
                mTargetWindowTokens.add(w.mToken);
            }
        }, true /* traverseTopToBottom */);
    }

    /** Applies show animation on the previously hidden window tokens. */
    void show() {
        for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
            final WindowToken windowToken = mTargetWindowTokens.get(i);
            fadeWindowToken(true /* show */, windowToken, ANIMATION_TYPE_FIXED_TRANSFORM);
        }
        mTargetWindowTokens.clear();
        if (mFrozenTimeoutRunnable != null) {
            mService.mH.removeCallbacks(mFrozenTimeoutRunnable);
        }
    }

    /**
     * Returns {@code true} if all target windows are shown. It only takes effects if this
     * controller is created for normal rotation.
     */
    boolean show(WindowToken token) {
        if (mFrozenTimeoutRunnable != null && mTargetWindowTokens.remove(token)) {
            fadeWindowToken(true /* show */, token, ANIMATION_TYPE_FIXED_TRANSFORM);
            if (mTargetWindowTokens.isEmpty()) {
                mService.mH.removeCallbacks(mFrozenTimeoutRunnable);
                return true;
            }
        }
        return false;
    }

    /** Applies hide animation on the window tokens which may be seamlessly rotated later. */
    void hide() {
        for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
            final WindowToken windowToken = mTargetWindowTokens.get(i);
            fadeWindowToken(false /* show */, windowToken, ANIMATION_TYPE_FIXED_TRANSFORM);
        }
        if (mFrozenTimeoutRunnable != null) {
            mService.mH.postDelayed(mFrozenTimeoutRunnable,
                    WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION);
        }
    }

    /** Returns {@code true} if the window is handled by this controller. */
    boolean isTargetToken(WindowToken token) {
        return token == mNavBarToken || mTargetWindowTokens.contains(token);
    }

    @Override
    public Animation getFadeInAnimation() {
        if (mFrozenTimeoutRunnable != null) {
            // Use a shorter animation so it is easier to align with screen rotation animation.
            return AnimationUtils.loadAnimation(mContext, R.anim.screen_rotate_0_enter);
        }
        return super.getFadeInAnimation();
    }

    @Override
    public Animation getFadeOutAnimation() {
        if (mFrozenTimeoutRunnable != null) {
            // Hide the window immediately because screen should have been covered by screenshot.
            return new AlphaAnimation(0 /* fromAlpha */, 0 /* toAlpha */);
        }
        return super.getFadeOutAnimation();
    }
}
+0 −76
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_FIXED_TRANSFORM;

import java.util.ArrayList;

/**
 * Controller to fade out and in system ui when applying a fixed rotation transform to a window
 * token.
 *
 * The system bars will be fade out when the fixed rotation transform starts and will be fade in
 * once all surfaces have been rotated.
 */
public class FixedRotationAnimationController extends FadeAnimationController {

    private final WindowState mStatusBar;
    private final WindowState mNavigationBar;
    private final ArrayList<WindowToken> mAnimatedWindowToken = new ArrayList<>(2);

    public FixedRotationAnimationController(DisplayContent displayContent) {
        super(displayContent);
        final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
        mStatusBar = displayPolicy.getStatusBar();

        final RecentsAnimationController controller =
                displayContent.mWmService.getRecentsAnimationController();
        final boolean navBarControlledByRecents =
                controller != null && controller.isNavigationBarAttachedToApp();
        // Do not animate movable navigation bar (e.g. non-gesture mode) or when the navigation bar
        // is currently controlled by recents animation.
        mNavigationBar = !displayPolicy.navigationBarCanMove()
                && !navBarControlledByRecents ? displayPolicy.getNavigationBar() : null;
    }

    /** Applies show animation on the previously hidden window tokens. */
    void show() {
        for (int i = mAnimatedWindowToken.size() - 1; i >= 0; i--) {
            final WindowToken windowToken = mAnimatedWindowToken.get(i);
            fadeWindowToken(true /* show */, windowToken, ANIMATION_TYPE_FIXED_TRANSFORM);
        }
    }

    /** Applies hide animation on the window tokens which may be seamlessly rotated later. */
    void hide() {
        if (mNavigationBar != null) {
            fadeWindowToken(false /* show */, mNavigationBar.mToken,
                    ANIMATION_TYPE_FIXED_TRANSFORM);
        }
        if (mStatusBar != null) {
            fadeWindowToken(false /* show */, mStatusBar.mToken,
                    ANIMATION_TYPE_FIXED_TRANSFORM);
        }
    }

    @Override
    public void fadeWindowToken(boolean show, WindowToken windowToken, int animationType) {
        super.fadeWindowToken(show, windowToken, animationType);
        mAnimatedWindowToken.add(windowToken);
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ class NonAppWindowAnimationAdapter implements AnimationAdapter {
            final boolean shouldAttachNavBarToApp =
                    displayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition()
                            && service.getRecentsAnimationController() == null
                            && displayContent.getFixedRotationAnimationController() == null;
                            && displayContent.getFadeRotationAnimationController() == null;
            if (shouldAttachNavBarToApp) {
                startNavigationBarWindowAnimation(
                        displayContent, durationHint, statusBarTransitionDelay, targets,
Loading