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

Commit 91830b24 authored by Jiaming Liu's avatar Jiaming Liu Committed by Android (Google) Code Review
Browse files

Merge "Fix TF visibility due to other translucent TF in Task" into main

parents bf6295d5 d5b5148b
Loading
Loading
Loading
Loading
+20 −7
Original line number Diff line number Diff line
@@ -1407,14 +1407,22 @@ class TaskFragment extends WindowContainer<WindowContainer> {

            final TaskFragment otherTaskFrag = other.asTaskFragment();
            if (otherTaskFrag != null && otherTaskFrag.hasAdjacentTaskFragment()) {
                // For adjacent TaskFragments, we have assumptions that:
                // 1. A set of adjacent TaskFragments always cover the entire Task window, so that
                // if this TaskFragment is behind a set of opaque TaskFragments, then this
                // TaskFragment is invisible.
                // 2. Adjacent TaskFragments do not overlap, so that if this TaskFragment is behind
                // any translucent TaskFragment in the adjacent set, then this TaskFragment is
                // visible behind translucent.
                if (Flags.allowMultipleAdjacentTaskFragments()) {
                    final boolean hasTraversedAdj = otherTaskFrag.forOtherAdjacentTaskFragments(
                            adjacentTaskFragments::contains);
                    if (hasTraversedAdj) {
                        final boolean isTranslucent = otherTaskFrag.isTranslucent(starting)
                                || otherTaskFrag.forOtherAdjacentTaskFragments(adjacentTf -> {
                                    return adjacentTf.isTranslucent(starting);
                                });
                        final boolean isTranslucent =
                                isBehindTransparentTaskFragment(otherTaskFrag, starting)
                                || otherTaskFrag.forOtherAdjacentTaskFragments(
                                        (Predicate<TaskFragment>) tf ->
                                                isBehindTransparentTaskFragment(tf, starting));
                        if (isTranslucent) {
                            // Can be visible behind a translucent adjacent TaskFragments.
                            gotTranslucentFullscreen = true;
@@ -1426,8 +1434,9 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                    }
                } else {
                    if (adjacentTaskFragments.contains(otherTaskFrag.mAdjacentTaskFragment)) {
                        if (otherTaskFrag.isTranslucent(starting)
                                || otherTaskFrag.mAdjacentTaskFragment.isTranslucent(starting)) {
                        if (isBehindTransparentTaskFragment(otherTaskFrag, starting)
                                || isBehindTransparentTaskFragment(
                                        otherTaskFrag.mAdjacentTaskFragment, starting)) {
                            // Can be visible behind a translucent adjacent TaskFragments.
                            gotTranslucentFullscreen = true;
                            gotTranslucentAdjacent = true;
@@ -1439,7 +1448,6 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                }
                adjacentTaskFragments.add(otherTaskFrag);
            }

        }

        if (!shouldBeVisible) {
@@ -1452,6 +1460,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                : TASK_FRAGMENT_VISIBILITY_VISIBLE;
    }

    private boolean isBehindTransparentTaskFragment(
            @NonNull TaskFragment otherTf, @Nullable ActivityRecord starting) {
        return otherTf.isTranslucent(starting) && getBounds().intersect(otherTf.getBounds());
    }

    private static boolean hasRunningActivity(WindowContainer wc) {
        if (wc.asTaskFragment() != null) {
            return wc.asTaskFragment().topRunningActivity() != null;
+71 −0
Original line number Diff line number Diff line
@@ -45,6 +45,9 @@ import static com.android.server.wm.TaskFragment.EMBEDDED_DIM_AREA_PARENT_TASK;
import static com.android.server.wm.TaskFragment.EMBEDDED_DIM_AREA_TASK_FRAGMENT;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_UNTRUSTED_HOST;
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_INVISIBLE;
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBLE;
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
import static com.android.server.wm.WindowContainer.POSITION_TOP;

import static org.junit.Assert.assertEquals;
@@ -254,6 +257,74 @@ public class TaskFragmentTest extends WindowTestsBase {
        assertEquals(true, activityBelow.isVisibleRequested());
    }

    @Test
    public void testVisibilityBehindOpaqueTaskFragment_withTranslucentTaskFragmentInTask() {
        final Task topTask = createTask(mDisplayContent);
        final Rect top = new Rect();
        final Rect bottom = new Rect();
        topTask.getBounds().splitVertically(top, bottom);

        final TaskFragment taskFragmentA = createTaskFragmentWithActivity(topTask);
        final TaskFragment taskFragmentB = createTaskFragmentWithActivity(topTask);
        final TaskFragment taskFragmentC = createTaskFragmentWithActivity(topTask);

        // B and C split the task window. A is behind B. C is translucent.
        taskFragmentA.setBounds(top);
        taskFragmentB.setBounds(top);
        taskFragmentC.setBounds(bottom);
        taskFragmentA.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        taskFragmentB.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        taskFragmentC.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        taskFragmentB.setAdjacentTaskFragments(
                new TaskFragment.AdjacentSet(taskFragmentB, taskFragmentC));
        doReturn(true).when(taskFragmentC).isTranslucent(any());

        // Ensure the activity below is visible
        topTask.ensureActivitiesVisible(null /* starting */);

        // B and C should be visible. A should be invisible.
        assertEquals(TASK_FRAGMENT_VISIBILITY_INVISIBLE,
                taskFragmentA.getVisibility(null /* starting */));
        assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
                taskFragmentB.getVisibility(null /* starting */));
        assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
                taskFragmentC.getVisibility(null /* starting */));
    }

    @Test
    public void testVisibilityBehindTranslucentTaskFragment() {
        final Task topTask = createTask(mDisplayContent);
        final Rect top = new Rect();
        final Rect bottom = new Rect();
        topTask.getBounds().splitVertically(top, bottom);

        final TaskFragment taskFragmentA = createTaskFragmentWithActivity(topTask);
        final TaskFragment taskFragmentB = createTaskFragmentWithActivity(topTask);
        final TaskFragment taskFragmentC = createTaskFragmentWithActivity(topTask);

        // B and C split the task window. A is behind B. B is translucent.
        taskFragmentA.setBounds(top);
        taskFragmentB.setBounds(top);
        taskFragmentC.setBounds(bottom);
        taskFragmentA.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        taskFragmentB.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        taskFragmentC.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        taskFragmentB.setAdjacentTaskFragments(
                new TaskFragment.AdjacentSet(taskFragmentB, taskFragmentC));
        doReturn(true).when(taskFragmentB).isTranslucent(any());

        // Ensure the activity below is visible
        topTask.ensureActivitiesVisible(null /* starting */);

        // A, B and C should be visible.
        assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
                taskFragmentC.getVisibility(null /* starting */));
        assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
                taskFragmentB.getVisibility(null /* starting */));
        assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                taskFragmentA.getVisibility(null /* starting */));
    }

    @Test
    public void testFindTopNonFinishingActivity_ignoresLaunchedFromBubbleActivities() {
        final ActivityOptions opts = ActivityOptions.makeBasic();