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

Commit af1b500a authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Avoid empty TaskFragment removal affecting playing transition

A transition will apply the finish transaction from
buildFinishTransaction when it finishes. But if there is a parallel
transition runs and finishes before the previous transition, the
layer assignment may have conflict. Even if the transition doesn't
contain changes (shell will abort it), its finish transaction is
still applied by shell's Transitions#onFinish.

E.g. when recents transition (allow parallel) is running, an app
with embedded activities deletes its empty TaskFragment when its
activity is removed by recents (swipe up task view).

By not collect invisible TF and not return WCT effect for empty TF
removal, applyTaskFragmentTransactionLocked can abort the empty
transition in WM core if the effect is none and the transition does
not contain participants.

Fix: 381466040
Flag: EXEMPT bugfix
Test: TaskFragmentOrganizerControllerTest# \
      testApplyTransaction_enforceHierarchyChange_deleteTaskFragment
Change-Id: Ibe86b36ea675330d63b90dda30332d0d4220489d
parent f7c4dc87
Loading
Loading
Loading
Loading
+10 −1
Original line number Original line Diff line number Diff line
@@ -2658,10 +2658,19 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub


    private int deleteTaskFragment(@NonNull TaskFragment taskFragment,
    private int deleteTaskFragment(@NonNull TaskFragment taskFragment,
            @Nullable Transition transition) {
            @Nullable Transition transition) {
        if (transition != null) transition.collectExistenceChange(taskFragment);
        final boolean isEmpty = taskFragment.getNonFinishingActivityCount() == 0;
        if (transition != null && (taskFragment.isVisibleRequested()
                // In case to update existing change type.
                || transition.mChanges.containsKey(taskFragment))) {
            transition.collectExistenceChange(taskFragment);
        }


        mLaunchTaskFragments.remove(taskFragment.getFragmentToken());
        mLaunchTaskFragments.remove(taskFragment.getFragmentToken());
        taskFragment.remove(true /* withTransition */, "deleteTaskFragment");
        taskFragment.remove(true /* withTransition */, "deleteTaskFragment");
        if (isEmpty) {
            // The removal of an empty TaskFragment doesn't affect lifecycle.
            return 0;
        }
        return TRANSACT_EFFECTS_LIFECYCLE;
        return TRANSACT_EFFECTS_LIFECYCLE;
    }
    }


+1 −0
Original line number Original line Diff line number Diff line
@@ -638,6 +638,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
    @Test
    @Test
    public void testApplyTransaction_enforceHierarchyChange_deleteTaskFragment() {
    public void testApplyTransaction_enforceHierarchyChange_deleteTaskFragment() {
        doReturn(true).when(mTaskFragment).isAttached();
        doReturn(true).when(mTaskFragment).isAttached();
        doReturn(1).when(mTaskFragment).getNonFinishingActivityCount();
        mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
        mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);


        // Throw exception if the transaction is trying to change a window that is not organized by
        // Throw exception if the transaction is trying to change a window that is not organized by