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

Commit 93a5865a authored by Chris Li's avatar Chris Li
Browse files

Make sure the secondary TaskFragment is above the primary

Before, we may reuse the existing TaskFragment for secondary activity,
which may be below the primary TaskFragment. Now, we make sure the
secondary TaskFragment is always on top.

Bug: 244254584
Test: atest WMJetpackUnitTests:SplitPresenterTest
Test: atest WMJetpackUnitTests:TaskFragmentContainerTest
Change-Id: Id4c240af71fbd344126ae8bbbad57d9c2150d550
parent f2826d86
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -792,6 +792,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
     * Checks if there is a rule to split the two activities. If there is one, puts them into split
     * Checks if there is a rule to split the two activities. If there is one, puts them into split
     * and returns {@code true}. Otherwise, returns {@code false}.
     * and returns {@code true}. Otherwise, returns {@code false}.
     */
     */
    // Suppress GuardedBy warning because lint ask to mark this method as
    // @GuardedBy(mPresenter.mController.mLock), which is mLock itself
    @SuppressWarnings("GuardedBy")
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private boolean putActivitiesIntoSplitIfNecessary(@NonNull WindowContainerTransaction wct,
    private boolean putActivitiesIntoSplitIfNecessary(@NonNull WindowContainerTransaction wct,
            @NonNull Activity primaryActivity, @NonNull Activity secondaryActivity) {
            @NonNull Activity primaryActivity, @NonNull Activity secondaryActivity) {
+6 −2
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ import android.view.WindowInsets;
import android.view.WindowMetrics;
import android.view.WindowMetrics;
import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransaction;


import androidx.annotation.GuardedBy;
import androidx.annotation.IntDef;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;
@@ -171,6 +172,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
     *                          created and the activity will be re-parented to it.
     *                          created and the activity will be re-parented to it.
     * @param rule The split rule to be applied to the container.
     * @param rule The split rule to be applied to the container.
     */
     */
    @GuardedBy("mController.mLock")
    void createNewSplitContainer(@NonNull WindowContainerTransaction wct,
    void createNewSplitContainer(@NonNull WindowContainerTransaction wct,
            @NonNull Activity primaryActivity, @NonNull Activity secondaryActivity,
            @NonNull Activity primaryActivity, @NonNull Activity secondaryActivity,
            @NonNull SplitPairRule rule) {
            @NonNull SplitPairRule rule) {
@@ -187,8 +189,10 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        final TaskFragmentContainer curSecondaryContainer = mController.getContainerWithActivity(
        final TaskFragmentContainer curSecondaryContainer = mController.getContainerWithActivity(
                secondaryActivity);
                secondaryActivity);
        TaskFragmentContainer containerToAvoid = primaryContainer;
        TaskFragmentContainer containerToAvoid = primaryContainer;
        if (rule.shouldClearTop() && curSecondaryContainer != null) {
        if (curSecondaryContainer != null
            // Do not reuse the current TaskFragment if the rule is to clear top.
                && (rule.shouldClearTop() || primaryContainer.isAbove(curSecondaryContainer))) {
            // Do not reuse the current TaskFragment if the rule is to clear top, or if it is below
            // the primary TaskFragment.
            containerToAvoid = curSecondaryContainer;
            containerToAvoid = curSecondaryContainer;
        }
        }
        final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct,
        final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct,
+4 −0
Original line number Original line Diff line number Diff line
@@ -162,4 +162,8 @@ class TaskContainer {
        }
        }
        return null;
        return null;
    }
    }

    int indexOf(@NonNull TaskFragmentContainer child) {
        return mContainers.indexOf(child);
    }
}
}
+12 −0
Original line number Original line Diff line number Diff line
@@ -501,6 +501,18 @@ class TaskFragmentContainer {
        return new Size(maxMinWidth, maxMinHeight);
        return new Size(maxMinWidth, maxMinHeight);
    }
    }


    /** Whether the current TaskFragment is above the {@code other} TaskFragment. */
    boolean isAbove(@NonNull TaskFragmentContainer other) {
        if (mTaskContainer != other.mTaskContainer) {
            throw new IllegalArgumentException(
                    "Trying to compare two TaskFragments in different Task.");
        }
        if (this == other) {
            throw new IllegalArgumentException("Trying to compare a TaskFragment with itself.");
        }
        return mTaskContainer.indexOf(this) > mTaskContainer.indexOf(other);
    }

    @Override
    @Override
    public String toString() {
    public String toString() {
        return toString(true /* includeContainersToFinishOnExit */);
        return toString(true /* includeContainersToFinishOnExit */);
+21 −0
Original line number Original line Diff line number Diff line
@@ -39,6 +39,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
@@ -247,6 +248,26 @@ public class SplitPresenterTest {
        verify(mPresenter).expandTaskFragment(mTransaction, secondaryTf.getTaskFragmentToken());
        verify(mPresenter).expandTaskFragment(mTransaction, secondaryTf.getTaskFragmentToken());
    }
    }


    @Test
    public void testCreateNewSplitContainer_secondaryAbovePrimary() {
        final Activity secondaryActivity = createMockActivity();
        final TaskFragmentContainer bottomTf = mController.newContainer(secondaryActivity, TASK_ID);
        final TaskFragmentContainer primaryTf = mController.newContainer(mActivity, TASK_ID);
        final SplitPairRule rule = new SplitPairRule.Builder(pair ->
                pair.first == mActivity && pair.second == secondaryActivity, pair -> false,
                metrics -> true)
                .setShouldClearTop(false)
                .build();

        mPresenter.createNewSplitContainer(mTransaction, mActivity, secondaryActivity, rule);

        assertEquals(primaryTf, mController.getContainerWithActivity(mActivity));
        final TaskFragmentContainer secondaryTf = mController.getContainerWithActivity(
                secondaryActivity);
        assertNotEquals(bottomTf, secondaryTf);
        assertTrue(secondaryTf.isAbove(primaryTf));
    }

    private Activity createMockActivity() {
    private Activity createMockActivity() {
        final Activity activity = mock(Activity.class);
        final Activity activity = mock(Activity.class);
        final Configuration activityConfig = new Configuration();
        final Configuration activityConfig = new Configuration();
Loading