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

Commit 07d25048 authored by Chris Li's avatar Chris Li
Browse files

Cleanup TaskFragment reference on remove

Before, we stored organizer created TaskFragment in
WindowOrganizerController, which would only be removed if there is a
request from client.

Now, we also cleanup when the TaskFragment is removed from the display
for any other reason (such as app close),

Fix: 223499926
Test: atest WmTests:TaskFragmentOrganizerControllerTest
Change-Id: Id7c2124bec3e20e9d2466806e20973ec128c463c
parent 87d60042
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -242,7 +242,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {

    /** Client assigned unique token for this TaskFragment if this is created by an organizer. */
    @Nullable
    private IBinder mFragmentToken;
    private final IBinder mFragmentToken;

    /**
     * Whether to delay the last activity of TaskFragment being immediately removed while finishing.
@@ -2383,10 +2383,18 @@ class TaskFragment extends WindowContainer<WindowContainer> {
    void removeImmediately() {
        mIsRemovalRequested = false;
        resetAdjacentTaskFragment();
        cleanUp();
        super.removeImmediately();
        sendTaskFragmentVanished();
    }

    /** Called on remove to cleanup. */
    private void cleanUp() {
        if (mIsEmbedded) {
            mAtmService.mWindowOrganizerController.cleanUpEmbeddedTaskFragment(this);
        }
    }

    @Override
    Dimmer getDimmer() {
        // If the window is in an embedded TaskFragment, we want to dim at the TaskFragment.
+5 −5
Original line number Diff line number Diff line
@@ -140,7 +140,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
                mLastSentTaskFragmentInfos.put(tf, info);
                tf.mTaskFragmentAppearedSent = true;
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception sending onTaskFragmentAppeared callback", e);
                Slog.d(TAG, "Exception sending onTaskFragmentAppeared callback", e);
            }
            onTaskFragmentParentInfoChanged(organizer, tf);
        }
@@ -150,7 +150,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
            try {
                organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo());
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception sending onTaskFragmentVanished callback", e);
                Slog.d(TAG, "Exception sending onTaskFragmentVanished callback", e);
            }
            tf.mTaskFragmentAppearedSent = false;
            mLastSentTaskFragmentInfos.remove(tf);
@@ -175,7 +175,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
                organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo());
                mLastSentTaskFragmentInfos.put(tf, info);
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception sending onTaskFragmentInfoChanged callback", e);
                Slog.d(TAG, "Exception sending onTaskFragmentInfoChanged callback", e);
            }
        }

@@ -198,7 +198,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
                organizer.onTaskFragmentParentInfoChanged(tf.getFragmentToken(), parentConfig);
                mLastSentTaskFragmentParentConfigs.put(tf, new Configuration(parentConfig));
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e);
                Slog.d(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e);
            }
        }

@@ -210,7 +210,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
            try {
                organizer.onTaskFragmentError(errorCallbackToken, exceptionBundle);
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception sending onTaskFragmentError callback", e);
                Slog.d(TAG, "Exception sending onTaskFragmentError callback", e);
            }
        }
    }
+4 −0
Original line number Diff line number Diff line
@@ -1470,6 +1470,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
        return mLaunchTaskFragments.get(tfToken);
    }

    void cleanUpEmbeddedTaskFragment(TaskFragment taskFragment) {
        mLaunchTaskFragments.remove(taskFragment.getFragmentToken());
    }

    static class CallerInfo {
        final int mPid;
        final int mUid;
+42 −9
Original line number Diff line number Diff line
@@ -359,17 +359,11 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
    public void testApplyTransaction_enforceHierarchyChange_createTaskFragment()
            throws RemoteException {
        mController.registerOrganizer(mIOrganizer);
        final ActivityRecord activity = createActivityRecord(mDisplayContent);
        final int uid = Binder.getCallingUid();
        activity.info.applicationInfo.uid = uid;
        activity.getTask().effectiveUid = uid;
        final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent);
        final IBinder fragmentToken = new Binder();
        final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
                mOrganizerToken, fragmentToken, activity.token).build();
        mOrganizer.applyTransaction(mTransaction);

        // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
        mTransaction.createTaskFragment(params);
        createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
        mTransaction.startActivityInTaskFragment(
                mFragmentToken, null /* callerToken */, new Intent(), null /* activityOptions */);
        mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class));
@@ -381,7 +375,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        final TaskFragment taskFragment = mAtm.mWindowOrganizerController
                .getTaskFragment(fragmentToken);
        assertNotNull(taskFragment);
        assertEquals(activity.getTask(), taskFragment.getTask());
        assertEquals(ownerActivity.getTask(), taskFragment.getTask());
    }

    @Test
@@ -523,4 +517,43 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        mController.dispatchPendingEvents();
        verify(mOrganizer).onTaskFragmentInfoChanged(any());
    }

    /**
     * When an embedded {@link TaskFragment} is removed, we should clean up the reference in the
     * {@link WindowOrganizerController}.
     */
    @Test
    public void testTaskFragmentRemoved_cleanUpEmbeddedTaskFragment()
            throws RemoteException {
        mController.registerOrganizer(mIOrganizer);
        final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent);
        final IBinder fragmentToken = new Binder();
        createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
        final TaskFragment taskFragment = mAtm.mWindowOrganizerController
                .getTaskFragment(fragmentToken);

        assertNotNull(taskFragment);

        taskFragment.removeImmediately();

        assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
    }

    /**
     * Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls
     * {@link WindowOrganizerController#applyTransaction} to apply the transaction,
     */
    private void createTaskFragmentFromOrganizer(WindowContainerTransaction wct,
            ActivityRecord ownerActivity, IBinder fragmentToken) {
        final int uid = Binder.getCallingUid();
        ownerActivity.info.applicationInfo.uid = uid;
        ownerActivity.getTask().effectiveUid = uid;
        final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
                mOrganizerToken, fragmentToken, ownerActivity.token).build();
        mOrganizer.applyTransaction(wct);

        // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
        wct.createTaskFragment(params);
    }
}