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

Commit a6a11712 authored by Garfield Tan's avatar Garfield Tan
Browse files

Notify config changes caused orientation changes

When windowing mode changes the requested orientation of tasks can
change as well so let's notify upward the hierarchy if it does.

In RVC we also added a special logic for display rotation when PIP is
enabled which I encapsulated here too.

Also change the check of matchParentsBounds() to check resolved bounds
because when a freeform task is maximized its requested bounds are still
preserved, but resolved bounds are empty (if not letterboxed).

Addtionally it cleans up some usage of matchParentsBounds().

Note this CL doesn't fix the case where the requested orientation isn't
reported if the task is letterboxed.

Bug: 156423660
Test: orientation change is notified when it changes.
Test: WM smoke tests.
Test: atest TaskRecordTests
Test: atest DisplayContentTests#testNoFixedRotationWithPip
Change-Id: Ieeb638a54441071754943f18eef74572e95f90db
parent b70873a5
Loading
Loading
Loading
Loading
+4 −32
Original line number Diff line number Diff line
@@ -161,7 +161,6 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

@@ -610,7 +609,8 @@ class ActivityStack extends Task {
        // Update bounds if applicable
        boolean hasNewOverrideBounds = false;
        // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
        if ((overrideWindowingMode != WINDOWING_MODE_PINNED) && !matchParentBounds()) {
        if ((overrideWindowingMode != WINDOWING_MODE_PINNED)
                && !getRequestedOverrideBounds().isEmpty()) {
            // If the parent (display) has rotated, rotate our bounds to best-fit where their
            // bounds were on the pre-rotated display.
            final int newRotation = getWindowConfiguration().getRotation();
@@ -762,41 +762,12 @@ class ActivityStack extends Task {
                        + " while there is already one isn't currently supported");
                //return;
            }

            mTmpRect2.setEmpty();
            if (windowingMode != WINDOWING_MODE_FULLSCREEN) {
                if (matchParentBounds()) {
                    mTmpRect2.setEmpty();
                } else {
                    getRawBounds(mTmpRect2);
                }
            }

            if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) {
                resize(mTmpRect2, false /*preserveWindows*/, true /*deferResume*/);
            }
        } finally {
            mAtmService.continueWindowLayout();
        }

        mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
        mRootWindowContainer.resumeFocusedStacksTopActivities();

        final boolean pinnedToFullscreen = currentMode == WINDOWING_MODE_PINNED
                && windowingMode == WINDOWING_MODE_FULLSCREEN;
        if (pinnedToFullscreen && topActivity != null && !isForceHidden()) {
            mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(true);
            try {
                // Report orientation as soon as possible so that the display can freeze earlier if
                // the display orientation will be changed. Because the surface bounds of activity
                // may have been set to fullscreen but the activity hasn't redrawn its content yet,
                // the rotation animation needs to capture snapshot earlier to avoid animating from
                // an intermediate state.
                topActivity.reportDescendantOrientationChangeIfNeeded();
            } finally {
                mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(false);
            }
        }
    }

    @Override
