diff options
4 files changed, 67 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 2f7673a309a2..d872ada1fd0c 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -7867,6 +7867,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged( task.mTaskId, requestedOrientation); + + mDisplayContent.getDisplayRotation().onSetRequestedOrientation(); } /* diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 30791d3a3cd5..248d89b49a67 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -97,6 +97,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; @@ -184,6 +186,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; @@ -861,6 +869,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(); @@ -1568,6 +1577,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=" @@ -1966,9 +1986,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 */); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 2cc752cd1b1a..c91822279e7c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -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 diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java index 890e55b36194..131ff7b2ab04 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java @@ -68,6 +68,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; @@ -137,6 +138,8 @@ public class DisplayRotationTests { private DeviceStateController mDeviceStateController; private DisplayRotation mTarget; + @Nullable + private DisplayRotationImmersiveAppCompatPolicy mDisplayRotationImmersiveAppCompatPolicyMock; @BeforeClass public static void setUpOnce() { @@ -161,7 +164,7 @@ public class DisplayRotationTests { LocalServices.removeServiceForTest(StatusBarManagerInternal.class); mMockStatusBarManagerInternal = mock(StatusBarManagerInternal.class); LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal); - + mDisplayRotationImmersiveAppCompatPolicyMock = null; mBuilder = new DisplayRotationBuilder(); } @@ -574,6 +577,38 @@ public class DisplayRotationTests { } @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 { mBuilder.build(); @@ -1354,7 +1389,7 @@ public class DisplayRotationTests { @Override DisplayRotationImmersiveAppCompatPolicy initImmersiveAppCompatPolicy( WindowManagerService service, DisplayContent displayContent) { - return null; + return mDisplayRotationImmersiveAppCompatPolicyMock; } @Override |