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

Commit 9de8f4b9 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Support for setting stack windowing mode"

parents d8f2a064 30e441de
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -736,7 +736,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
        // However, the window bounds include the insets, so we need to subtract them here to make
        // them identical.
        if (ssp.hasDockedTask()) {
            if (systemInsets.bottom < windowRect.height()) {
                // Only apply inset if it isn't going to cause the rect height to go negative.
                windowRect.bottom -= systemInsets.bottom;
            }
            systemInsets.bottom = 0;
        }
        calculateWindowStableInsets(systemInsets, windowRect, displayRect);
+56 −27
Original line number Diff line number Diff line
@@ -276,17 +276,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
        if (windowingMode == WINDOWING_MODE_PINNED) {
            return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop);
        }
        final T stack = (T) new ActivityStack(
        return (T) new ActivityStack(
                        this, stackId, mSupervisor, windowingMode, activityType, onTop);

        if (mDisplayId == DEFAULT_DISPLAY && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
            // Make sure recents stack exist when creating a dock stack as it normally needs to be
            // on the other side of the docked stack and we make visibility decisions based on that.
            // TODO: Not sure if this is needed after we change to calculate visibility based on
            // stack z-order vs. id.
            getOrCreateStack(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_RECENTS, onTop);
        }
        return stack;
    }

    /**
@@ -365,6 +356,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
                        + " already exist on display=" + this + " stack=" + stack);
            }
            mSplitScreenPrimaryStack = stack;
            onSplitScreenModeActivated();
        }
    }

@@ -377,6 +369,42 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
            mPinnedStack = null;
        } else if (stack == mSplitScreenPrimaryStack) {
            mSplitScreenPrimaryStack = null;
            // Inform the reset of the system that split-screen mode was dismissed so things like
            // resizing all the other stacks can take place.
            onSplitScreenModeDismissed();
        }
    }

    private void onSplitScreenModeDismissed() {
        mSupervisor.mWindowManager.deferSurfaceLayout();
        try {
            // Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
            for (int i = mStacks.size() - 1; i >= 0; --i) {
                final ActivityStack otherStack = mStacks.get(i);
                if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
                    continue;
                }
                otherStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
            }
        } finally {
            mSupervisor.mWindowManager.continueSurfaceLayout();
        }
    }

    private void onSplitScreenModeActivated() {
        mSupervisor.mWindowManager.deferSurfaceLayout();
        try {
            // Adjust the windowing mode of any affected by split-screen to split-screen secondary.
            for (int i = mStacks.size() - 1; i >= 0; --i) {
                final ActivityStack otherStack = mStacks.get(i);
                if (otherStack == mSplitScreenPrimaryStack
                        || !otherStack.affectedBySplitScreenResize()) {
                    continue;
                }
                otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
            }
        } finally {
            mSupervisor.mWindowManager.continueSurfaceLayout();
        }
    }

@@ -475,22 +503,10 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
                supportsFreeform, supportsPip, activityType)) {
            return windowingMode;
        }
        // Return the display's windowing mode
        return getWindowingMode();
    }

    /** Returns the top visible stack activity type that isn't in the exclude windowing mode. */
    int getTopVisibleStackActivityType(int excludeWindowingMode) {
        for (int i = mStacks.size() - 1; i >= 0; --i) {
            final ActivityStack stack = mStacks.get(i);
            if (stack.getWindowingMode() == excludeWindowingMode) {
                continue;
            }
            if (stack.shouldBeVisible(null /* starting */)) {
                return stack.getActivityType();
            }
        }
        return ACTIVITY_TYPE_UNDEFINED;
        // Try to use the display's windowing mode otherwise fallback to fullscreen.
        windowingMode = getWindowingMode();
        return windowingMode != WINDOWING_MODE_UNDEFINED
                ? windowingMode : WINDOWING_MODE_FULLSCREEN;
    }

    /**
@@ -599,7 +615,20 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
    }

    public void dump(PrintWriter pw, String prefix) {
        pw.println(prefix + "displayId=" + mDisplayId + " mStacks=" + mStacks);
        pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size());
        final String myPrefix = prefix + " ";
        if (mHomeStack != null) {
            pw.println(myPrefix + "mHomeStack=" + mHomeStack);
        }
        if (mRecentsStack != null) {
            pw.println(myPrefix + "mRecentsStack=" + mRecentsStack);
        }
        if (mPinnedStack != null) {
            pw.println(myPrefix + "mPinnedStack=" + mPinnedStack);
        }
        if (mSplitScreenPrimaryStack != null) {
            pw.println(myPrefix + "mSplitScreenPrimaryStack=" + mSplitScreenPrimaryStack);
        }
    }

    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+65 −76
Original line number Diff line number Diff line
@@ -4761,7 +4761,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            throws RemoteException {
        Slog.i(TAG, "Activity tried to startVoiceInteraction");
        synchronized (this) {
            ActivityRecord activity = getFocusedStack().topActivity();
            ActivityRecord activity = getFocusedStack().getTopActivity();
            if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
                throw new SecurityException("Only focused activity can call startVoiceInteraction");
            }
@@ -10436,13 +10436,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                            "exitFreeformMode: You can only go fullscreen from freeform.");
                }
                final ActivityStack fullscreenStack = stack.getDisplay().getOrCreateStack(
                        WINDOWING_MODE_FULLSCREEN, stack.getActivityType(), ON_TOP);
                if (DEBUG_STACK) Slog.d(TAG_STACK, "exitFreeformMode: " + r);
                // TODO: Should just change windowing mode vs. re-parenting...
                r.getTask().reparent(fullscreenStack, ON_TOP,
                        REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "exitFreeformMode");
                stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
@@ -10451,6 +10445,11 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public void setTaskWindowingMode(int taskId, int windowingMode, boolean toTop) {
        if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
            setTaskWindowingModeSplitScreenPrimary(taskId, SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT,
                    toTop, ANIMATE, null /* initialBounds */);
            return;
        }
        enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingMode()");
        synchronized (this) {
            final long ident = Binder.clearCallingIdentity();
@@ -10463,56 +10462,16 @@ public class ActivityManagerService extends IActivityManager.Stub
                if (DEBUG_STACK) Slog.d(TAG_STACK, "setTaskWindowingMode: moving task=" + taskId
                        + " to windowingMode=" + windowingMode + " toTop=" + toTop);
                if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
                    mWindowManager.setDockedStackCreateState(SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT,
                            null /* initialBounds */);
                }
                if (!task.isActivityTypeStandardOrUndefined()) {
                    throw new IllegalArgumentException("setTaskWindowingMode: Attempt to move task "
                            + taskId + " to non-standard windowin mode=" + windowingMode);
                    throw new IllegalArgumentException("setTaskWindowingMode: Attempt to move"
                            + " non-standard task " + taskId + " to windowing mode="
                            + windowingMode);
                }
                final ActivityDisplay display = task.getStack().getDisplay();
                final ActivityStack stack = display.getOrCreateStack(windowingMode,
                        task.getStack().getActivityType(), toTop);
                // TODO: We should just change the windowing mode for the task vs. creating and
                // moving it to a stack.
                task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME,
                        "moveTaskToStack");
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }
    @Override
    public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
        enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
        synchronized (this) {
            long ident = Binder.clearCallingIdentity();
            try {
                final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
                if (task == null) {
                    Slog.w(TAG, "moveTaskToStack: No task for id=" + taskId);
                    return;
                }
                if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
                        + " to stackId=" + stackId + " toTop=" + toTop);
                final ActivityStack stack = mStackSupervisor.getStack(stackId);
                if (stack == null) {
                    throw new IllegalStateException(
                            "moveTaskToStack: No stack for stackId=" + stackId);
                }
                if (!stack.isActivityTypeStandardOrUndefined()) {
                    throw new IllegalArgumentException("moveTaskToStack: Attempt to move task "
                            + taskId + " to stack " + stackId);
                }
                if (stack.inSplitScreenPrimaryWindowingMode()) {
                    mWindowManager.setDockedStackCreateState(
                            SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
                }
                // TODO: Use ActivityStack.setWindowingMode instead of re-parenting.
                task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME,
                        "moveTaskToStack");
            } finally {
@@ -10522,7 +10481,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    }
    /**
     * Moves the input task to the primary-split-screen stack.
     * Moves the specified task to the primary-split-screen stack.
     *
     * @param taskId Id of task to move.
     * @param createMode The mode the primary split screen stack should be created in if it doesn't
@@ -10531,7 +10490,7 @@ public class ActivityManagerService extends IActivityManager.Stub
     *                   and
     *                   {@link android.app.ActivityManager#SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT}
     * @param toTop If the task and stack should be moved to the top.
     * @param animate Whether we should play an animation for the moving the task
     * @param animate Whether we should play an animation for the moving the task.
     * @param initialBounds If the primary stack gets created, it will use these bounds for the
     *                      stack. Pass {@code null} to use default bounds.
     */
