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

Commit 66e601fb authored by wilsonshih's avatar wilsonshih Committed by Wei Sheng Shih
Browse files

[Shell Transition] Schedule another transition to update visibility.

Activity could call setTranslucent during a transition playing, if the
task of an activity was in transition and that activity should become
invisible, it would be defer until transition finish.
However, since the activity wasn't participant the running transition,
there won't do commitVisibility for it after transition finish.
To correct the visibility status, trigger another transition so the
activities which visibility changed can be collect and commit.

Bug: 246518648
Test: atest testConvertTranslucentOnTranslucentActivity
Test: atest testConvertTranslucentOnNonTopTranslucentActivity
Change-Id: Ic1cda79da37162cca2a1a3fbc73311cc325b3874
parent cee1239a
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -132,8 +132,11 @@ public final class TransitionInfo implements Parcelable {
     */
    public static final int FLAG_IS_BEHIND_STARTING_WINDOW = 1 << 14;

    /** This change happened underneath something else. */
    public static final int FLAG_IS_OCCLUDED = 1 << 15;

    /** The first unused bit. This can be used by remotes to attach custom flags to this change. */
    public static final int FLAG_FIRST_CUSTOM = 1 << 15;
    public static final int FLAG_FIRST_CUSTOM = 1 << 16;

    /** @hide */
    @IntDef(prefix = { "FLAG_" }, value = {
@@ -153,6 +156,7 @@ public final class TransitionInfo implements Parcelable {
            FLAG_CROSS_PROFILE_OWNER_THUMBNAIL,
            FLAG_CROSS_PROFILE_WORK_THUMBNAIL,
            FLAG_IS_BEHIND_STARTING_WINDOW,
            FLAG_IS_OCCLUDED,
            FLAG_FIRST_CUSTOM
    })
    public @interface ChangeFlags {}
@@ -362,6 +366,9 @@ public final class TransitionInfo implements Parcelable {
        if ((flags & FLAG_IS_BEHIND_STARTING_WINDOW) != 0) {
            sb.append(sb.length() == 0 ? "" : "|").append("IS_BEHIND_STARTING_WINDOW");
        }
        if ((flags & FLAG_IS_OCCLUDED) != 0) {
            sb.append(sb.length() == 0 ? "" : "|").append("IS_OCCLUDED");
        }
        if ((flags & FLAG_FIRST_CUSTOM) != 0) {
            sb.append(sb.length() == 0 ? "" : "|").append("FIRST_CUSTOM");
        }
+27 −23
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.fixScale;
import static android.window.TransitionInfo.FLAG_IS_INPUT_METHOD;
import static android.window.TransitionInfo.FLAG_IS_OCCLUDED;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;

@@ -441,24 +442,28 @@ public class Transitions implements RemoteCallable<Transitions> {
            return;
        }

        // apply transfer starting window directly if there is no other task change. Since this
        // is an activity->activity situation, we can detect it by selecting transitions with only
        // 2 changes where neither are tasks and one is a starting-window recipient.
        final int changeSize = info.getChanges().size();
        if (changeSize == 2) {
            boolean nonTaskChange = true;
        boolean taskChange = false;
        boolean transferStartingWindow = false;
        boolean allOccluded = changeSize > 0;
        for (int i = changeSize - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
                if (change.getTaskInfo() != null) {
                    nonTaskChange = false;
                    break;
                }
                if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
                    transferStartingWindow = true;
                }
            }
            if (nonTaskChange && transferStartingWindow) {
            taskChange |= change.getTaskInfo() != null;
            transferStartingWindow |= change.hasFlags(FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT);
            if (!change.hasFlags(FLAG_IS_OCCLUDED)) {
                allOccluded = false;
            }
        }
        // There does not need animation when:
        // A. Transfer starting window. Apply transfer starting window directly if there is no other
        // task change. Since this is an activity->activity situation, we can detect it by selecting
        // transitions with only 2 changes where neither are tasks and one is a starting-window
        // recipient.
        if (!taskChange && transferStartingWindow && changeSize == 2
                // B. It's visibility change if the TRANSIT_TO_BACK/TO_FRONT happened when all
                // changes are underneath another change.
                || ((info.getType() == TRANSIT_TO_BACK || info.getType() == TRANSIT_TO_FRONT)
                && allOccluded)) {
            t.apply();
            finishT.apply();
            // Treat this as an abort since we are bypassing any merge logic and effectively
@@ -466,7 +471,6 @@ public class Transitions implements RemoteCallable<Transitions> {
            onAbort(transitionToken);
            return;
        }
        }

        final ActiveTransition active = mActiveTransitions.get(activeIdx);
        active.mInfo = info;
+41 −2
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IMMERSIVE;
@@ -707,7 +709,26 @@ class ActivityClientController extends IActivityClientController.Stub {
        try {
            synchronized (mGlobalLock) {
                final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
                return r != null && r.setOccludesParent(true);
                // Create a transition if the activity is playing in case the below activity didn't
                // commit invisible. That's because if any activity below this one has changed its
                // visibility while playing transition, there won't able to commit visibility until
                // the running transition finish.
                final Transition transition = r != null
                        && r.mTransitionController.inPlayingTransition(r)
                        ? r.mTransitionController.createTransition(TRANSIT_TO_BACK) : null;
                if (transition != null) {
                    r.mTransitionController.requestStartTransition(transition, null /*startTask */,
                            null /* remoteTransition */, null /* displayChange */);
                }
                final boolean changed = r != null && r.setOccludesParent(true);
                if (transition != null) {
                    if (changed) {
                        r.mTransitionController.setReady(r.getDisplayContent());
                    } else {
                        transition.abort();
                    }
                }
                return changed;
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
@@ -728,7 +749,25 @@ class ActivityClientController extends IActivityClientController.Stub {
                if (under != null) {
                    under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
                }
                return r.setOccludesParent(false);
                // Create a transition if the activity is playing in case the current activity
                // didn't commit invisible. That's because if this activity has changed its
                // visibility while playing transition, there won't able to commit visibility until
                // the running transition finish.
                final Transition transition = r.mTransitionController.inPlayingTransition(r)
                        ? r.mTransitionController.createTransition(TRANSIT_TO_FRONT) : null;
                if (transition != null) {
                    r.mTransitionController.requestStartTransition(transition, null /*startTask */,
                            null /* remoteTransition */, null /* displayChange */);
                }
                final boolean changed = r.setOccludesParent(false);
                if (transition != null) {
                    if (changed) {
                        r.mTransitionController.setReady(r.getDisplayContent());
                    } else {
                        transition.abort();
                    }
                }
                return changed;
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
+11 −5
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_OLD_UNSET;
import static android.window.TransitionInfo.FLAG_IS_OCCLUDED;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ANIM;
@@ -658,7 +660,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
            new WindowState.UpdateReportedVisibilityResults();

    boolean mUseTransferredAnimation;
    int mTransitionChangeFlags;

    /** Whether we need to setup the animation to animate only within the letterbox. */
    private boolean mNeedsLetterboxedAnimation;
@@ -4395,10 +4397,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                    // When transferring an animation, we no longer need to apply an animation to
                    // the token we transfer the animation over. Thus, set this flag to indicate
                    // we've transferred the animation.
                    mUseTransferredAnimation = true;
                    mTransitionChangeFlags |= FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
                } else if (mTransitionController.getTransitionPlayer() != null) {
                    // In the new transit system, just set this every time we transfer the window
                    mUseTransferredAnimation = true;
                    mTransitionChangeFlags |= FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
                }
                // Post cleanup after the visibility and animation are transferred.
                fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
@@ -5247,6 +5249,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        // If in a transition, defer commits for activities that are going invisible
        if (!visible && inTransition()) {
            if (mTransitionController.inPlayingTransition(this)
                    && mTransitionController.isCollecting(this)) {
                mTransitionChangeFlags |= FLAG_IS_OCCLUDED;
            }
            return;
        }
        // If we are preparing an app transition, then delay changing
@@ -5297,7 +5303,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    @Override
    boolean applyAnimation(LayoutParams lp, @TransitionOldType int transit, boolean enter,
            boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {
        if (mUseTransferredAnimation) {
        if ((mTransitionChangeFlags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
            return false;
        }
        // If it was set to true, reset the last request to force the transition.
@@ -5370,7 +5376,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            mWmService.mWindowPlacerLocked.performSurfacePlacement();
        }
        displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
        mUseTransferredAnimation = false;
        mTransitionChangeFlags = 0;

        postApplyAnimation(visible, fromTransition);
    }
+1 −4
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_OCCLUDES_KEYGUARD;
import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
import static android.window.TransitionInfo.FLAG_WILL_IME_SHOWN;

@@ -1879,12 +1878,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            final ActivityRecord record = wc.asActivityRecord();
            if (record != null) {
                parentTask = record.getTask();
                if (record.mUseTransferredAnimation) {
                    flags |= FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
                }
                if (record.mVoiceInteraction) {
                    flags |= FLAG_IS_VOICE_INTERACTION;
                }
                flags |= record.mTransitionChangeFlags;
            }
            final TaskFragment taskFragment = wc.asTaskFragment();
            if (taskFragment != null && task == null) {