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

Commit fe766df5 authored by Oleg Blinnikov's avatar Oleg Blinnikov
Browse files

Added OnSetRequestedOrientation callback

DisplayRotation disables Auto-Rotation for immersive applications.
But during the rotation of the device, application may change
the requested orientation by calling
ActivityRecord.setRequestedOrientation

This CL makes sure that onProposedRotationChanged gets reevaluated
if previously user was shown with the rotation button, and
then setRequestedOrientation being invoked by the application.

Bug: 275810916
Test: atest DisplayRotationTests ActivityRecordTests
Change-Id: I4fe6ef7716398047a757a5c761f316f6145d00b6
Merged-In: I4fe6ef7716398047a757a5c761f316f6145d00b6
parent 86305544
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -7867,6 +7867,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
                task.mTaskId, requestedOrientation);

        mDisplayContent.getDisplayRotation().onSetRequestedOrientation();
    }

    /*
+22 −0
Original line number Diff line number Diff line
@@ -92,6 +92,8 @@ public class DisplayRotation {
    // config changes and unexpected jumps while folding the device to closed state.
    private static final int FOLDING_RECOMPUTE_CONFIG_DELAY_MS = 800;

    private static final int ROTATION_UNDEFINED = -1;

    private static class RotationAnimationPair {
        @AnimRes
        int mEnter;
@@ -179,6 +181,12 @@ public class DisplayRotation {
     */
    private int mShowRotationSuggestions;

    /**
     * The most recent {@link Surface.Rotation} choice shown to the user for confirmation, or
     * {@link #ROTATION_UNDEFINED}
     */
    private int mRotationChoiceShownToUserForConfirmation = ROTATION_UNDEFINED;

    private static final int ALLOW_ALL_ROTATIONS_UNDEFINED = -1;
    private static final int ALLOW_ALL_ROTATIONS_DISABLED = 0;
    private static final int ALLOW_ALL_ROTATIONS_ENABLED = 1;
@@ -856,6 +864,7 @@ public class DisplayRotation {

    @VisibleForTesting
    void setUserRotation(int userRotationMode, int userRotation) {
        mRotationChoiceShownToUserForConfirmation = ROTATION_UNDEFINED;
        if (isDefaultDisplay) {
            // We'll be notified via settings listener, so we don't need to update internal values.
            final ContentResolver res = mContext.getContentResolver();
@@ -1545,6 +1554,17 @@ public class DisplayRotation {
        return shouldUpdateRotation;
    }

    /**
     * Called from {@link ActivityRecord#setRequestedOrientation(int)}
     */
    void onSetRequestedOrientation() {
        if (mCompatPolicyForImmersiveApps == null
                || mRotationChoiceShownToUserForConfirmation == ROTATION_UNDEFINED) {
            return;
        }
        mOrientationListener.onProposedRotationChanged(mRotationChoiceShownToUserForConfirmation);
    }

    void dump(String prefix, PrintWriter pw) {
        pw.println(prefix + "DisplayRotation");
        pw.println(prefix + "  mCurrentAppOrientation="
@@ -1786,9 +1806,11 @@ public class DisplayRotation {
            // Send interaction power boost to improve redraw performance.
            mService.mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, 0);
            if (isRotationChoiceAllowed(rotation)) {
                mRotationChoiceShownToUserForConfirmation = rotation;
                final boolean isValid = isValidRotationChoice(rotation);
                sendProposedRotationChangeToStatusBarInternal(rotation, isValid);
            } else {
                mRotationChoiceShownToUserForConfirmation = ROTATION_UNDEFINED;
                mService.updateRotation(false /* alwaysSendConfiguration */,
                        false /* forceRelayout */);
            }
+6 −0
Original line number Diff line number Diff line
@@ -588,12 +588,18 @@ public class ActivityRecordTests extends WindowTestsBase {
                throw new IllegalStateException("Orientation in new config should be either"
                        + "landscape or portrait.");
        }

        final DisplayRotation displayRotation = activity.mDisplayContent.getDisplayRotation();
        spyOn(displayRotation);

        activity.setRequestedOrientation(requestedOrientation);

        final ActivityConfigurationChangeItem expected =
                ActivityConfigurationChangeItem.obtain(newConfig);
        verify(mAtm.getLifecycleManager()).scheduleTransaction(eq(activity.app.getThread()),
                eq(activity.token), eq(expected));

        verify(displayRotation).onSetRequestedOrientation();
    }

    @Test
+37 −2
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import android.view.DisplayAddress;
import android.view.Surface;
import android.view.WindowManager;

import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;

import com.android.internal.util.test.FakeSettingsProvider;
@@ -126,6 +127,8 @@ public class DisplayRotationTests {

    private DeviceStateController mDeviceStateController;
    private DisplayRotation mTarget;
    @Nullable
    private DisplayRotationImmersiveAppCompatPolicy mDisplayRotationImmersiveAppCompatPolicyMock;

    @BeforeClass
    public static void setUpOnce() {
@@ -149,7 +152,7 @@ public class DisplayRotationTests {
        LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
        mMockStatusBarManagerInternal = mock(StatusBarManagerInternal.class);
        LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal);

        mDisplayRotationImmersiveAppCompatPolicyMock = null;
        mBuilder = new DisplayRotationBuilder();
    }

@@ -557,6 +560,38 @@ public class DisplayRotationTests {
        verify(mMockStatusBarManagerInternal).onProposedRotationChanged(Surface.ROTATION_90, true);
    }

    @Test
    public void testNotifiesChoiceWhenSensorUpdates_immersiveApp() throws Exception {
        mDisplayRotationImmersiveAppCompatPolicyMock = mock(
                DisplayRotationImmersiveAppCompatPolicy.class);
        when(mDisplayRotationImmersiveAppCompatPolicyMock.isRotationLockEnforced(
                Surface.ROTATION_90)).thenReturn(true);

        mBuilder.build();
        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);

        thawRotation();

        enableOrientationSensor();

        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
        assertTrue(waitForUiHandler());

        verify(mMockStatusBarManagerInternal).onProposedRotationChanged(Surface.ROTATION_90, true);

        // An imaginary ActivityRecord.setRequestedOrientation call disables immersive mode:
        when(mDisplayRotationImmersiveAppCompatPolicyMock.isRotationLockEnforced(
                Surface.ROTATION_90)).thenReturn(false);

        // And then ActivityRecord.setRequestedOrientation calls onSetRequestedOrientation.
        mTarget.onSetRequestedOrientation();

        // onSetRequestedOrientation should lead to a second call to
        // mOrientationListener.onProposedRotationChanged
        // but now, instead of notifying mMockStatusBarManagerInternal, it calls updateRotation:
        verify(sMockWm).updateRotation(false, false);
    }

    @Test
    public void testAllowAllRotations_allowsUpsideDownSuggestion()
            throws Exception {
@@ -1158,7 +1193,7 @@ public class DisplayRotationTests {
                @Override
                DisplayRotationImmersiveAppCompatPolicy initImmersiveAppCompatPolicy(
                        WindowManagerService service, DisplayContent displayContent) {
                    return null;
                    return mDisplayRotationImmersiveAppCompatPolicyMock;
                }
            };