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
This commit is contained in:
Oleg Blinnikov
2023-04-03 16:06:25 +00:00
parent 8630554449
commit fe766df5e0
4 changed files with 67 additions and 2 deletions

View File

@@ -7867,6 +7867,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
task.mTaskId, requestedOrientation);
mDisplayContent.getDisplayRotation().onSetRequestedOrientation();
}
/*

View File

@@ -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 */);
}

View File

@@ -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

View File

@@ -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;
}
};