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

Commit 9bc01a81 authored by Jiaquan He's avatar Jiaquan He
Browse files

Add visibility logic for onTopLauncher.

This commit adds visibility logic to:
- force an on-top launcher to show on the top;
- determine visibility of each activity stack;
- determine visibility of each activity.

Bug: 29250513

Change-Id: Ie9d4a4ab5d2c2e0b2e44daa9d9e91c361de5e116
parent e13e9646
Loading
Loading
Loading
Loading
+44 −1
Original line number Diff line number Diff line
@@ -1614,6 +1614,28 @@ final class ActivityStack {
        final ActivityStack focusedStack = mStackSupervisor.getFocusedStack();
        final int focusedStackId = focusedStack.mStackId;

        final TaskRecord topFocusedTask = focusedStack.topTask();
        final boolean isOnTopLauncherFocused = topFocusedTask != null &&
                topFocusedTask.isOnTopLauncher();
        if (isOnTopLauncherFocused) {
            // When an on-top launcher is focused, we should find out whether the freeform stack or
            // the fullscreen stack appears first underneath and has activities to show, and then
            // make it visible.
            boolean behindFullscreenOrFreeForm = false;
            for (int stackBehindFocusedIndex = mStacks.indexOf(focusedStack) - 1;
                 stackBehindFocusedIndex >= 0; stackBehindFocusedIndex--) {
                ActivityStack stack = mStacks.get(stackBehindFocusedIndex);
                if ((stack.mStackId == FREEFORM_WORKSPACE_STACK_ID
                        || stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID)
                        && stack.topRunningActivityLocked() != null) {
                    if (stackIndex == stackBehindFocusedIndex) {
                        return !behindFullscreenOrFreeForm ? STACK_VISIBLE : STACK_INVISIBLE;
                    }
                    behindFullscreenOrFreeForm = true;
                }
            }
        }

        if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID
                && hasVisibleBehindActivity() && focusedStackId == HOME_STACK_ID
                && !focusedStack.topActivity().fullscreen) {
@@ -1803,7 +1825,28 @@ final class ActivityStack {
                // status of an activity in a previous task affects other.
                behindFullscreenActivity = stackVisibility == STACK_INVISIBLE;
            } else if (mStackId == HOME_STACK_ID) {
                if (task.isHomeTask()) {
                if (task.isOnTopLauncher()) {
                    if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "On-top launcher: at " + task
                            + " stackInvisible=" + stackInvisible
                            + " behindFullscreenActivity=" + behindFullscreenActivity);
                    // When an on-top launcher is visible, (e.g. it's on the top of the home stack),
                    // other tasks in the home stack could be visible if and only if:
                    // - some app is running in the docked stack;
                    // - no app is running in either the fullscreen stack or the freefrom stack.
                    final ActivityStack dockedStack = mStackSupervisor.getStack(DOCKED_STACK_ID);
                    final ActivityStack fullscreenStack = mStackSupervisor.getStack(
                            FULLSCREEN_WORKSPACE_STACK_ID);
                    final ActivityStack freeformStack = mStackSupervisor.getStack(
                            FREEFORM_WORKSPACE_STACK_ID);
                    final boolean dockedStackEmpty = dockedStack == null ||
                            dockedStack.topRunningActivityLocked() == null;
                    final boolean fullscreenStackEmpty = fullscreenStack == null ||
                            fullscreenStack.topRunningActivityLocked() == null;
                    final boolean freeformStackEmpty = freeformStack == null ||
                            freeformStack.topRunningActivityLocked() == null;
                    behindFullscreenActivity = dockedStackEmpty || !fullscreenStackEmpty ||
                            !freeformStackEmpty;
                } else if (task.isHomeTask()) {
                    if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
                            + " stackInvisible=" + stackInvisible
                            + " behindFullscreenActivity=" + behindFullscreenActivity);
+5 −1
Original line number Diff line number Diff line
@@ -519,7 +519,11 @@ public class DockedStackDividerController implements DimLayerUser {
        final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
        final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisibleLocked())
                || (homeStackTasks.size() > 1 && topHomeStackTask != homeTask);
        setMinimizedDockedStack(homeVisible && !homeBehind, animate);
        // If the home task is an on-top launcher, we don't want to minimize the docked stack.
        // Instead we want everything underneath that was visible to remain visible.
        // See android.R.attr#onTopLauncher.
        final boolean isOnTopLauncher = topHomeStackTask.isOnTopLauncher();
        setMinimizedDockedStack(homeVisible && !homeBehind && !isOnTopLauncher, animate);
    }

    private boolean isWithinDisplay(Task task) {
+17 −2
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ public class WindowLayersController {
    private ArrayDeque<WindowState> mPinnedWindows = new ArrayDeque<>();
    private ArrayDeque<WindowState> mDockedWindows = new ArrayDeque<>();
    private ArrayDeque<WindowState> mInputMethodWindows = new ArrayDeque<>();
    private ArrayDeque<WindowState> mOnTopLauncherWindows = new ArrayDeque<>();
    private WindowState mDockDivider = null;
    private ArrayDeque<WindowState> mReplacingWindows = new ArrayDeque<>();

@@ -165,6 +166,7 @@ public class WindowLayersController {
        mPinnedWindows.clear();
        mInputMethodWindows.clear();
        mDockedWindows.clear();
        mOnTopLauncherWindows.clear();
        mReplacingWindows.clear();
        mDockDivider = null;
    }
@@ -181,7 +183,14 @@ public class WindowLayersController {
            mInputMethodWindows.add(w);
            return;
        }
        final TaskStack stack = w.getStack();
        final Task task = w.getTask();
        if (task == null) {
            return;
        }
        if (task.isOnTopLauncher()) {
            mOnTopLauncherWindows.add(w);
        }
        final TaskStack stack = task.mStack;
        if (stack == null) {
            return;
        }
@@ -202,7 +211,13 @@ public class WindowLayersController {

        layer = assignAndIncreaseLayerIfNeeded(mDockDivider, layer);

        if (mDockDivider != null && mDockDivider.isVisibleLw()) {
        boolean onTopLauncherVisible = !mOnTopLauncherWindows.isEmpty();
        while (!mOnTopLauncherWindows.isEmpty()) {
            layer = assignAndIncreaseLayerIfNeeded(mOnTopLauncherWindows.remove(), layer);
        }

        // Make sure IME windows are showing above the dock divider and on-top launcher windows.
        if ((mDockDivider != null && mDockDivider.isVisibleLw()) || onTopLauncherVisible) {
            while (!mInputMethodWindows.isEmpty()) {
                final WindowState w = mInputMethodWindows.remove();
                // Only ever move IME windows up, else we brake IME for windows above the divider.