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

Commit c79f21db authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Defer orientation for transient launch with immersive app policy" into main

parents 5c9a7aec 4a445658
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -485,6 +485,9 @@ public class DisplayRotation {
            if (isDefaultDisplay) {
                updateOrientationListenerLw();
            }
        } else if (mCompatPolicyForImmersiveApps != null
                && mCompatPolicyForImmersiveApps.deferOrientationUpdate()) {
            return false;
        }
        return updateRotationUnchecked(forceUpdate);
    }
+34 −0
Original line number Diff line number Diff line
@@ -17,10 +17,13 @@
package com.android.server.wm;

import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;

import static com.android.server.policy.WindowManagerPolicy.USER_ROTATION_FREE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Configuration.Orientation;
@@ -65,6 +68,37 @@ final class DisplayRotationImmersiveAppCompatPolicy {
        mDisplayContent = displayContent;
    }

    /**
     * Returns {@code true} if the orientation update should be skipped and it will update when
     * transition is done. This is to keep the orientation which was preserved by
     * {@link #isRotationLockEnforced} from being changed by a transient launch (i.e. recents).
     */
    boolean deferOrientationUpdate() {
        if (mDisplayRotation.getUserRotation() != USER_ROTATION_FREE
                || mDisplayRotation.getLastOrientation() != SCREEN_ORIENTATION_UNSPECIFIED) {
            return false;
        }
        final WindowOrientationListener orientationListener =
                mDisplayRotation.getOrientationListener();
        if (orientationListener == null
                || orientationListener.getProposedRotation() == mDisplayRotation.getRotation()) {
            return false;
        }
        // The above conditions mean that isRotationLockEnforced might have taken effect:
        // Auto-rotation is enabled and the proposed rotation is not applied.
        // Then the update should defer until the transition idle to avoid disturbing animation.
        if (!mDisplayContent.mTransitionController.hasTransientLaunch(mDisplayContent)) {
            return false;
        }
        mDisplayContent.mTransitionController.mStateValidators.add(() -> {
            if (!isRotationLockEnforcedLocked(orientationListener.getProposedRotation())) {
                mDisplayContent.mWmService.updateRotation(false /* alwaysSendConfiguration */,
                        false /* forceRelayout */);
            }
        });
        return true;
    }

    /**
     * Decides whether it is necessary to lock screen rotation, preventing auto rotation, based on
     * the top activity configuration and proposed screen rotation.
+23 −0
Original line number Diff line number Diff line
@@ -20,16 +20,19 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;

import android.platform.test.annotations.Presubmit;
import android.view.Surface;
@@ -54,6 +57,7 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas

    private DisplayRotationImmersiveAppCompatPolicy mPolicy;

    private DisplayRotation mMockDisplayRotation;
    private AppCompatConfiguration mMockAppCompatConfiguration;
    private ActivityRecord mMockActivityRecord;
    private Task mMockTask;
@@ -98,6 +102,7 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas
        when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_90)).thenReturn(true);
        when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_180)).thenReturn(false);
        when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_270)).thenReturn(true);
        mMockDisplayRotation = mockDisplayRotation;

        return mockDisplayRotation;
    }
@@ -195,6 +200,24 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas
        assertIsRotationLockEnforcedReturnsFalseForAllRotations();
    }

    @Test
    public void testDeferOrientationUpdate() {
        assertFalse(mPolicy.deferOrientationUpdate());

        doReturn(SCREEN_ORIENTATION_UNSPECIFIED).when(mMockDisplayRotation).getLastOrientation();
        final WindowOrientationListener orientationListener = mock(WindowOrientationListener.class);
        doReturn(Surface.ROTATION_90).when(orientationListener).getProposedRotation();
        doReturn(orientationListener).when(mMockDisplayRotation).getOrientationListener();
        spyOn(mDisplayContent.mTransitionController);
        doReturn(true).when(mDisplayContent.mTransitionController)
                .hasTransientLaunch(mDisplayContent);

        assertTrue(mPolicy.deferOrientationUpdate());
        mDisplayContent.mTransitionController.mStateValidators.getFirst().run();

        verify(mWm).updateRotation(false, false);
    }

    @Test
    public void testRotationChoiceEnforcedOnly_nullTopRunningActivity_lockNotEnforced() {
        when(mDisplayContent.topRunningActivity()).thenReturn(null);