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

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

Merge "Synchronize rotating non-app windows with fade animation"

parents 3ae3da19 35385b8c
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -6337,7 +6337,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                }
                }
            } else if (w.isDrawn()) {
            } else if (w.isDrawn()) {
                // The starting window for this container is drawn.
                // The starting window for this container is drawn.
                mTaskSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(this);
                startingDisplayed = true;
                startingDisplayed = true;
            }
            }
        }
        }
+53 −9
Original line number Original line Diff line number Diff line
@@ -59,8 +59,13 @@ public class FadeRotationAnimationController extends FadeAnimationController {
    /** The list to store the drawn tokens before the rotation animation starts. */
    /** The list to store the drawn tokens before the rotation animation starts. */
    private ArrayList<WindowToken> mPendingShowTokens;
    private ArrayList<WindowToken> mPendingShowTokens;


    /** It is used when the display has rotated, but some windows fade out in old rotation. */
    /**
    private SeamlessRotator mRotator;
     * The sync transactions of the target windows. It is used when the display has rotated but
     * the windows need to fade out in previous rotation. These transactions will be applied with
     * fade-in animation, so there won't be a flickering such as the windows have redrawn during
     * fading out.
     */
    private ArrayMap<WindowState, SurfaceControl.Transaction> mCapturedDrawTransactions;


    private final int mOriginalRotation;
    private final int mOriginalRotation;
    private final boolean mHasScreenRotationAnimation;
    private final boolean mHasScreenRotationAnimation;
@@ -110,16 +115,36 @@ public class FadeRotationAnimationController extends FadeAnimationController {
                mTargetWindowTokens.put(w.mToken, null);
                mTargetWindowTokens.put(w.mToken, null);
            }
            }
        }, true /* traverseTopToBottom */);
        }, true /* traverseTopToBottom */);

        // The transition sync group may be finished earlier because it doesn't wait for these
        // target windows. But the windows still need to use sync transaction to keep the appearance
        // in previous rotation, so request a no-op sync to keep the state.
        if (!mIsChangeTransition && transitionType != WindowManager.TRANSIT_NONE) {
            for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
                final WindowToken token = mTargetWindowTokens.keyAt(i);
                for (int j = token.getChildCount() - 1; j >= 0; j--) {
                    token.getChildAt(j).applyWithNextDraw(t -> {});
                }
            }
        }
    }
    }


    @Override
    @Override
    public void fadeWindowToken(boolean show, WindowToken windowToken, int animationType) {
    public void fadeWindowToken(boolean show, WindowToken windowToken, int animationType) {
        if (show) {
        if (show) {
            final SurfaceControl leash = mTargetWindowTokens.remove(windowToken);
            // The previous animation leash will be dropped when preparing fade-in animation, so
            if (leash != null && mRotator != null) {
            // simply remove it without restoring the transformation.
                // The leash was unrotated by start transaction of transition. Clear the transform
            mTargetWindowTokens.remove(windowToken);
                // to reshow the window in current rotation.
            if (mCapturedDrawTransactions != null) {
                mRotator.setIdentityMatrix(mDisplayContent.getPendingTransaction(), leash);
                // Unblock the window to draw its latest content with fade-in animation.
                final SurfaceControl.Transaction t = mDisplayContent.getPendingTransaction();
                for (int i = windowToken.getChildCount() - 1; i >= 0; i--) {
                    final SurfaceControl.Transaction drawT =
                            mCapturedDrawTransactions.remove(windowToken.getChildAt(i));
                    if (drawT != null) {
                        t.merge(drawT);
                    }
                }
            }
            }
        }
        }
        super.fadeWindowToken(show, windowToken, animationType);
        super.fadeWindowToken(show, windowToken, animationType);
@@ -225,14 +250,14 @@ public class FadeRotationAnimationController extends FadeAnimationController {
            // Take OPEN/CLOSE transition type as the example, the non-activity windows need to
            // Take OPEN/CLOSE transition type as the example, the non-activity windows need to
            // fade out in previous rotation while display has rotated to the new rotation, so
            // fade out in previous rotation while display has rotated to the new rotation, so
            // their leashes are unrotated with the start transaction.
            // their leashes are unrotated with the start transaction.
            mRotator = new SeamlessRotator(mOriginalRotation,
            final SeamlessRotator rotator = new SeamlessRotator(mOriginalRotation,
                    mDisplayContent.getWindowConfiguration().getRotation(),
                    mDisplayContent.getWindowConfiguration().getRotation(),
                    mDisplayContent.getDisplayInfo(),
                    mDisplayContent.getDisplayInfo(),
                    false /* applyFixedTransformationHint */);
                    false /* applyFixedTransformationHint */);
            for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
            for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
                final SurfaceControl leash = mTargetWindowTokens.valueAt(i);
                final SurfaceControl leash = mTargetWindowTokens.valueAt(i);
                if (leash != null) {
                if (leash != null) {
                    mRotator.applyTransform(t, leash);
                    rotator.applyTransform(t, leash);
                }
                }
            }
            }
            return;
            return;
@@ -280,6 +305,25 @@ public class FadeRotationAnimationController extends FadeAnimationController {
        }
        }
    }
    }


    /** Captures the post draw transaction if the window should update with fade-in animation. */
    boolean handleFinishDrawing(WindowState w, SurfaceControl.Transaction postDrawTransaction) {
        if (mIsChangeTransition || !isTargetToken(w.mToken)) return false;
        if (postDrawTransaction != null && w.mTransitionController.inTransition()) {
            if (mCapturedDrawTransactions == null) {
                mCapturedDrawTransactions = new ArrayMap<>();
            }
            final SurfaceControl.Transaction t = mCapturedDrawTransactions.get(w);
            if (t == null) {
                mCapturedDrawTransactions.put(w, postDrawTransaction);
            } else {
                t.merge(postDrawTransaction);
            }
            return true;
        }
        mDisplayContent.finishFadeRotationAnimation(w.mToken);
        return false;
    }

    @Override
    @Override
    public Animation getFadeInAnimation() {
    public Animation getFadeInAnimation() {
        if (mHasScreenRotationAnimation) {
        if (mHasScreenRotationAnimation) {
+5 −1
Original line number Original line Diff line number Diff line
@@ -3354,8 +3354,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
        for (int i = mChildren.size() - 1; i >= 0; --i) {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            mChildren.get(i).finishSync(outMergedTransaction, cancel);
            mChildren.get(i).finishSync(outMergedTransaction, cancel);
        }
        }
        mSyncState = SYNC_STATE_NONE;
        if (cancel && mSyncGroup != null) mSyncGroup.onCancelSync(this);
        if (cancel && mSyncGroup != null) mSyncGroup.onCancelSync(this);
        clearSyncState();
    }

    void clearSyncState() {
        mSyncState = SYNC_STATE_NONE;
        mSyncGroup = null;
        mSyncGroup = null;
    }
    }


+22 −15
Original line number Original line Diff line number Diff line
@@ -5747,29 +5747,36 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            Slog.i(TAG, "finishDrawing of relaunch: " + this + " " + duration + "ms");
            Slog.i(TAG, "finishDrawing of relaunch: " + this + " " + duration + "ms");
            mActivityRecord.mRelaunchStartTime = 0;
            mActivityRecord.mRelaunchStartTime = 0;
        }
        }

        if (mActivityRecord != null && mAttrs.type == TYPE_APPLICATION_STARTING) {
        executeDrawHandlers(postDrawTransaction);

        final boolean applyPostDrawNow = mClientWasDrawingForSync && postDrawTransaction != null;
        mClientWasDrawingForSync = false;
        if (!onSyncFinishedDrawing()) {
            return mWinAnimator.finishDrawingLocked(postDrawTransaction, applyPostDrawNow);
        }

        if (mActivityRecord != null
                && mTransitionController.isShellTransitionsEnabled()
                && mAttrs.type == TYPE_APPLICATION_STARTING) {
            mWmService.mAtmService.mTaskSupervisor.getActivityMetricsLogger()
            mWmService.mAtmService.mTaskSupervisor.getActivityMetricsLogger()
                    .notifyStartingWindowDrawn(mActivityRecord);
                    .notifyStartingWindowDrawn(mActivityRecord);
        }
        }


        if (postDrawTransaction != null) {
        final boolean hasSyncHandlers = executeDrawHandlers(postDrawTransaction);

        boolean skipLayout = false;
        // Control the timing to switch the appearance of window with different rotations.
        final FadeRotationAnimationController fadeRotationController =
                mDisplayContent.getFadeRotationAnimationController();
        if (fadeRotationController != null
                && fadeRotationController.handleFinishDrawing(this, postDrawTransaction)) {
            // Consume the transaction because the controller will apply it with fade animation.
            // Layout is not needed because the window will be hidden by the fade leash. Clear
            // sync state because its sync transaction doesn't need to be merged to sync group.
            postDrawTransaction = null;
            skipLayout = true;
            clearSyncState();
        } else if (onSyncFinishedDrawing() && postDrawTransaction != null) {
            mSyncTransaction.merge(postDrawTransaction);
            mSyncTransaction.merge(postDrawTransaction);
            // Consume the transaction because the sync group will merge it.
            postDrawTransaction = null;
        }
        }


        mWinAnimator.finishDrawingLocked(null, false /* forceApplyNow */);
        final boolean layoutNeeded =
                mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
        mClientWasDrawingForSync = false;
        // We always want to force a traversal after a finish draw for blast sync.
        // We always want to force a traversal after a finish draw for blast sync.
        return true;
        return !skipLayout && (hasSyncHandlers || layoutNeeded);
    }
    }


    void immediatelyNotifyBlastSync() {
    void immediatelyNotifyBlastSync() {
+8 −1
Original line number Original line Diff line number Diff line
@@ -556,8 +556,15 @@ public class TransitionTests extends WindowTestsBase {


        // The redrawn window will be faded in when the transition finishes. And because this test
        // The redrawn window will be faded in when the transition finishes. And because this test
        // only use one non-activity window, the fade rotation controller should also be cleared.
        // only use one non-activity window, the fade rotation controller should also be cleared.
        statusBar.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
        statusBar.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
        final SurfaceControl.Transaction postDrawTransaction =
                mock(SurfaceControl.Transaction.class);
        final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction);
        assertFalse(layoutNeeded);
        player.finish();
        player.finish();
        // The controller should capture the draw transaction and merge it when preparing to run
        // fade-in animation.
        verify(mDisplayContent.getPendingTransaction()).merge(eq(postDrawTransaction));
        assertNull(mDisplayContent.getFadeRotationAnimationController());
        assertNull(mDisplayContent.getFadeRotationAnimationController());
    }
    }