@@ -10551,22 +10510,55 @@ public class ActivityManagerService extends IActivityManager.Stub
                if (DEBUG_STACK) Slog.d(TAG_STACK,
                        "setTaskWindowingModeSplitScreenPrimary: moving task=" + taskId
                        + " to createMode=" + createMode + " toTop=" + toTop);
                if (!task.isActivityTypeStandardOrUndefined()) {
                    throw new IllegalArgumentException("setTaskWindowingMode: Attempt to move"
                            + " non-standard task " + taskId + " to split-screen windowing mode");
                }
                mWindowManager.setDockedStackCreateState(createMode, initialBounds);
                final int windowingMode = task.getWindowingMode();
                final ActivityStack stack = task.getStack();
                if (toTop) {
                    stack.moveToFront("setTaskWindowingModeSplitScreenPrimary", task);
                }
                stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, animate);
                return windowingMode != task.getWindowingMode();
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }
                final ActivityDisplay display = task.getStack().getDisplay();
                final ActivityStack stack = display.getOrCreateStack(
                        WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, task.getStack().getActivityType(),
                        toTop);
                // Defer resuming until we move the home stack to the front below
                // TODO: Should just change windowing mode vs. re-parenting...
                final boolean moved = task.reparent(stack, toTop,
                        REPARENT_KEEP_STACK_AT_FRONT, animate, !DEFER_RESUME,
                        "setTaskWindowingModeSplitScreenPrimary");
                if (moved) {
                    mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
    @Override
    public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
        enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
        synchronized (this) {
            long ident = Binder.clearCallingIdentity();
            try {
                final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
                if (task == null) {
                    Slog.w(TAG, "moveTaskToStack: No task for id=" + taskId);
                    return;
                }
                return moved;
                if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
                        + " to stackId=" + stackId + " toTop=" + toTop);
                final ActivityStack stack = mStackSupervisor.getStack(stackId);
                if (stack == null) {
                    throw new IllegalStateException(
                            "moveTaskToStack: No stack for stackId=" + stackId);
                }
                if (!stack.isActivityTypeStandardOrUndefined()) {
                    throw new IllegalArgumentException("moveTaskToStack: Attempt to move task "
                            + taskId + " to stack " + stackId);
                }
                if (stack.inSplitScreenPrimaryWindowingMode()) {
                    mWindowManager.setDockedStackCreateState(
                            SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
                }
                task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME,
                        "moveTaskToStack");
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
@@ -10589,14 +10581,11 @@ public class ActivityManagerService extends IActivityManager.Stub
                    Slog.w(TAG, "dismissSplitScreenMode: primary split-screen stack not found.");
                    return;
                }
                if (toTop) {
                    mStackSupervisor.resizeStackLocked(stack, null /* destBounds */,
                            null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
                            true /* preserveWindows */, true /* allowResizeInDockedMode */,
                            !DEFER_RESUME);
                } else {
                    mStackSupervisor.moveTasksToFullscreenStackLocked(stack, false /* onTop */);
                    stack.moveToFront("dismissSplitScreenMode");
                }
                stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
@@ -12952,7 +12941,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                return false;
            }
            final ActivityRecord activity = focusedStack.topActivity();
            final ActivityRecord activity = focusedStack.getTopActivity();
            if (activity == null) {
                return false;
            }
