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

Commit 72a84350 authored by Andrii Kulian's avatar Andrii Kulian Committed by Android (Google) Code Review
Browse files

Merge "Never resume activities that are partially occluded"

parents 328c096a 0c869cc2
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
import static com.android.server.am.ActivityDisplayProto.STACKS;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
@@ -575,7 +576,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
            final ActivityStack stack = mStacks.get(stackNdx);
            final ActivityRecord resumedActivity = stack.getResumedActivity();
            if (resumedActivity != null
                    && (!stack.shouldBeVisible(resuming) || !stack.isFocusable())) {
                    && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
                        || !stack.isFocusable())) {
                if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
                        " mResumedActivity=" + resumedActivity);
                someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
+5 −2
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
import static com.android.server.wm.ActivityStack.LAUNCH_TICK;
import static com.android.server.wm.ActivityStack.LAUNCH_TICK_MSG;
import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
@@ -2054,8 +2055,10 @@ final class ActivityRecord extends ConfigurationContainer {
     * @param activeActivity the activity that is active or just completed pause action. We won't
     *                       resume if this activity is active.
     */
    private boolean shouldResumeActivity(ActivityRecord activeActivity) {
        return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED);
    @VisibleForTesting
    boolean shouldResumeActivity(ActivityRecord activeActivity) {
        return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED)
                && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE;
    }

    /**
+75 −15
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ import static com.android.server.wm.RootActivityContainer.FindTaskResult;

import static java.lang.Integer.MAX_VALUE;

import android.annotation.IntDef;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -223,6 +224,22 @@ class ActivityStack extends ConfigurationContainer {
    // How many activities have to be scheduled to stop to force a stop pass.
    private static final int MAX_STOPPING_TO_FORCE = 3;

    @IntDef(prefix = {"STACK_VISIBILITY"}, value = {
            STACK_VISIBILITY_VISIBLE,
            STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
            STACK_VISIBILITY_INVISIBLE,
    })
    @interface StackVisibility {}

    /** Stack is visible. No other stacks on top that fully or partially occlude it. */
    static final int STACK_VISIBILITY_VISIBLE = 0;

    /** Stack is partially occluded by other translucent stack(s) on top of it. */
    static final int STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT = 1;

    /** Stack is completely invisible. */
    static final int STACK_VISIBILITY_INVISIBLE = 2;

    @Override
    protected int getChildCount() {
        return mTaskHistory.size();
@@ -1959,14 +1976,28 @@ class ActivityStack extends ConfigurationContainer {
     * @param starting The currently starting activity or null if there is none.
     */
    boolean shouldBeVisible(ActivityRecord starting) {
        return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
    }

    /**
     * Returns true if the stack should be visible.
     *
     * @param starting The currently starting activity or null if there is none.
     */
    @StackVisibility
    int getVisibility(ActivityRecord starting) {
        if (!isAttached() || mForceHidden) {
            return false;
            return STACK_VISIBILITY_INVISIBLE;
        }

        final ActivityDisplay display = getDisplay();
        boolean gotSplitScreenStack = false;
        boolean gotOpaqueSplitScreenPrimary = false;
        boolean gotOpaqueSplitScreenSecondary = false;
        boolean gotTranslucentFullscreen = false;
        boolean gotTranslucentSplitScreenPrimary = false;
        boolean gotTranslucentSplitScreenSecondary = false;
        boolean shouldBeVisible = true;
        final int windowingMode = getWindowingMode();
        final boolean isAssistantType = isActivityTypeAssistant();
        for (int i = display.getChildCount() - 1; i >= 0; --i) {
@@ -1975,8 +2006,9 @@ class ActivityStack extends ConfigurationContainer {
            if (other == this) {
                // Should be visible if there is no other stack occluding it, unless it doesn't
                // have any running activities, not starting one and not home stack.
                return hasRunningActivities || isInStackLocked(starting) != null
                shouldBeVisible = hasRunningActivities || isInStackLocked(starting) != null
                        || isActivityTypeHome();
                break;
            }

            if (!hasRunningActivities) {
@@ -1997,50 +2029,78 @@ class ActivityStack extends ConfigurationContainer {
                    if (activityType == ACTIVITY_TYPE_HOME
                            || (activityType == ACTIVITY_TYPE_ASSISTANT
                                && mWindowManager.getRecentsAnimationController() != null)) {
                       return true;
                        break;
                    }
                }
                if (other.isStackTranslucent(starting)) {
                    // Can be visible behind a translucent fullscreen stack.
                    gotTranslucentFullscreen = true;
                    continue;
                }
                return false;
                return STACK_VISIBILITY_INVISIBLE;
            } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                    && !gotOpaqueSplitScreenPrimary) {
                gotSplitScreenStack = true;
                gotOpaqueSplitScreenPrimary =
                        !other.isStackTranslucent(starting);
                gotTranslucentSplitScreenPrimary = other.isStackTranslucent(starting);
                gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
                if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                        && gotOpaqueSplitScreenPrimary) {
                    // Can not be visible behind another opaque stack in split-screen-primary mode.
                    return false;
                    return STACK_VISIBILITY_INVISIBLE;
                }
            } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
                    && !gotOpaqueSplitScreenSecondary) {
                gotSplitScreenStack = true;
                gotOpaqueSplitScreenSecondary =
                        !other.isStackTranslucent(starting);
                gotTranslucentSplitScreenSecondary = other.isStackTranslucent(starting);
                gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
                if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
                        && gotOpaqueSplitScreenSecondary) {
                    // Can not be visible behind another opaque stack in split-screen-secondary mode.
                    return false;
                    return STACK_VISIBILITY_INVISIBLE;
                }
            }
            if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) {
                // Can not be visible if we are in split-screen windowing mode and both halves of
                // the screen are opaque.
                return false;
                return STACK_VISIBILITY_INVISIBLE;
            }
            if (isAssistantType && gotSplitScreenStack) {
                // Assistant stack can't be visible behind split-screen. In addition to this not
                // making sense, it also works around an issue here we boost the z-order of the
                // assistant window surfaces in window manager whenever it is visible.
                return false;
                return STACK_VISIBILITY_INVISIBLE;
            }
        }

        // Well, nothing is stopping you from being visible...
        return true;
        if (!shouldBeVisible) {
            return STACK_VISIBILITY_INVISIBLE;
        }

        // Handle cases when there can be a translucent split-screen stack on top.
        switch (windowingMode) {
            case WINDOWING_MODE_FULLSCREEN:
                if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) {
                    // At least one of the split-screen stacks that covers this one is translucent.
                    return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
                }
                break;
            case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
                if (gotTranslucentSplitScreenPrimary) {
                    // Covered by translucent primary split-screen on top.
                    return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
                }
                break;
            case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
                if (gotTranslucentSplitScreenSecondary) {
                    // Covered by translucent secondary split-screen on top.
                    return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
                }
                break;
        }

        // Lastly - check if there is a translucent fullscreen stack on top.
        return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
                : STACK_VISIBILITY_VISIBLE;
    }

    final int rankTaskLayers(int baseLayer) {
+19 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
@@ -34,6 +35,9 @@ import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -380,6 +384,21 @@ public class ActivityRecordTests extends ActivityTestsBase {
        assertEquals(true, mActivity.shouldMakeActive(null /* activeActivity */));
    }

    @Test
    public void testShouldResume_stackVisibility() {
        mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
        spyOn(mStack);

        doReturn(STACK_VISIBILITY_VISIBLE).when(mStack).getVisibility(null);
        assertEquals(true, mActivity.shouldResumeActivity(null /* activeActivity */));

        doReturn(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT).when(mStack).getVisibility(null);
        assertEquals(false, mActivity.shouldResumeActivity(null /* activeActivity */));

        doReturn(STACK_VISIBILITY_INVISIBLE).when(mStack).getVisibility(null);
        assertEquals(false, mActivity.shouldResumeActivity(null /* activeActivity */));
    }

    @Test
    public void testPushConfigurationWhenLaunchTaskBehind() throws Exception {
        mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
+153 −0
Original line number Diff line number Diff line
@@ -37,6 +37,9 @@ import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;

@@ -321,12 +324,23 @@ public class ActivityStackTests extends ActivityTestsBase {
        assertFalse(homeStack.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
        assertEquals(STACK_VISIBILITY_INVISIBLE, homeStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                splitScreenPrimary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                splitScreenSecondary.getVisibility(null /* starting */));

        // Home stack should be visible if one of the halves of split-screen is translucent.
        splitScreenPrimary.setIsTranslucent(true);
        assertTrue(homeStack.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                homeStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                splitScreenPrimary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                splitScreenSecondary.getVisibility(null /* starting */));

        final TestActivityStack splitScreenSecondary2 =
                createStackForShouldBeVisibleTest(mDefaultDisplay,
@@ -336,12 +350,20 @@ public class ActivityStackTests extends ActivityTestsBase {
        splitScreenSecondary2.setIsTranslucent(false);
        assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
        assertEquals(STACK_VISIBILITY_INVISIBLE,
                splitScreenSecondary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                splitScreenSecondary2.getVisibility(null /* starting */));

        // First split-screen secondary should be visible behind another translucent split-screen
        // secondary.
        splitScreenSecondary2.setIsTranslucent(true);
        assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                splitScreenSecondary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                splitScreenSecondary2.getVisibility(null /* starting */));

        final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
@@ -352,6 +374,14 @@ public class ActivityStackTests extends ActivityTestsBase {
        assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
        assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
        assertFalse(splitScreenSecondary2.shouldBeVisible(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                assistantStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_INVISIBLE,
                splitScreenPrimary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_INVISIBLE,
                splitScreenSecondary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_INVISIBLE,
                splitScreenSecondary2.getVisibility(null /* starting */));

        // Split-screen stacks should be visible behind a translucent fullscreen stack.
        assistantStack.setIsTranslucent(true);
@@ -359,6 +389,14 @@ public class ActivityStackTests extends ActivityTestsBase {
        assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                assistantStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                splitScreenPrimary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                splitScreenSecondary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                splitScreenSecondary2.getVisibility(null /* starting */));

        // Assistant stack shouldn't be visible behind translucent split-screen stack
        assistantStack.setIsTranslucent(false);
@@ -369,6 +407,113 @@ public class ActivityStackTests extends ActivityTestsBase {
        assertFalse(assistantStack.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
        assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
        assertEquals(STACK_VISIBILITY_INVISIBLE,
                assistantStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                splitScreenPrimary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_INVISIBLE,
                splitScreenSecondary.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                splitScreenSecondary2.getVisibility(null /* starting */));
    }

    @Test
    public void testGetVisibility_FullscreenBehindTranslucent() {
        final TestActivityStack bottomStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        false /* translucent */);
        final TestActivityStack translucentStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        true /* translucent */);

        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                bottomStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                translucentStack.getVisibility(null /* starting */));
    }

    @Test
    public void testGetVisibility_FullscreenBehindTranslucentAndOpaque() {
        final TestActivityStack bottomStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        false /* translucent */);
        final TestActivityStack translucentStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        true /* translucent */);
        final TestActivityStack opaqueStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        false /* translucent */);

        assertEquals(STACK_VISIBILITY_INVISIBLE, bottomStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_INVISIBLE,
                translucentStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE, opaqueStack.getVisibility(null /* starting */));
    }

    @Test
    public void testGetVisibility_FullscreenBehindOpaqueAndTranslucent() {
        final TestActivityStack bottomStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        false /* translucent */);
        final TestActivityStack opaqueStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        false /* translucent */);
        final TestActivityStack translucentStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        true /* translucent */);

        assertEquals(STACK_VISIBILITY_INVISIBLE, bottomStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                opaqueStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                translucentStack.getVisibility(null /* starting */));
    }

    @Test
    public void testGetVisibility_FullscreenTranslucentBehindTranslucent() {
        final TestActivityStack bottomTranslucentStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        true /* translucent */);
        final TestActivityStack translucentStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        true /* translucent */);

        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                bottomTranslucentStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                translucentStack.getVisibility(null /* starting */));
    }

    @Test
    public void testGetVisibility_FullscreenTranslucentBehindOpaque() {
        final TestActivityStack bottomTranslucentStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        true /* translucent */);
        final TestActivityStack opaqueStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        false /* translucent */);

        assertEquals(STACK_VISIBILITY_INVISIBLE,
                bottomTranslucentStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE, opaqueStack.getVisibility(null /* starting */));
    }

    @Test
    public void testGetVisibility_FullscreenBehindTranslucentAndPip() {
        final TestActivityStack bottomStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        false /* translucent */);
        final TestActivityStack translucentStack =
                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                        true /* translucent */);
        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);

        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
                bottomStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE,
                translucentStack.getVisibility(null /* starting */));
        assertEquals(STACK_VISIBILITY_VISIBLE, pinnedStack.getVisibility(null /* starting */));
    }

    @Test
@@ -628,6 +773,14 @@ public class ActivityStackTests extends ActivityTestsBase {
        assertFalse(assistantStack.shouldBeVisible(null /* starting */));
    }

    private TestActivityStack createStandardStackForVisibilityTest(int windowingMode,
            boolean translucent) {
        final TestActivityStack stack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                windowingMode, ACTIVITY_TYPE_STANDARD, true /* onTop */);
        stack.setIsTranslucent(translucent);
        return stack;
    }

    @SuppressWarnings("TypeParameterUnusedInFormals")
    private <T extends ActivityStack> T createStackForShouldBeVisibleTest(
            ActivityDisplay display, int windowingMode, int activityType, boolean onTop) {