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

Commit bbe25f59 authored by Chris Li's avatar Chris Li
Browse files

Only allow TaskDisplayArea to specify orientation if it is focused

(1/n Orientation on DisplayAreaGroup)

Record the last focused TDA and only allow it to specify orientation
if it is the last focused one on the logical display, so that when
there are multiple TDAs, we only respect the TDA with focus.

Bug: 155431879
Test: manual: test with fixed-orientation app
Test: atest WmTests:TaskRecordTests
Test: atest WmTests:TaskDisplayAreaTests
Change-Id: Ia574550368ce45a6e2c2f81b543adcfa4cf01ba1
parent bea44472
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -253,6 +253,12 @@
      "group": "WM_DEBUG_ORIENTATION",
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    "-1741065110": {
      "message": "No app is requesting an orientation, return %d for display id=%d",
      "level": "VERBOSE",
      "group": "WM_DEBUG_ORIENTATION",
      "at": "com\/android\/server\/wm\/DisplayContent.java"
    },
    "-1730156332": {
      "message": "Display id=%d rotation changed to %d from %d, lastOrientation=%d",
      "level": "VERBOSE",
@@ -1897,6 +1903,12 @@
      "group": "WM_ERROR",
      "at": "com\/android\/server\/wm\/WindowToken.java"
    },
    "845234215": {
      "message": "App is requesting an orientation, return %d for display id=%d",
      "level": "VERBOSE",
      "group": "WM_DEBUG_ORIENTATION",
      "at": "com\/android\/server\/wm\/DisplayContent.java"
    },
    "853091290": {
      "message": "Moved stack=%s behind stack=%s",
      "level": "DEBUG",
@@ -2167,12 +2179,6 @@
      "group": "WM_DEBUG_IME",
      "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
    },
    "1381227466": {
      "message": "App is requesting an orientation, return %d for display id=%d",
      "level": "VERBOSE",
      "group": "WM_DEBUG_ORIENTATION",
      "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
    },
    "1401295262": {
      "message": "Mode default, asking user",
      "level": "WARN",
@@ -2359,12 +2365,6 @@
      "group": "WM_DEBUG_RESIZE",
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    "1640436199": {
      "message": "No app is requesting an orientation, return %d for display id=%d",
      "level": "VERBOSE",
      "group": "WM_DEBUG_ORIENTATION",
      "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
    },
    "1653210583": {
      "message": "Removing app %s delayed=%b animation=%s animating=%b",
      "level": "VERBOSE",
+37 −1
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
@@ -465,6 +467,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     */
    ActivityRecord mFocusedApp = null;

    /** The last focused {@link TaskDisplayArea} on this display. */
    private TaskDisplayArea mLastFocusedTaskDisplayArea = null;

    /**
     * The launching activity which is using fixed rotation transformation.
     *
@@ -2328,7 +2333,21 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                return getLastOrientation();
            }
        }
        return super.getOrientation();

        final int orientation = super.getOrientation();
        if (orientation != SCREEN_ORIENTATION_UNSET && orientation != SCREEN_ORIENTATION_BEHIND) {
            ProtoLog.v(WM_DEBUG_ORIENTATION,
                    "App is requesting an orientation, return %d for display id=%d",
                    orientation, mDisplayId);
            return orientation;
        }

        ProtoLog.v(WM_DEBUG_ORIENTATION,
                "No app is requesting an orientation, return %d for display id=%d",
                getLastOrientation(), mDisplayId);
        // The next app has not been requested to be visible, so we keep the current orientation
        // to prevent freezing/unfreezing the display too early.
        return getLastOrientation();
    }

    void updateDisplayInfo() {
@@ -3203,6 +3222,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                throw new IllegalStateException(newFocus + " is not on " + getName()
                        + " but " + ((appDisplay != null) ? appDisplay.getName() : "none"));
            }

            // Called even if the focused app is not changed in case the app is moved to a different
            // TaskDisplayArea.
            setLastFocusedTaskDisplayArea(newFocus.getDisplayArea());
        }
        if (mFocusedApp == newFocus) {
            return false;
@@ -3215,6 +3238,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        return true;
    }

    /** Called when the focused {@link TaskDisplayArea} on this display may have changed. */
    @VisibleForTesting
    void setLastFocusedTaskDisplayArea(@Nullable TaskDisplayArea taskDisplayArea) {
        if (taskDisplayArea != null) {
            mLastFocusedTaskDisplayArea = taskDisplayArea;
        }
    }

    /** Gets the last focused {@link TaskDisplayArea} on this display. */
    TaskDisplayArea getLastFocusedTaskDisplayArea() {
        return mLastFocusedTaskDisplayArea;
    }

    /** Updates the layer assignment of windows on this display. */
    void assignWindowLayers(boolean setLayoutNeeded) {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "assignWindowLayers");
+13 −17
Original line number Diff line number Diff line
@@ -29,12 +29,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
@@ -645,6 +643,12 @@ final class TaskDisplayArea extends DisplayArea<Task> {

    @Override
    int getOrientation(int candidate) {
        // Only allow to specify orientation if this TDA has the focus.
        // TODO(b/155431879) Add option to never allow a TDA to specify orientation.
        if (!isLastFocused()) {
            return SCREEN_ORIENTATION_UNSET;
        }

        if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
            // Apps and their containers are not allowed to specify an orientation while using
            // root tasks...except for the home stack if it is not resizable and currently
@@ -671,21 +675,7 @@ final class TaskDisplayArea extends DisplayArea<Task> {
            return SCREEN_ORIENTATION_UNSPECIFIED;
        }

        final int orientation = super.getOrientation(candidate);
        if (orientation != SCREEN_ORIENTATION_UNSET
                && orientation != SCREEN_ORIENTATION_BEHIND) {
            ProtoLog.v(WM_DEBUG_ORIENTATION,
                    "App is requesting an orientation, return %d for display id=%d",
                    orientation, mDisplayContent.mDisplayId);
            return orientation;
        }

        ProtoLog.v(WM_DEBUG_ORIENTATION,
                "No app is requesting an orientation, return %d for display id=%d",
                mDisplayContent.getLastOrientation(), mDisplayContent.mDisplayId);
        // The next app has not been requested to be visible, so we keep the current orientation
        // to prevent freezing/unfreezing the display too early.
        return mDisplayContent.getLastOrientation();
        return super.getOrientation(candidate);
    }

    @Override
@@ -1880,6 +1870,12 @@ final class TaskDisplayArea extends DisplayArea<Task> {
        return lastReparentedStack;
    }

    /** Whether this task display area is the last focused one on this logical display. */
    @VisibleForTesting
    boolean isLastFocused() {
        return mDisplayContent.getLastFocusedTaskDisplayArea() == this;
    }

    @Override
    protected boolean isTaskDisplayArea() {
        return true;
+3 −0
Original line number Diff line number Diff line
@@ -318,6 +318,9 @@ public class SystemServicesTestRule implements TestRule {
        display.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN);
        spyOn(display);
        final TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();

        // Set the default focused TDA.
        display.setLastFocusedTaskDisplayArea(taskDisplayArea);
        spyOn(taskDisplayArea);
        final Task homeStack = taskDisplayArea.getStack(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+35 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -242,6 +243,40 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
        assertEquals(rootWindowContainer.getOrientation(), rootHomeTask.getOrientation());
    }

    @Test
    public void testIsLastFocused() {
        final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
        final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
                mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
                FEATURE_VENDOR_FIRST);
        final Task firstStack = firstTaskDisplayArea.createStack(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
        final Task secondStack = secondTaskDisplayArea.createStack(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
        final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
                .setStack(firstStack).build();
        final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setCreateTask(true)
                .setStack(secondStack).build();

        // Activity on TDA1 is focused
        mDisplayContent.setFocusedApp(firstActivity);

        assertThat(firstTaskDisplayArea.isLastFocused()).isTrue();
        assertThat(secondTaskDisplayArea.isLastFocused()).isFalse();

        // No focused app, TDA1 is still recorded as last focused.
        mDisplayContent.setFocusedApp(null);

        assertThat(firstTaskDisplayArea.isLastFocused()).isTrue();
        assertThat(secondTaskDisplayArea.isLastFocused()).isFalse();

        // Activity on TDA2 is focused
        mDisplayContent.setFocusedApp(secondActivity);

        assertThat(firstTaskDisplayArea.isLastFocused()).isFalse();
        assertThat(secondTaskDisplayArea.isLastFocused()).isTrue();
    }

    private void assertGetOrCreateStack(int windowingMode, int activityType, Task candidateTask,
            boolean reuseCandidate) {
        final TaskDisplayArea taskDisplayArea = candidateTask.getDisplayArea();
Loading