@@ -12969,7 +12958,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        try {
            synchronized (this) {
                ActivityRecord caller = ActivityRecord.forTokenLocked(token);
                ActivityRecord top = getFocusedStack().topActivity();
                ActivityRecord top = getFocusedStack().getTopActivity();
                if (top != caller) {
                    Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
                            + " is not current top " + top);
@@ -13012,7 +13001,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                "enqueueAssistContext()");
        synchronized (this) {
            ActivityRecord activity = getFocusedStack().topActivity();
            ActivityRecord activity = getFocusedStack().getTopActivity();
            if (activity == null) {
                Slog.w(TAG, "getAssistContextExtras failed: no top activity");
                return null;
+138 −19

File changed.

Preview size limit exceeded, changes collapsed.

+7 −7
Original line number Diff line number Diff line
@@ -2962,6 +2962,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
     * Returns the reparent target stack, creating the stack if necessary.  This call also enforces
     * the various checks on tasks that are going to be reparented from one stack to another.
     */
    // TODO: Look into changing users to this method to ActivityDisplay.resolveWindowingMode()
    ActivityStack getReparentTargetStack(TaskRecord task, ActivityStack stack, boolean toTop) {
        final ActivityStack prevStack = task.getStack();
        final int stackId = stack.mStackId;
@@ -2988,8 +2989,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                    + " reparent task=" + task + " to stackId=" + stackId);
        }

        // Ensure that we aren't trying to move into a freeform stack without freeform
        // support
        // Ensure that we aren't trying to move into a freeform stack without freeform support
        if (stack.getWindowingMode() == WINDOWING_MODE_FREEFORM
                && !mService.mSupportsFreeformWindowManagement) {
            throw new IllegalArgumentException("Device doesn't support freeform, can not reparent"
@@ -3393,7 +3393,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D

        // When launching tasks behind, update the last active time of the top task after the new
        // task has been shown briefly
        final ActivityRecord top = stack.topActivity();
        final ActivityRecord top = stack.getTopActivity();
        if (top != null) {
            top.getTask().touchActiveTime();
        }
@@ -4217,10 +4217,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            }
        }

        final ActivityRecord topActivity = task.getTopActivity();
        if (!task.supportsSplitScreenWindowingMode() || forceNonResizable) {
            // Display a warning toast that we tried to put a non-dockable task in the docked
            // stack.
            // Display a warning toast that we tried to put an app that doesn't support split-screen
            // in split-screen.
            mService.mTaskChangeNotificationController.notifyActivityDismissingDockedStack();

            // Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
@@ -4234,6 +4233,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            return;
        }

        final ActivityRecord topActivity = task.getTopActivity();
        if (topActivity != null && topActivity.isNonResizableOrForcedResizable()
            && !topActivity.noDisplay) {
            final String packageName = topActivity.appInfo.packageName;
@@ -4569,7 +4569,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                final ActivityStack stack = display.getChildAt(j);
                // Get top activity from a visible stack and add it to the list.
                if (stack.shouldBeVisible(null /* starting */)) {
                    final ActivityRecord top = stack.topActivity();
                    final ActivityRecord top = stack.getTopActivity();
                    if (top != null) {
                        if (stack == mFocusedStack) {
                            topActivityTokens.add(0, top.appToken);
Loading