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

Commit 1e60e0c6 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Support for pinned stack to always be on-top of visible stacks

Bug: 25006507
Change-Id: I577e11224eead72dbb50def6be30b640707d2187
parent 4503d2f1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5409,7 +5409,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
     * @Return Returns true if the window should show a non client decor.
     **/
    private static boolean hasNonClientDecor(int workspaceId) {
        return workspaceId == FREEFORM_WORKSPACE_STACK_ID || workspaceId == PINNED_STACK_ID;
        return workspaceId == FREEFORM_WORKSPACE_STACK_ID;
    }

    /**
+34 −29
Original line number Diff line number Diff line
@@ -530,16 +530,27 @@ final class ActivityStack {
     * @param task If non-null, the task will be moved to the top of the stack.
     * */
    void moveToFront(String reason, TaskRecord task) {
        if (isAttached()) {
            final ActivityStack lastFocusStack = mStacks.get(mStacks.size() - 1);
            // Need to move this stack to the front before calling
            // {@link ActivityStackSupervisor#setFocusStack} below.
        if (!isAttached()) {
            return;
        }

        mStacks.remove(this);
            mStacks.add(this);
        int addIndex = mStacks.size();

        if (addIndex > 0) {
            final ActivityStack topStack = mStacks.get(addIndex - 1);
            if (topStack.mStackId == PINNED_STACK_ID && topStack != this) {
                // The pinned stack is always the top most stack (always-on-top).
                // So, stack is moved just below the pinned stack.
                addIndex--;
            }
        }

        mStacks.add(addIndex, this);

        // TODO(multi-display): Needs to also work if focus is moving to the non-home display.
        if (isOnHomeDisplay()) {
                mStackSupervisor.setFocusStack(reason, lastFocusStack);
            mStackSupervisor.setFocusStack(reason, this);
        }
        if (task != null) {
            insertTaskAtTop(task, null);
@@ -550,7 +561,6 @@ final class ActivityStack {
            mWindowManager.moveTaskToTop(task.taskId);
        }
    }
    }

    final boolean isAttached() {
        return mStacks != null;
@@ -1304,12 +1314,7 @@ final class ActivityStack {
            return false;
        }

        if (mStackSupervisor.isFrontStack(this)) {
            return true;
        }

        if (mStackId == PINNED_STACK_ID) {
            // Pinned stack is always visible if it exist.
        if (mStackSupervisor.isFrontStack(this) || mStackSupervisor.isFocusedStack(this)) {
            return true;
        }

@@ -2041,7 +2046,7 @@ final class ActivityStack {
            // Have the window manager re-evaluate the orientation of
            // the screen based on the new activity order.
            boolean notUpdated = true;
            if (mStackSupervisor.isFrontStack(this)) {
            if (mStackSupervisor.isFocusedStack(this)) {
                Configuration config = mWindowManager.updateOrientationFromAppTokens(
                        mService.mConfiguration,
                        next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
@@ -2788,7 +2793,7 @@ final class ActivityStack {
    }

    private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
        if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
        if (mStackSupervisor.isFocusedStack(this) && mService.mFocusedActivity == r) {
            ActivityRecord next = topRunningActivityLocked();
            final String myReason = reason + " adjustFocus";
            if (next != r) {
@@ -3395,7 +3400,7 @@ final class ActivityStack {
        if (task != null && task.removeActivity(r)) {
            if (DEBUG_STACK) Slog.i(TAG_STACK,
                    "removeActivityFromHistoryLocked: last activity removed from " + this);
            if (mStackSupervisor.isFrontStack(this) && task == topTask() &&
            if (mStackSupervisor.isFocusedStack(this) && task == topTask() &&
                    task.isOverHomeStack()) {
                mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason);
            }
@@ -4569,7 +4574,7 @@ final class ActivityStack {
        if (mTaskHistory.isEmpty()) {
            if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
            // We only need to adjust focused stack if this stack is in focus.
            if (isOnHomeDisplay() && mStackSupervisor.isFrontStack(this)) {
            if (isOnHomeDisplay() && mStackSupervisor.isFocusedStack(this)) {
                String myReason = reason + " leftTaskHistoryEmpty";
                if (mFullscreen || !adjustFocusToNextVisibleStackLocked(null, myReason)) {
                    mStackSupervisor.moveHomeStackToFront(myReason);
@@ -4677,7 +4682,7 @@ final class ActivityStack {
            return;
        }

        final boolean wasFocused = mStackSupervisor.isFrontStack(prevStack)
        final boolean wasFocused = mStackSupervisor.isFocusedStack(prevStack)
                && (mStackSupervisor.topRunningActivityLocked() == r);
        final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r);

+27 −26
Original line number Diff line number Diff line
@@ -458,10 +458,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
        return mLastFocusedStack;
    }

    /** Top of all visible stacks is/should always be equal to the focused stack.
     * Use {@link ActivityStack#isStackVisibleLocked} to determine if a specific
     * stack is visible or not. */
    boolean isFrontStack(ActivityStack stack) {
    boolean isFocusedStack(ActivityStack stack) {
        if (stack == null) {
            return false;
        }
@@ -473,19 +470,23 @@ public final class ActivityStackSupervisor implements DisplayListener {
        return stack == mFocusedStack;
    }

    void setFocusStack(String reason, ActivityStack lastFocusedStack) {
        ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
        final int topNdx = stacks.size() - 1;
        if (topNdx <= 0) {
            return;
    /** The top most stack. */
    boolean isFrontStack(ActivityStack stack) {
        if (stack == null) {
            return false;
        }

        final ActivityStack topStack = stacks.get(topNdx);
        mFocusedStack = topStack;
        if (lastFocusedStack != null) {
            mLastFocusedStack = lastFocusedStack;
        final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
        if (parent != null) {
            stack = parent.task.stack;
        }
        return stack == mHomeStack.mStacks.get((mHomeStack.mStacks.size() - 1));
    }

    void setFocusStack(String reason, ActivityStack focusedStack) {
        mLastFocusedStack = mFocusedStack;
        mFocusedStack = focusedStack;

        EventLogTags.writeAmFocusedStack(
                mCurrentUser, mFocusedStack == null ? -1 : mFocusedStack.getStackId(),
                mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), reason);
@@ -642,7 +643,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (!isFrontStack(stack)) {
                if (!isFocusedStack(stack)) {
                    continue;
                }
                ActivityRecord hr = stack.topRunningActivityLocked();
@@ -673,7 +674,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (!isFrontStack(stack) || stack.numActivities() == 0) {
                if (!isFocusedStack(stack) || stack.numActivities() == 0) {
                    continue;
                }
                final ActivityRecord resumedActivity = stack.mResumedActivity;
@@ -692,7 +693,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (isFrontStack(stack)) {
                if (isFocusedStack(stack)) {
                    final ActivityRecord r = stack.mResumedActivity;
                    if (r != null && r.state != RESUMED) {
                        return false;
@@ -737,7 +738,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (!isFrontStack(stack) && stack.mResumedActivity != null) {
                if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
                    if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
                            " mResumedActivity=" + stack.mResumedActivity);
                    someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
@@ -1374,7 +1375,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
        // launching the initial activity (that is, home), so that it can have
        // a chance to initialize itself while in the background, making the
        // switch back to it faster and look better.
        if (isFrontStack(stack)) {
        if (isFocusedStack(stack)) {
            mService.startSetupActivityLocked();
        }

@@ -2621,7 +2622,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
            r.idle = true;

            //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
            if (isFrontStack(r.task.stack) || fromTimeout) {
            if (isFocusedStack(r.task.stack) || fromTimeout) {
                booting = checkFinishBootingLocked();
            }
        }
@@ -2773,7 +2774,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (isFrontStack(stack)) {
                if (isFocusedStack(stack)) {
                    if (stack.mResumedActivity != null) {
                        fgApp = stack.mResumedActivity.app;
                    } else if (stack.mPausingActivity != null) {
@@ -2805,7 +2806,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
        }
        // Do targetStack first.
        boolean result = false;
        if (isFrontStack(targetStack)) {
        if (isFocusedStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

@@ -2817,7 +2818,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
                    // Already started above.
                    continue;
                }
                if (isFrontStack(stack)) {
                if (isFocusedStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
@@ -3243,7 +3244,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
    ActivityStack moveTaskToStackUncheckedLocked(
            TaskRecord task, int stackId, boolean toTop, boolean forceFocus, String reason) {
        final ActivityRecord r = task.getTopActivity();
        final boolean wasFocused = isFrontStack(task.stack) && (topRunningActivityLocked() == r);
        final boolean wasFocused = isFocusedStack(task.stack) && (topRunningActivityLocked() == r);
        final boolean wasResumed = wasFocused && (task.stack.mResumedActivity == r);

        final boolean resizeable = task.mResizeable;
@@ -3469,7 +3470,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                stack.awakeFromSleepingLocked();
                if (isFrontStack(stack)) {
                if (isFocusedStack(stack)) {
                    resumeTopActivitiesLocked();
                }
            }
@@ -3536,7 +3537,7 @@ public final class ActivityStackSupervisor implements DisplayListener {

    boolean reportResumedActivityLocked(ActivityRecord r) {
        final ActivityStack stack = r.task.stack;
        if (isFrontStack(stack)) {
        if (isFocusedStack(stack)) {
            mService.updateUsageStats(r, true);
        }
        if (allResumedActivitiesComplete()) {
@@ -3829,7 +3830,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
                final ActivityStack stack = stacks.get(stackNdx);
                final ActivityRecord r = stack.topRunningActivityLocked();
                final ActivityState state = r == null ? DESTROYED : r.state;
                if (isFrontStack(stack)) {
                if (isFocusedStack(stack)) {
                    if (r == null) Slog.e(TAG,
                            "validateTop...: null top activity, stack=" + stack);
                    else {
+22 −2
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ package com.android.server.wm;

import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.app.ActivityManager.HOME_STACK_ID;

import static android.app.ActivityManager.PINNED_STACK_ID;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerService.TAG;
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
@@ -243,10 +243,30 @@ class DisplayContent {
    }

    void moveStack(TaskStack stack, boolean toTop) {
        if (stack.mStackId == PINNED_STACK_ID && !toTop) {
            // Pinned stack is always-on-top silly...
            Slog.w(TAG, "Ignoring move of always-on-top stack=" + stack + " to bottom");
            return;
        }

        if (!mStacks.remove(stack)) {
            Slog.wtf(TAG, "moving stack that was not added: " + stack, new Throwable());
        }
        mStacks.add(toTop ? mStacks.size() : 0, stack);

        int addIndex = toTop ? mStacks.size() : 0;

        if (toTop
                && mService.isStackVisibleLocked(PINNED_STACK_ID)
                && stack.mStackId != PINNED_STACK_ID) {
            // The pinned stack is always the top most stack (always-on-top) when it is visible.
            // So, stack is moved just below the pinned stack.
            addIndex--;
            TaskStack topStack = mStacks.get(addIndex);
            if (topStack.mStackId != PINNED_STACK_ID) {
                throw new IllegalStateException("Pinned stack isn't top stack??? " + mStacks);
            }
        }
        mStacks.add(addIndex, stack);
    }

    void detachStack(TaskStack stack) {
+8 −6
Original line number Diff line number Diff line
@@ -3284,10 +3284,8 @@ public class WindowManagerService extends IWindowManager.Stub
            }
        }

        final TaskStack dockedStack = mStackIdToStack.get(DOCKED_STACK_ID);
        final TaskStack freeformStack = mStackIdToStack.get(FREEFORM_WORKSPACE_STACK_ID);
        if ((dockedStack != null && dockedStack.isVisibleLocked())
                || (freeformStack != null && freeformStack.isVisibleLocked())) {
        if (isStackVisibleLocked(DOCKED_STACK_ID)
                || isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
            // We don't let app affect the system orientation when in freeform or docked mode since
            // they don't occupy the entire display and their request can conflict with other apps.
            return SCREEN_ORIENTATION_UNSPECIFIED;
@@ -4518,6 +4516,11 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    boolean isStackVisibleLocked(int stackId) {
        final TaskStack stack = mStackIdToStack.get(stackId);
        return (stack != null && stack.isVisibleLocked());
    }

    public void setDockedStackCreateMode(int mode) {
        synchronized (mWindowMap) {
            sDockedStackCreateMode = mode;
@@ -10214,8 +10217,7 @@ public class WindowManagerService extends IWindowManager.Stub
        @Override
        public boolean isStackVisible(int stackId) {
            synchronized (mWindowMap) {
                final TaskStack stack = mStackIdToStack.get(stackId);
                return (stack != null && stack.isVisibleLocked());
                return WindowManagerService.this.isStackVisibleLocked(stackId);
            }
        }
    }