@@ -2900,7 +2871,8 @@ class ActivityStack extends Task {
                .isKeyguardOrAodShowing(displayId);
        if (!mStackSupervisor.getLaunchParamsController()
                .layoutTask(task, info.windowLayout, activity, source, options)
                && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
                && !getRequestedOverrideBounds().isEmpty()
                && task.isResizeable() && !isLockscreenShown) {
            task.setBounds(getRequestedOverrideBounds());
        }

+7 −6
Original line number Diff line number Diff line
@@ -203,15 +203,16 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
    }

    /**
     * Indicates whether this container has not requested any bounds different from its parent. In
     * this case, it will inherit the bounds of the first ancestor which specifies a bounds subject
     * to policy constraints.
     * Indicates whether this container chooses not to override any bounds from its parent, either
     * because it doesn't request to override them or the request is dropped during configuration
     * resolution. In this case, it will inherit the bounds of the first ancestor which specifies a
     * bounds subject to policy constraints.
     *
     * @return {@code true} if no explicit bounds have been requested at this container level.
     *         {@code false} otherwise.
     * @return {@code true} if this container level uses bounds from parent level. {@code false}
     *         otherwise.
     */
    public boolean matchParentBounds() {
        return getRequestedOverrideBounds().isEmpty();
        return getResolvedOverrideBounds().isEmpty();
    }

    /**
+25 −19
Original line number Diff line number Diff line
@@ -1902,12 +1902,14 @@ class Task extends WindowContainer<WindowContainer> {
        mTmpPrevBounds.set(getBounds());
        final boolean wasInMultiWindowMode = inMultiWindowMode();
        final boolean wasInPictureInPicture = inPinnedWindowingMode();
        final int oldOrientation = getOrientation();
        super.onConfigurationChanged(newParentConfig);
        // Only need to update surface size here since the super method will handle updating
        // surface position.
        updateSurfaceSize(getSyncTransaction());

        if (wasInPictureInPicture != inPinnedWindowingMode()) {
        final boolean pipChanging = wasInPictureInPicture != inPinnedWindowingMode();
        if (pipChanging) {
            mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, getStack());
        } else if (wasInMultiWindowMode != inMultiWindowMode()) {
            mStackSupervisor.scheduleUpdateMultiWindowMode(this);
@@ -1928,6 +1930,26 @@ class Task extends WindowContainer<WindowContainer> {
            }
        }

        if (pipChanging) {
            mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(true);
        }
        try {
            // We have 2 reasons why we need to report orientation change here.
            // 1. In some cases (e.g. freeform -> fullscreen) we don't have other ways of reporting.
            // 2. Report orientation as soon as possible so that the display can freeze earlier if
            // the display orientation will be changed. Because the surface bounds of activity
            // may have been set to fullscreen but the activity hasn't redrawn its content yet,
            // the rotation animation needs to capture snapshot earlier to avoid animating from
            // an intermediate state.
            if (oldOrientation != getOrientation()) {
                onDescendantOrientationChanged(null, this);
            }
        } finally {
            if (pipChanging) {
                mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(false);
            }
        }

        saveLaunchingStateIfNeeded();
        final boolean taskOrgChanged = updateTaskOrganizerState(false /* forceUpdate */);
        // If the task organizer has changed, then it will already be receiving taskAppeared with
@@ -2518,20 +2540,7 @@ class Task extends WindowContainer<WindowContainer> {
            return;
        }

        if (inStack.inFreeformWindowingMode()) {
            if (!isResizeable()) {
                throw new IllegalArgumentException("Can not position non-resizeable task="
                        + this + " in stack=" + inStack);
            }
            if (!matchParentBounds()) {
                return;
            }
            if (mLastNonFullscreenBounds != null) {
                setBounds(mLastNonFullscreenBounds);
            } else {
                mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
            }
        } else {
        if (!inStack.inFreeformWindowingMode()) {
            setBounds(inStack.getRequestedOverrideBounds());
        }
    }
@@ -3024,10 +3033,7 @@ class Task extends WindowContainer<WindowContainer> {
        if (displayContent == null) {
            return;
        }
        if (matchParentBounds()) {
            // TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a
            // problem once we move mBounds into WindowConfiguration.
            setBounds(null);
        if (getRequestedOverrideBounds().isEmpty()) {
            return;
        }
        final int displayId = displayContent.getDisplayId();
+18 −0
Original line number Diff line number Diff line
@@ -38,6 +38,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.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.policy.WindowManagerPolicy.USER_ROTATION_FREE;
@@ -957,6 +958,23 @@ public class TaskRecordTests extends ActivityTestsBase {
        assertEquals(SCREEN_ORIENTATION_UNSET, taskDisplayArea.getOrientation());
    }

    @Test
    public void testNotifyOrientationChangeCausedByConfigurationChange() {
        final Task task = getTestTask();
        final ActivityRecord activity = task.getTopMostActivity();
        final DisplayContent display = task.getDisplayContent();
        display.setWindowingMode(WINDOWING_MODE_FREEFORM);

        activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
        assertEquals(SCREEN_ORIENTATION_UNSET, task.getOrientation());
        verify(display).onDescendantOrientationChanged(any(), same(task));
        reset(display);

        display.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, task.getOrientation());
        verify(display).onDescendantOrientationChanged(any(), same(task));
    }

    private Task getTestTask() {
        final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
        return stack.getBottomMostTask();